diff options
| -rwxr-xr-x | compare-master-to-stable.js | 163 | ||||
| -rw-r--r-- | package.json | 4 | 
2 files changed, 166 insertions, 1 deletions
| 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); +}); + diff --git a/package.json b/package.json index 8cc184cb..2cc6daf4 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,9 @@      "grunt-ddescribe-iit": "~0.0.1",      "grunt-merge-conflict": "~0.0.1",      "promises-aplus-tests": "~1.3.2", -    "grunt-shell": "~0.3.1" +    "grunt-shell": "~0.3.1", +    "semver": "~2.1.0", +    "lodash": "~1.3.1"    },    "licenses": [      { | 
