From f0e1816c6c97fc335a4be86e7b3b47897007f420 Mon Sep 17 00:00:00 2001 From: Alexey Orlenko Date: Sun, 26 Feb 2017 20:32:53 +0200 Subject: [PATCH] tools: generate authors list automatically * Add new `update-authors.js` tool that traverses commit history using `git log` and creates authors list. * Decouple common functions into a module shared between tools. * Add `.mailmap` file. This file is automatically parsed by Git so that `git log --format='%aN <%aE>'` won't show duplicate entries in case something was committed with misconfigured Git. E.g., without this file @tshemsedinov appears twice in the list, as Timur Shemsedinov and as tshemsedinov, but with mailmap applied Git automatically coalesces these entries to use the full name only. This file now includes the active collaborators (@tshemsedinov for a reason and @aqrln and @belochub just in case), proper names and emails of contributors who committed with invalid ones should be placed here. PR-URL: https://github.com/metarhia/JSTP/pull/88 --- .mailmap | 3 +++ tools/common.js | 27 +++++++++++++++++++++++++++ tools/prepare-release.js | 24 ++---------------------- tools/update-authors.js | 22 ++++++++++++++++++++++ 4 files changed, 54 insertions(+), 22 deletions(-) create mode 100644 .mailmap create mode 100644 tools/common.js create mode 100755 tools/update-authors.js diff --git a/.mailmap b/.mailmap new file mode 100644 index 00000000..c68926c1 --- /dev/null +++ b/.mailmap @@ -0,0 +1,3 @@ +Timur Shemsedinov +Alexey Orlenko +Mykola Bilochub diff --git a/tools/common.js b/tools/common.js new file mode 100644 index 00000000..876a357a --- /dev/null +++ b/tools/common.js @@ -0,0 +1,27 @@ +// Common utilities used by tools +'use strict'; + +const childProcess = require('child_process'); +const fs = require('fs'); + +const common = {}; +module.exports = common; + +common.getCommandOutput = (cmd) => { + const exec = common.promisify(childProcess.exec); + return exec(cmd).then((stdout, stderr) => { + if (stderr) console.error(stderr); + return stdout; + }); +}; + +common.promisify = (fn) => (...args) => ( + new Promise((resolve, reject) => { + fn(...args, (error, ...result) => { + if (error) reject(error); + else resolve(...result); + }); + }) +); + +common.writeFile = common.promisify(fs.writeFile); diff --git a/tools/prepare-release.js b/tools/prepare-release.js index c8e11c20..eacc53ba 100755 --- a/tools/prepare-release.js +++ b/tools/prepare-release.js @@ -2,11 +2,11 @@ 'use strict'; -const childProcess = require('child_process'); -const fs = require('fs'); const https = require('https'); const path = require('path'); +const { getCommandOutput, writeFile } = require('./common'); + const commandName = path.relative('.', __filename); const help = `\ This tool allows to filter the result of @@ -83,14 +83,6 @@ getCommandOutput('git cherry ' + branch).then((cherryOut) => { process.exit(1); }); -function getCommandOutput(cmd) { - const exec = promisify(childProcess.exec); - return exec(cmd).then((stdout, stderr) => { - if (stderr) console.error(stderr); - return stdout; - }); -} - function getMetadata(commitHash) { const command = 'git log --format="%aN%n%B" -n 1 ' + commitHash; return getCommandOutput(command).then((output) => { @@ -188,17 +180,6 @@ function getStreamData(stream, callback) { stream.on('error', callback); } -function promisify(fn) { - return (...args) => ( - new Promise((resolve, reject) => { - fn(...args, (error, ...result) => { - if (error) reject(error); - else resolve(...result); - }); - }) - ); -} - function processCommits(commits) { commits = filterCommits(commits, maxLevel); @@ -233,7 +214,6 @@ function processCommits(commits) { script += '\n'; - const writeFile = promisify(fs.writeFile); return Promise.all([ writeFile(`${branch}-apply-commits.sh`, script), writeFile(`${branch}-commits.md`, changelog) diff --git a/tools/update-authors.js b/tools/update-authors.js new file mode 100755 index 00000000..c4ae6f09 --- /dev/null +++ b/tools/update-authors.js @@ -0,0 +1,22 @@ +#!/usr/bin/env node + +'use strict'; + +const path = require('path'); +const { getCommandOutput, writeFile } = require('./common'); + +const AUTHORS_PATH = path.resolve(__dirname, '..', 'AUTHORS'); + +getCommandOutput('git log --reverse --format="%aN <%aE>"').then((out) => { + const authors = []; + for (const author of out.split('\n')) { + if (!authors.includes(author)) { + authors.push(author); + } + } + return writeFile(AUTHORS_PATH, authors.join('\n')); +}).catch((error) => { + const message = error.stack || error.toString(); + console.error(message); + process.exit(1); +});