Skip to content

Instantly share code, notes, and snippets.

@rolandcrosby
Created November 21, 2019 02:47
Show Gist options
  • Save rolandcrosby/bb11a1fe652296ba5914cb1244f27014 to your computer and use it in GitHub Desktop.
Save rolandcrosby/bb11a1fe652296ba5914cb1244f27014 to your computer and use it in GitHub Desktop.
const childProcess = require("child_process");
function gitCmd(args) {
const cmd = childProcess.spawnSync("/usr/local/bin/git", args);
return cmd.stdout.toString().split("\n");
}
function commitsForPath(path) {
return gitCmd(["rev-list", "--format=oneline", "--all", path])
.map(x => [x.substr(0, 40), x.substr(41)])
.reverse();
}
function diffs(commits) {
const out = [];
for (var i = 0; i < commits.length - 1; i++) {
const changes = diff(commits[i][0], commits[i + 1][0]);
if (changes.changeCount > 0) {
out.push({
commit: commits[i + 1][0],
message: commits[i + 1][1],
...changes
});
}
}
return out;
}
function diff(hash1, hash2) {
let changes = gitCmd(["diff", "-U0", `${hash1}..${hash2}`, "words"]).filter(
l => l.match(/^[+-]([A-z0-9_-])+$/)
);
let additions = new Set(
changes.filter(l => l[0] == "+").map(l => l.substr(1))
);
let removals = new Set(
changes.filter(l => l[0] == "-").map(l => l.substr(1))
);
let netAdditions = setDifference(additions, removals);
let netRemovals = setDifference(removals, additions);
return {
changeCount: netAdditions.size + netRemovals.size,
removals: Array.from(netRemovals),
additions: Array.from(netAdditions),
moves: Array.from(setIntersection(additions, removals))
};
}
function setDifference(a, b) {
const difference = new Set(a);
for (let el of b) {
difference.delete(el);
}
return difference;
}
function setIntersection(a, b) {
const intersection = new Set();
for (let el of a) {
if (b.has(el)) {intersection.add(el)}
}
return intersection;
}
// usage: node diff.js | jq '.[] | select(.removals | length > 0) | select(.removals | length < 100) | {commit: .commit, message: .message, removals: .removals}'
console.log(JSON.stringify(diffs(commitsForPath(process.argv[2] || 'words')), null, 2));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment