调用 git shortlog -sn 时节点 child_process spawn 挂起

Node child_process spawn hangs when calling git shortlog -sn

我的场景

在我的节点应用程序中,我使用 child_process.spawn 从当前存储库中查询信息

我已经为 return 一个 promise 构建了一个小函数,该 promise 通过命令的响应解析:

const spawn = require('child_process').spawn;

const gitExec = command => (
  new Promise((resolve, reject) => {
    const thread = spawn('git', command);
    const stdOut = [];
    const stdErr = [];

    thread.stdout.on('data', (data) => {
      stdOut.push(data.toString('utf8'));
    });

    thread.stderr.on('data', (data) => {
      stdErr.push(data.toString('utf8'));
    });

    thread.on('close', () => {
      if (stdErr.length) {
        reject(stdErr.join(''));
        return;
      }
      resolve(stdOut.join());
    });
  })
);

module.exports = gitExec;

调用 git branch 工作正常:

gitExec(['branch'])
.then((branchInfo) => {
  console.log(branchInfo);
})

(如预期)导致

    * develop
      feature/forever
      feature/sourceconfig
      feature/testing
      master

根据我的理解,这证明我使用的方法确实有效。

当调用 git shortlog -sn 生成的进程时 "hangs" 并且没有解析任何东西

gitExec(['shortlog', '-sn'])
.then((shortlogInfo) => {
  console.log(shortlogInfo);
})

通过命令行调用 git shortlog -sn 我得到了预期的结果:

   154  Andreas Gack
    89  Some other dude
     6  Whoever else

我的(到目前为止不成功)尝试

使用 spawnSync(同时更改我的 gitExec 函数以适应同步方法)returns 一个记录的对象 - 所以该过程似乎实际上退出了 - 但相关的对象 output stdoutstderr 的 props 都是空的。
对象的status0表示命令执行成功

我读过关于必须在 spawn 选项中重新定义 maxBuffer 的内容,但是无论是将其设置为(荒谬的)高值还是非常小的值都不会对同步或异步方法产生影响.

shell 选项设置为 true 也不会对上述所有情况产生影响。

问题发生在我的 Win10x64 以及 MacOs 运行 节点 v6.9.x 或 7.x

同样调用别名git log --pretty=short不提供结果

我的实际问题

我觉得 git branchgit shortlog 这两个命令在内部以不同的方式处理它们的输出。

我很乐意在他们的 git 中心页面上创建一个问题,但实际上我不知道如何确定该问题的实际根本原因。

非常感谢任何进一步的输入!

git shortlog 认为它需要从 stdin 中读取一些东西,这就是整个过程挂起的原因。要解决此问题,您可以将 stdin 作为选项从主进程传递,并像往常一样通过管道传递其他所有内容。那么它应该 运行.

const spawn = require('child_process').spawn;

const gitExec = command => (
  new Promise((resolve, reject) => {
    const thread = spawn('git', command, { stdio: ['inherit', 'pipe', 'pipe'] });
    const stdOut = [];
    const stdErr = [];

    thread.stdout.on('data', (data) => {
      stdOut.push(data.toString('utf8'));
    });

    thread.stderr.on('data', (data) => {
      stdErr.push(data.toString('utf8'));
    });

    thread.on('close', () => {
      if (stdErr.length) {
        reject(stdErr.join(''));
        return;
      }
      resolve(stdOut.join());
    });
  })
);

module.exports = gitExec;

也许来自 git documentation 的更多上下文:

If no revisions are passed on the command line and either standard input is not a terminal or there is no current branch, git shortlog will output a summary of the log read from standard input, without reference to the current repository.

生成子进程时就是这种情况。所以它期望通过 stdin 传递一些东西。通过设置 stdin 到主进程 git shortlog 知道终端,因此将 运行.

我通过指定提交之前和之后的哈希来让它工作。

git shortlog -sn `git log --pretty=format:'%H' --reverse | head -1` `git log --pretty=format:'%H' | head -1`"