From 347d8616296137348b4df476ca142c316ee653c7 Mon Sep 17 00:00:00 2001 From: Rod Vagg Date: Mon, 14 Oct 2019 22:18:46 +1100 Subject: [PATCH] replace bash subcommands with separate shell spawns --- .github/workflows/test.yml | 3 +- changelog-maker.js | 146 ++++++++++++++++++++++++++----------- package-lock.json | 53 +++++--------- package.json | 2 +- 4 files changed, 127 insertions(+), 77 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 43638b6..38ebde8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,8 +11,7 @@ jobs: strategy: fail-fast: false matrix: - # switch to `8` when https://github.com/actions/setup-node/issues/27 is fixed - node: [8.16.1, 10, 12] + node: [10, 12] os: [ubuntu-latest, windows-latest] steps: diff --git a/changelog-maker.js b/changelog-maker.js index f65e9e8..053bdf6 100755 --- a/changelog-maker.js +++ b/changelog-maker.js @@ -4,6 +4,8 @@ const fs = require('fs') const path = require('path') +const promisify = require('util').promisify +const pipeline = promisify(require('stream').pipeline) const split2 = require('split2') const list = require('list-stream') const stripAnsi = require('strip-ansi') @@ -12,7 +14,7 @@ const commitStream = require('commit-stream') const gitexec = require('gitexec') const commitToOutput = require('./commit-to-output') const groupCommits = require('./group-commits') -const collectCommitLabels = require('./collect-commit-labels') +const collectCommitLabels = promisify(require('./collect-commit-labels')) // TODO const { isReleaseCommit } = require('./groups') const pkg = require('./package.json') const debug = require('debug')(pkg.name) @@ -30,15 +32,17 @@ const ghId = { user: argv._[0] || pkgId.user || 'nodejs', repo: argv._[1] || (pkgId.name && stripScope(pkgId.name)) || 'node' } -const gitcmd = 'git log --pretty=full --since="{{sincecmd}}" --until="{{untilcmd}}"' -const commitdatecmd = '$(git show -s --format=%cd `{{refcmd}}`)' -const untilcmd = '' -const refcmd = argv.a || argv.all ? 'git rev-list --max-parents=0 HEAD' : 'git rev-list --max-count=1 {{ref}}' -const defaultRef = '--tags=v*.*.* 2> /dev/null ' + - '|| git rev-list --max-count=1 --tags=*.*.* 2> /dev/null ' + - '|| git rev-list --max-count=1 HEAD' - -debug(ghId) +const gitcmd = 'git log --pretty=full --since="{{since}}" --until="{{until}}"' +const commitdatecmd = 'git show -s --format=%cd {{ref}}' +const refCmd = 'git rev-list --max-count=1 {{ref}}' +const allRefCmd = 'git rev-list --max-parents=0 HEAD' +const startRefGuessCmd = [ + 'git rev-list --max-count=1 --tags=v*.*.*', + 'git rev-list --max-count=1 --tags=*.*.*', + 'git rev-list --max-count=1 HEAD' +] + +debug('using id:', ghId) if (help) { showUsage() @@ -103,45 +107,105 @@ function printCommits (list) { process.stdout.write(out) } -function onCommitList (err, list) { +async function processCommitList (list) { + list = organiseCommits(list) + + await collectCommitLabels(list) + + if (argv.group) { + list = groupCommits(list) + } + + list = list.map((commit) => commitToOutput(commit, simple, ghId, commitUrl)) + + if (!quiet) { + printCommits(list) + } +} + +async function runGit (cmd, isCommitList) { + const ge = gitexec.exec(process.cwd(), cmd) + const streams = [ge, split2()] + if (isCommitList) { + streams.push(commitStream(ghId.user, ghId.repo)) + } + + // awkward callback construction is required because list.obj() rolls up + // the stream into an array provided to the callback, but we want to use + // stream.pipeline() to do a nice error-forwarding & cleanup pipeline + let err, data + streams.push(list.obj((_err, _data) => { + err = _err + data = _data + })) + + await pipeline(streams) + + // we land here _after_ the callback to list.obj() so `err` and `data` should be populated if (err) { throw err } - list = organiseCommits(list) + return data +} - collectCommitLabels(list, (err) => { - if (err) { - throw err +async function guessStartRef () { + for (const cmd of startRefGuessCmd) { + debug('guessing startRef with:', cmd) + const startRef = (await runGit(cmd))[0] + if (startRef) { + return startRef } + } - if (argv.group) { - list = groupCommits(list) - } + throw new Error(`Unexpected error finding default start ref, \`${startRefGuessCmd[startRefGuessCmd.length - 1]}\` didn't even work`) +} - list = list.map((commit) => { - return commitToOutput(commit, simple, ghId, commitUrl) - }) +async function findStartDate () { + let cmd + let startRef - if (!quiet) { - printCommits(list) - } - }) + if (argv.a || argv.all) { + cmd = allRefCmd + } else if (argv['start-ref']) { + cmd = replace(refCmd, { ref: argv['start-ref'] }) + } + + if (cmd) { + debug('startRef command: %s', cmd) + startRef = (await runGit(cmd))[0] + } else { + startRef = await guessStartRef() + } + + cmd = replace(commitdatecmd, { ref: startRef }) + debug('converting ref to date:', cmd) + return (await runGit(cmd))[0] +} + +async function findEndDate () { + if (!argv['end-ref']) { + debug('using blank endRef') + return '' // --until='' + } + let cmd = replace(refCmd, { ref: argv['end-ref'] }) + debug('endRef command: %s', cmd) + const endRef = (await runGit(cmd))[0] + cmd = replace(commitdatecmd, { ref: endRef }) + debug('converting ref to date:', cmd) + return (await runGit(cmd))[0] +} + +async function run () { + const [startDate, endDate] = await Promise.all([findStartDate(), findEndDate()]) + + const cmd = replace(gitcmd, { since: startDate, until: endDate }) + debug('executing:', cmd) + const commits = await runGit(cmd, true) + return processCommitList(commits) } -const _startrefcmd = replace(refcmd, { ref: argv['start-ref'] || defaultRef }) -const _endrefcmd = argv['end-ref'] && replace(refcmd, { ref: argv['end-ref'] }) -const _sincecmd = replace(commitdatecmd, { refcmd: _startrefcmd }) -const _untilcmd = argv['end-ref'] ? replace(commitdatecmd, { refcmd: _endrefcmd }) : untilcmd -const _gitcmd = replace(gitcmd, { sincecmd: _sincecmd, untilcmd: _untilcmd }) - -debug('%s', _startrefcmd) -debug('%s', _endrefcmd) -debug('%s', _sincecmd) -debug('%s', _untilcmd) -debug('%s', _gitcmd) - -gitexec.exec(process.cwd(), _gitcmd) - .pipe(split2()) - .pipe(commitStream(ghId.user, ghId.repo)) - .pipe(list.obj(onCommitList)) +run().catch((err) => { + console.error(err) + process.exit(1) +}) diff --git a/package-lock.json b/package-lock.json index 7de118c..3b9ca4b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,9 +31,9 @@ "dev": true }, "acorn-jsx": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.2.tgz", - "integrity": "sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", + "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", "dev": true }, "ajv": { @@ -876,43 +876,30 @@ } }, "gitexec": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gitexec/-/gitexec-1.0.0.tgz", - "integrity": "sha1-rFicoxd6mUJ0Zao3sfgXF2weNCI=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/gitexec/-/gitexec-2.0.1.tgz", + "integrity": "sha512-GH5WDye/Rewj74Rvp8RaezLcWM1ot7IQjZEA9/M/fIIsLWYAw2OBviOnJ85bUQXMSR+tfpZWtulhE+LtOqlxMA==", "requires": { - "bl": "~1.0.0" + "bl": "^4.0.0" }, "dependencies": { "bl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.0.3.tgz", - "integrity": "sha1-/FQhoo/UImA2w7OJGmaiW8ZNIm4=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.0.tgz", + "integrity": "sha512-QwQvAZZA1Bw1FWnhNj2X5lu+sPxxB2ITH3mqEqYyahN6JZR13ONjk+XiTnBaGEzMPUrAgOkaD68pBH1rvPRPsw==", "requires": { - "readable-stream": "~2.0.5" + "readable-stream": "^3.4.0" } }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" - }, "readable-stream": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", + "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "string_decoder": "~0.10.x", - "util-deprecate": "~1.0.1" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" } } }, @@ -972,9 +959,9 @@ "dev": true }, "hosted-git-info": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.4.tgz", - "integrity": "sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ==", + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", + "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==", "dev": true }, "hyperquest": { diff --git a/package.json b/package.json index 9cf3eee..5572d0e 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "debug": "^4.1.1", "ghauth": "^3.2.1", "ghissues": "^1.1.3", - "gitexec": "^1.0.0", + "gitexec": "^2.0.1", "list-stream": "^1.0.1", "minimist": "^1.2.0", "pkg-to-id": "0.0.3",