diff --git a/__tests__/git.spec.js b/__tests__/git.spec.js index 810f4e9f..73c46a82 100644 --- a/__tests__/git.spec.js +++ b/__tests__/git.spec.js @@ -276,6 +276,43 @@ describe('Git', function() { ); }); + describe('RevList', function() { + + it('requires at least 1 argument', function() { + runCommand('git rev-list', function(commandMsg) { + expect(commandMsg).toContain('at least 1'); + }); + }); + + describe('supports', function() { + var SETUP = 'git co -b left C0; gc; git merge master; git co -b right C0; gc; git merge master; git co -b all left; git merge right; '; + + it('single included revision', function() { + runCommand(SETUP + 'git rev-list all', function(commandMsg) { + expect(commandMsg).toBe('C6\nC5\nC4\nC3\nC2\nC1\nC0\n'); + }); + }); + + it('single excluded revision', function() { + runCommand(SETUP + 'git rev-list all ^right', function(commandMsg) { + expect(commandMsg).toBe('C6\nC3\nC2\n'); + }); + }); + + it('multiple included revisions', function() { + runCommand(SETUP + 'git rev-list right left', function(commandMsg) { + expect(commandMsg).toBe('C5\nC4\nC3\nC2\nC1\nC0\n'); + }); + }); + + it('multiple excluded revisions', function() { + runCommand(SETUP + 'git rev-list all ^right ^left', function(commandMsg) { + expect(commandMsg).toBe('C6\n'); + }); + }); + }); + }); + describe('Log supports', function() { var SETUP = 'git co -b left C0; gc; git merge master; git co -b right C0; gc; git merge master; git co -b all left; git merge right; '; diff --git a/src/js/git/commands.js b/src/js/git/commands.js index 4c083d5e..83e21e80 100644 --- a/src/js/git/commands.js +++ b/src/js/git/commands.js @@ -574,6 +574,18 @@ var commandConfig = { } }, + revlist: { + dontCountForGolf: true, + displayName: 'rev-list', + regex: /^git +rev-list($|\s)/, + execute: function(engine, command) { + var generalArgs = command.getGeneralArgs(); + command.validateArgBounds(generalArgs, 1); + + engine.revlist(generalArgs); + } + }, + log: { dontCountForGolf: true, regex: /^git +log($|\s)/, diff --git a/src/js/git/index.js b/src/js/git/index.js index d03a2075..ff811f8e 100644 --- a/src/js/git/index.js +++ b/src/js/git/index.js @@ -2740,6 +2740,20 @@ GitEngine.prototype.logWithout = function(ref, omitBranch) { this.log(ref, Graph.getUpstreamSet(this, omitBranch)); }; +GitEngine.prototype.revlist = function(refs) { + var range = new RevisionRange(this, refs); + + // now go through and collect ids + var bigLogStr = ''; + range.revisions.forEach(function(c) { + bigLogStr += c.id + '\n'; + }); + + throw new CommandResult({ + msg: bigLogStr + }); +}; + GitEngine.prototype.log = function(ref, omitSet) { // omit set is for doing stuff like git log branchA ^branchB omitSet = omitSet || {}; @@ -3079,6 +3093,71 @@ var Tag = Ref.extend({ } }); +function RevisionRange(engine, specifiers) { + this.engine = engine; + this.included = {}; + this.excluded = {}; + this.revisions = []; + + this.processSpecifiers(specifiers); +} + +RevisionRange.prototype.isExclusion = function(specifier) { + return specifier.startsWith('^'); +}; + +RevisionRange.prototype.processSpecifiers = function(specifiers) { + var self = this; + var inclusions = []; + var exclusions = []; + + specifiers.forEach(function(specifier) { + if(self.isExclusion(specifier)) { + exclusions.push(specifier.slice(1)); + } else { + inclusions.push(specifier); + } + }); + + exclusions.forEach(function(exclusion) { + self.addExcluded(Graph.getUpstreamSet(self.engine, exclusion)); + }); + + inclusions.forEach(function(inclusion) { + self.addIncluded(Graph.getUpstreamSet(self.engine, inclusion)); + }); + + var includedKeys = Array.from(Object.keys(self.included)); + + self.revisions = includedKeys.map(function(revision) { + return self.engine.resolveStringRef(revision); + }); + self.revisions.sort(self.engine.dateSortFunc); + self.revisions.reverse(); +}; + +RevisionRange.prototype.isExcluded = function(revision) { + return this.excluded.hasOwnProperty(revision); +}; + +RevisionRange.prototype.addExcluded = function(setToExclude) { + var self = this; + Object.keys(setToExclude).forEach(function(toExclude) { + if(!self.isExcluded(toExclude)) { + self.excluded[toExclude] = true; + } + }); +}; + +RevisionRange.prototype.addIncluded = function(setToInclude) { + var self = this; + Object.keys(setToInclude).forEach(function(toInclude) { + if(!self.isExcluded(toInclude)) { + self.included[toInclude] = true; + } + }); +}; + exports.GitEngine = GitEngine; exports.Commit = Commit; exports.Branch = Branch;