From cf0e6f360962abe62f1f49b0226b234e54adcff1 Mon Sep 17 00:00:00 2001 From: Brian Ford Date: Fri, 9 Aug 2013 17:26:07 -0700 Subject: chore(release): add script for comparing master and stable branches --- compare-master-to-stable.js | 163 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100755 compare-master-to-stable.js (limited to 'compare-master-to-stable.js') diff --git a/compare-master-to-stable.js b/compare-master-to-stable.js new file mode 100755 index 00000000..404383b0 --- /dev/null +++ b/compare-master-to-stable.js @@ -0,0 +1,163 @@ +#!/usr/local/bin/node + +var util = require('util'); +var cp = require('child_process'); + +var Q = require('q'); +var _ = require('lodash'); +var semver = require('semver'); + +var exec = function (cmd) { + return function () { + var args = Array.prototype.slice.call(arguments, 0); + args.unshift(cmd); + var fullCmd = util.format.apply(util, args); + return Q.nfcall(cp.exec, fullCmd).then(function (out) { + return out[0].split('\n'); + }); + }; +}; + +var andThen = function (fn, after) { + return function () { + return fn.apply(this, arguments).then(after); + }; +}; + +var oneArg = function (fn) { + return function (arg) { + return fn(arg); + }; +}; + +var oneLine = function (lines) { + return lines[0].trim(); +}; + +var noArgs = function (fn) { + return function () { + return fn(); + }; +}; + +var identity = function (i) { return i; }; + +// like Q.all, but runs the comands in series +// useful for ensuring env state (like which branch is checked out) +var allInSeries = function (fn) { + return function (args) { + var results = []; + var def; + while (args.length > 0) { + (function (arg) { + if (def) { + def = def.then(function () { + return fn(arg); + }); + } else { + def = fn(arg); + } + def = def.then(function (res) { + results.push(res); + }); + }(args.pop())); + } + return def.then(function () { + return results; + }); + }; +}; + +var compareBranches = function (left, right) { + console.log('# These commits are in ' + left.name + ' but not in ' + right.name + '\n'); + console.log(_(left.log). + difference(right.log). + map(function (line) { + return left.full[left.log.indexOf(line)]; // lol O(n^2) + }). + value(). + join('\n')); +}; + +var checkout = oneArg(exec('git checkout %s')); + +var getCurrentBranch = andThen(noArgs(exec('git rev-parse --abbrev-ref HEAD')), oneLine); +var getTags = noArgs(exec('git tag')); +var getShaOfTag = oneArg(exec('git rev-list %s | head -n 1')); +var getTheLog = oneArg(exec('git log --pretty=oneline %s..HEAD | cat')); + +// remember this so we can restore state +var currentBranch; + +getCurrentBranch(). +then(function (branch) { + currentBranch = branch; +}). +then(getTags). +then(function (tags) { + return tags. + filter(semver.valid). + map(semver.clean). + sort(semver.rcompare); +}). +then(function (tags) { + var major = tags[0].split('.')[0] + '.x'; + return tags. + filter(function (ver) { + return semver.satisfies(ver, major); + }); +}). +then(function (tags) { + return _(tags). + groupBy(function (tag) { + return tag.split('.')[1]; + }). + map(function (group) { + return _.first(group); + }). + map(function (tag) { + return 'v' + tag; + }). + value(); +}). +then(function (tags) { + return [ + { name: 'v1.0.x', tag: tags[0] }, + { name: 'master', tag: tags[1] } + ]; +}). +then(allInSeries(function (branch) { + return checkout(branch.name). + then(function () { + return getTheLog(branch.tag); + }). + then(function (log) { + return log. + filter(identity); + }). + then(function (log) { + branch.full = log.map(function (line) { + line = line.split(' '); + var sha = line.shift(); + var msg = line.join(' '); + return sha + (msg.toLowerCase().indexOf('fix') === -1 ? ' ' : ' * ') + msg; + }); + branch.log = log.map(function (line) { + return line.substr(41) + }); + return branch; + }); +})). +then(function (pairs) { + compareBranches(pairs[0], pairs[1]); + console.log('\n'); + compareBranches(pairs[1], pairs[0]); + return pairs; +}). +then(function () { + return checkout(currentBranch); +}). +catch(function (e) { + console.log(e.stack); +}); + -- cgit v1.2.3