Skip to content

Instantly share code, notes, and snippets.

@AyresMonteiro
Created July 30, 2022 16:32
Show Gist options
  • Save AyresMonteiro/ae83784e3412a2d0d54ef0b2e43cb2c3 to your computer and use it in GitHub Desktop.
Save AyresMonteiro/ae83784e3412a2d0d54ef0b2e43cb2c3 to your computer and use it in GitHub Desktop.
[nodejs module] Count commits
const { exec, spawn } = require("child_process");
function execPromise(command) {
return new Promise((resolve, reject) => {
exec(command, (err, stdout, stderr) => {
if (err) reject(err);
resolve({ stdout, stderr });
});
});
}
function pipedExecPromise(command, args, path) {
return new Promise((resolve, reject) => {
let stdOut = [];
let stdErr = [];
function stdoutAppend(data) {
stdOut.push(data.toString("utf8"));
}
function stderrAppend(data) {
stdErr.push(data.toString("utf8"));
}
let child = spawn(command, args, {
stdio: ["inherit", "pipe", "pipe"],
cwd: path,
});
child.stdout.on("data", stdoutAppend);
child.stderr.on("data", stderrAppend);
child.on("close", () => {
if (stdErr.length) {
reject({ stderr: stdErr.join("") });
return;
}
resolve({ stdout: stdOut.join("") });
});
});
}
async function getAuthors(path) {
const { stdout } = await pipedExecPromise(
"git",
"shortlog -sne".split(" "),
path
);
const baseEmails = stdout
.replace(/\n$/, "")
.split("\n")
.map((line) => line.replace(/^.+<(.+@.+)>$/, "$1"));
let emails = [];
baseEmails.forEach((email) => {
if (emails.find((e) => e === email)) {
return;
}
emails.push(email);
});
return emails;
}
async function countCommits(path, author) {
const command = `cd "${path}" && git rev-list "HEAD^1" --count ${
author ? "--author=" + author + " --regexp-ignore-case" : ""
}`;
const { stdout } = await execPromise(command);
return Number(stdout.replace(/\n$/, ""));
}
async function countCommitsByEmail(path) {
const authors = await getAuthors(path);
const results = await Promise.all(
authors.map((author) => countCommits(path, author))
);
return results.reduce((prev, curr, index) => {
prev[authors[index]] = curr;
return prev;
}, {});
}
module.exports = {
execPromise,
pipedExecPromise,
getAuthors,
countCommits,
countCommitsByEmail,
};
const path = require("path");
const { countCommitsByEmail } = require("./countCommits");
async function main() {
return await countCommitsByEmail(
path.resolve(__dirname, "../a/project")
);
}
main().then(console.log).catch(console.error);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment