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

时间:2017-06-08 15:01:18

标签: node.js git command-line-interface child-process spawn

我的场景

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

我已经构建了一个小函数来返回一个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生成的进程“挂起”并且无法解决时

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

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

   154  Andreas Gack
    89  Some other dude
     6  Whoever else

我的(迄今为止不成功)尝试

使用spawnSync(同时更改我的gitExec函数以修改同步方法)返回一个记录的对象 - 因此该过程似乎实际退出 - 但对象的相关道具output {{1 }和stdout都是空的 对象的stderrstatus,表示成功执行的命令

我已经读过必须在spawn选项中重新定义0,但是既不将它设置为(荒谬的)高值也不是非常小的值确实会对同步或异步方法产生影响。< / p>

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

问题出现在我的Win10x64以及运行节点v6.9.x或7.x的MacO上

同样调用别名true不会提供结果

我的实际问题

  • 是否有人通过child_process.spawn成功查询git log --pretty=short
  • 有没有人知道Node的模块,它允许查询当前的本地git-repository?

我不知何故认为两个命令git shortlog -sngit branch在内部以不同的方式处理它们的输出。

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

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

2 个答案:

答案 0 :(得分:9)

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的更多背景信息:

  

如果命令行没有传递任何修订,并且标准输入不是终端或者没有当前分支,git shortlog将输出从标准输入读取的日志摘要,而不引用到当前的存储库。

在生成子进程时会出现这种情况。所以它希望通过stdin传递一些东西。通过将stdin设置为主进程git shortlog,可以了解终端,因此将运行。

答案 1 :(得分:0)

我通过指定提交哈希之前和之后使其工作。

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