Created
November 21, 2019 02:47
-
-
Save rolandcrosby/bb11a1fe652296ba5914cb1244f27014 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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