2

According to the docs you can promisify NodeJS' require('child_process').exec by doing the following:

const util = require('util');
const exec = util.promisify(require('child_process').exec);

async function lsExample() {
  const { stdout, stderr } = await exec('ls');
  console.log('stdout:', stdout);
  console.error('stderr:', stderr);
}
lsExample();

However when I use this approach in a 'prepare-commit-msg' git hook to get the current branch name, the stdout constant is a promise object, not the branch name value as I'd expect. Am I missing something?

const util = require('util');
const stdExec = require('child_process').exec;
const exec = util.promisify(stdExec);

async function getBranchName() {
  const { err, stdout, stderr } = await exec('git rev-parse --abbrev-ref HEAD');

  console.log(err, stdout, stderr); // Returns correct stdout

  if (err) {
    // "git branch" will fail if initial commit hasn't been done, in that case, skip this hook
    process.exit(0);
  }

  return stdout;
}

function validateBranchName(name) {
    console.log(name);
)

// Call get branchName
if(condition) {
    const branchName = getBranchName(); // branchName is promise object

    validateBranchName(branchName);
}
Antfish
  • 1,313
  • 2
  • 22
  • 41
  • The `console.log` call should log `undefined somestring ` (the third argument is a blank string) — does it not do that? If I execute this, the return value of the function is a Promise that resolves to a string, as expected: `getBranchName().then(console.log)` – RickN May 13 '20 at 11:48
  • I've expanded the example, so it is clearer as to the problem. You are indeed right, it does return `undefined my-branch-name` but when `getBranchName()` is called it is a promise object not the value. As you mentioned it does work if you use .then() but I thought that since I was awaiting the stdout value, that it should pause execution until this is resolved and then return it? – Antfish May 13 '20 at 13:27
  • If you are not on old node versions, you can use ```child .execSync("git rev-parse --abbrev-ref HEAD") .toString("utf-8");``` – agenthunt May 13 '20 at 13:30

1 Answers1

0

I fixed this by refactoring where the function was being called into another async function:

const util = require('util');
const stdExec = require('child_process').exec;
const exec = util.promisify(stdExec);

async function getBranchName() {
  const { err, stdout, stderr } = await exec('git rev-parse --abbrev-ref HEAD');

  console.log(err, stdout, stderr);

  if (err) {
    // "git branch" will fail if initial commit hasn't been done, in that case, skip this hook
    process.exit(0);
  }

  return stdout;
}

function validateBranchName(name) {
    console.log(name);
)

function async prepareCommitMsg() {
    const branchName = await getBranchName();

    validateBranchName(branchName);
}

// Call get branchName
if(condition) {
    prepareCommitMsg().then(() => {console.log('DONE!')});
}
Antfish
  • 1,313
  • 2
  • 22
  • 41