Skip to content

Instantly share code, notes, and snippets.

@kotarou3
Last active March 18, 2016 11:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kotarou3/c99362a362608ed822ed to your computer and use it in GitHub Desktop.
Save kotarou3/c99362a362608ed822ed to your computer and use it in GitHub Desktop.
#!/usr/bin/nodejs
"use strict";
require("prfun/smash");
const co = require("co");
const execFile = Promise.guard(
require("os").cpus().length + 1,
(cmd, args) => require("mz/child_process").execFile(cmd, args, {maxBuffer: 100 * 1024 * 1024})
);
const fs = require("mz/fs");
co(function* () {
if (process.argv.length < 3) {
console.warn(`Usage: ${process.argv[1]} [-l <load hash to commits cache>] [-s <save hash to commits cache>] [-L <arguments to git-log>]... <hashes>...`);
process.exit(1);
}
const args = require("minimist")(process.argv.slice(2));
args.L = Array.isArray(args.L) ? args.L : (args.L ? [args.L] : []);
const hashToCommits = new Map();
if (args.l) {
yield new Promise(function (resolve, reject) {
require("readline").createInterface({input: fs.createReadStream(args.l)})
.on("line", function (line) {
const pair = JSON.parse(line);
hashToCommits.set(pair[0], pair[1]);
})
.on("close", resolve)
.on("error", reject);
});
} else {
console.warn("Building hash to commits map...");
const lsTrees = [];
for (const commitLine of (yield execFile("git", ["log", "--pretty=format:%H %T %ct %s"].concat(args.L))).toString().split("\n")) {
const commitMatch = commitLine.match(/^([a-z0-9]{40}) ([a-z0-9]{40}) ([0-9]+) (.*)$/);
if (!commitMatch)
continue;
const commit = {
hash: commitMatch[1],
tree: commitMatch[2],
date: commitMatch[3],
desc: commitMatch[4],
};
lsTrees.push(co(function* () {
for (const line of (yield execFile("git", ["ls-tree", "-r", commit.hash])).toString().split("\n")) {
const hash = line.match(/^[0-9]{6} blob ([a-z0-9]{40})\b/);
if (!hash)
continue;
let commits = hashToCommits.get(hash[1]);
if (!commits)
hashToCommits.set(hash[1], commits = new Set())
commits.add(commit);
}
}));
}
yield Promise.all(lsTrees);
if (args.s) {
const out = fs.createWriteStream(args.s);
for (const pair of hashToCommits) {
out.write(JSON.stringify([pair[0], Array.from(pair[1])]));
out.write("\n");
}
}
}
console.warn("Finding hashes...");
const foundCommits = new Map();
for (const hash of args._) {
const commits = hashToCommits.get(hash);
if (!commits)
continue;
for (const commit of commits) {
let foundCommit = foundCommits.get(commit.hash);
if (!foundCommit)
foundCommits.set(commit.hash, foundCommit = {commit: commit, count: 0});
++foundCommit.count;
}
}
console.log(
Array.from(foundCommits)
.sort((a, b) => (a[1].count - b[1].count) || (b[1].commit.date - a[1].commit.date))
.map(pair => `${pair[1].count} ${pair[1].commit.hash} ${pair[1].commit.desc}`)
.join("\n")
);
}).done();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment