diff --git a/src/diagrams/gitGraph/gitGraphAst.js b/src/diagrams/gitGraph/gitGraphAst.js index e83b99a8aa..6385570e7a 100644 --- a/src/diagrams/gitGraph/gitGraphAst.js +++ b/src/diagrams/gitGraph/gitGraphAst.js @@ -118,9 +118,21 @@ exports.checkout = function(branch) { head = commits[id]; } -exports.reset = function(ref) { - log.debug('in reset'); +exports.reset = function(commitRef) { + log.debug('in reset', commitRef); + var ref = commitRef.split(':')[0]; + var parentCount = parseInt(commitRef.split(':')[1]); var commit = ref == 'HEAD' ? head : commits[branches[ref]]; + log.debug(commit, parentCount); + while (parentCount > 0) { + commit = commits[commit.parent]; + parentCount--; + if (!commit) { + var err = 'Critical error - unique parent commit not found during reset'; + log.error(err); + throw err; + } + } head = commit; branches[curBranch] = commit.id; } diff --git a/src/diagrams/gitGraph/gitGraphParser.spec.js b/src/diagrams/gitGraph/gitGraphParser.spec.js index b0c8091e7c..c3d3774751 100644 --- a/src/diagrams/gitGraph/gitGraphParser.spec.js +++ b/src/diagrams/gitGraph/gitGraphParser.spec.js @@ -72,7 +72,7 @@ describe('when parsing a gitGraph',function() { }); it('should handle set direction', function () { - var str = 'gitGraph TB:\n' + + var str = 'gitGraph BT:\n' + 'commit\n'; parser.parse(str); @@ -81,7 +81,7 @@ describe('when parsing a gitGraph',function() { expect(Object.keys(commits).length).toBe(1); expect(parser.yy.getCurrentBranch()).toBe('master'); - expect(parser.yy.getDirection()).toBe('TB'); + expect(parser.yy.getDirection()).toBe('BT'); expect(Object.keys(parser.yy.getBranches()).length).toBe(1); }); @@ -145,6 +145,24 @@ describe('when parsing a gitGraph',function() { expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['newbranch']); }); + it('reset can take an argument', function () { + var str = 'gitGraph:\n' + + 'commit\n' + + 'commit\n' + + 'branch newbranch\n' + + 'checkout newbranch\n' + + 'commit\n' + + 'reset master^\n'; + + parser.parse(str); + + var commits = parser.yy.getCommits(); + expect(Object.keys(commits).length).toBe(3); + expect(parser.yy.getCurrentBranch()).toBe('newbranch'); + var master = commits[parser.yy.getBranches()['master']]; + expect(parser.yy.getHead().id).toEqual(master.parent); + }) + it('it should handle fast forwardable merges', function () { var str = 'gitGraph:\n' + 'commit\n' + diff --git a/src/diagrams/gitGraph/parser/gitGraph.jison b/src/diagrams/gitGraph/parser/gitGraph.jison index 6754f0b2ea..e675a56e45 100644 --- a/src/diagrams/gitGraph/parser/gitGraph.jison +++ b/src/diagrams/gitGraph/parser/gitGraph.jison @@ -25,9 +25,9 @@ "reset" return 'RESET'; "checkout" return 'CHECKOUT'; "LR" return 'DIR'; -"TB" return 'DIR'; "BT" return 'DIR'; ":" return ':'; +"^" return 'CARET' "options"\r?\n this.begin("options"); "end"\r?\n this.popState(); [^\n]+\r?\n return 'OPT'; @@ -83,6 +83,10 @@ commit_arg ; reset_arg - : 'HEAD' - | ID + : 'HEAD' reset_parents{$$ = $1+ ":" + $2 } + | ID reset_parents{$$ = $1+ ":" + yy.count; yy.count = 0} + ; +reset_parents + : /* empty */ {yy.count = 0} + | CARET reset_parents { yy.count += 1 } ; diff --git a/src/diagrams/gitGraph/parser/gitGraph.js b/src/diagrams/gitGraph/parser/gitGraph.js index d63cb91e13..5faa081a1f 100644 --- a/src/diagrams/gitGraph/parser/gitGraph.js +++ b/src/diagrams/gitGraph/parser/gitGraph.js @@ -71,15 +71,13 @@ recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error) } */ -var gitGraph = (function(){ -var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[2,3],$V1=[1,7],$V2=[7,12,15,17,19,20,21],$V3=[7,11,12,15,17,19,20,21]; -var parser = {trace: function trace() { - Jison.print.apply(null, arguments); - }, +var parser = (function(){ +var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[2,3],$V1=[1,7],$V2=[7,12,15,17,19,20,21],$V3=[7,11,12,15,17,19,20,21],$V4=[2,20],$V5=[1,32]; +var parser = {trace: function trace() { }, yy: {}, -symbols_: {"error":2,"start":3,"GG":4,":":5,"document":6,"EOF":7,"DIR":8,"options":9,"body":10,"OPT":11,"NL":12,"line":13,"statement":14,"COMMIT":15,"commit_arg":16,"BRANCH":17,"ID":18,"CHECKOUT":19,"MERGE":20,"RESET":21,"reset_arg":22,"STR":23,"HEAD":24,"$accept":0,"$end":1}, -terminals_: {2:"error",4:"GG",5:":",7:"EOF",8:"DIR",11:"OPT",12:"NL",15:"COMMIT",17:"BRANCH",18:"ID",19:"CHECKOUT",20:"MERGE",21:"RESET",23:"STR",24:"HEAD"}, -productions_: [0,[3,4],[3,5],[6,0],[6,2],[9,2],[9,1],[10,0],[10,2],[13,2],[13,1],[14,2],[14,2],[14,2],[14,2],[14,2],[16,0],[16,1],[22,1],[22,1]], +symbols_: {"error":2,"start":3,"GG":4,":":5,"document":6,"EOF":7,"DIR":8,"options":9,"body":10,"OPT":11,"NL":12,"line":13,"statement":14,"COMMIT":15,"commit_arg":16,"BRANCH":17,"ID":18,"CHECKOUT":19,"MERGE":20,"RESET":21,"reset_arg":22,"STR":23,"HEAD":24,"reset_parents":25,"CARET":26,"$accept":0,"$end":1}, +terminals_: {2:"error",4:"GG",5:":",7:"EOF",8:"DIR",11:"OPT",12:"NL",15:"COMMIT",17:"BRANCH",18:"ID",19:"CHECKOUT",20:"MERGE",21:"RESET",23:"STR",24:"HEAD",26:"CARET"}, +productions_: [0,[3,4],[3,5],[6,0],[6,2],[9,2],[9,1],[10,0],[10,2],[13,2],[13,1],[14,2],[14,2],[14,2],[14,2],[14,2],[16,0],[16,1],[22,2],[22,2],[25,0],[25,2]], performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) { /* this == yyval */ @@ -127,10 +125,22 @@ break; case 17: this.$=$$[$0] break; +case 18: +this.$ = $$[$0-1]+ ":" + $$[$0] +break; +case 19: +this.$ = $$[$0-1]+ ":" + yy.count; yy.count = 0 +break; +case 20: +yy.count = 0 +break; +case 21: + yy.count += 1 +break; } }, -table: [{3:1,4:[1,2]},{1:[3]},{5:[1,3],8:[1,4]},{6:5,7:$V0,9:6,12:$V1},{5:[1,8]},{7:[1,9]},o($V2,[2,7],{10:10,11:[1,11]}),o($V3,[2,6]),{6:12,7:$V0,9:6,12:$V1},{1:[2,1]},{7:[2,4],12:[1,15],13:13,14:14,15:[1,16],17:[1,17],19:[1,18],20:[1,19],21:[1,20]},o($V3,[2,5]),{7:[1,21]},o($V2,[2,8]),{12:[1,22]},o($V2,[2,10]),{12:[2,16],16:23,23:[1,24]},{18:[1,25]},{18:[1,26]},{18:[1,27]},{18:[1,30],22:28,24:[1,29]},{1:[2,2]},o($V2,[2,9]),{12:[2,11]},{12:[2,17]},{12:[2,12]},{12:[2,13]},{12:[2,14]},{12:[2,15]},{12:[2,18]},{12:[2,19]}], -defaultActions: {9:[2,1],21:[2,2],23:[2,11],24:[2,17],25:[2,12],26:[2,13],27:[2,14],28:[2,15],29:[2,18],30:[2,19]}, +table: [{3:1,4:[1,2]},{1:[3]},{5:[1,3],8:[1,4]},{6:5,7:$V0,9:6,12:$V1},{5:[1,8]},{7:[1,9]},o($V2,[2,7],{10:10,11:[1,11]}),o($V3,[2,6]),{6:12,7:$V0,9:6,12:$V1},{1:[2,1]},{7:[2,4],12:[1,15],13:13,14:14,15:[1,16],17:[1,17],19:[1,18],20:[1,19],21:[1,20]},o($V3,[2,5]),{7:[1,21]},o($V2,[2,8]),{12:[1,22]},o($V2,[2,10]),{12:[2,16],16:23,23:[1,24]},{18:[1,25]},{18:[1,26]},{18:[1,27]},{18:[1,30],22:28,24:[1,29]},{1:[2,2]},o($V2,[2,9]),{12:[2,11]},{12:[2,17]},{12:[2,12]},{12:[2,13]},{12:[2,14]},{12:[2,15]},{12:$V4,25:31,26:$V5},{12:$V4,25:33,26:$V5},{12:[2,18]},{12:$V4,25:34,26:$V5},{12:[2,19]},{12:[2,21]}], +defaultActions: {9:[2,1],21:[2,2],23:[2,11],24:[2,17],25:[2,12],26:[2,13],27:[2,14],28:[2,15],31:[2,18],33:[2,19],34:[2,21]}, parseError: function parseError(str, hash) { if (hash.recoverable) { this.trace(str); @@ -633,9 +643,9 @@ case 10:return 8; break; case 11:return 8; break; -case 12:return 8; +case 12:return 5; break; -case 13:return 5; +case 13:return 26 break; case 14:this.begin("options"); break; @@ -655,7 +665,7 @@ case 21:return 7; break; } }, -rules: [/^(?:(\r?\n)+)/i,/^(?:\s+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:gitGraph\b)/i,/^(?:commit\b)/i,/^(?:branch\b)/i,/^(?:merge\b)/i,/^(?:reset\b)/i,/^(?:checkout\b)/i,/^(?:LR\b)/i,/^(?:TB\b)/i,/^(?:BT\b)/i,/^(?::)/i,/^(?:options\r?\n)/i,/^(?:end\r?\n)/i,/^(?:[^\n]+\r?\n)/i,/^(?:["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:[a-zA-Z][a-zA-Z0-9_]+)/i,/^(?:$)/i], +rules: [/^(?:(\r?\n)+)/i,/^(?:\s+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:gitGraph\b)/i,/^(?:commit\b)/i,/^(?:branch\b)/i,/^(?:merge\b)/i,/^(?:reset\b)/i,/^(?:checkout\b)/i,/^(?:LR\b)/i,/^(?:BT\b)/i,/^(?::)/i,/^(?:\^)/i,/^(?:options\r?\n)/i,/^(?:end\r?\n)/i,/^(?:[^\n]+\r?\n)/i,/^(?:["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:[a-zA-Z][a-zA-Z0-9_]+)/i,/^(?:$)/i], conditions: {"options":{"rules":[15,16],"inclusive":false},"string":{"rules":[18,19],"inclusive":false},"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17,20,21],"inclusive":true}} }); return lexer; @@ -670,9 +680,9 @@ return new Parser; if (typeof require !== 'undefined' && typeof exports !== 'undefined') { -exports.parser = gitGraph; -exports.Parser = gitGraph.Parser; -exports.parse = function () { return gitGraph.parse.apply(gitGraph, arguments); }; +exports.parser = parser; +exports.Parser = parser.Parser; +exports.parse = function () { return parser.parse.apply(parser, arguments); }; exports.main = function commonjsMain(args) { if (!args[1]) { console.log('Usage: '+args[0]+' FILE'); diff --git a/testgitgraph.mm b/testgitgraph.mm index 4c5e844c10..194ef386cd 100644 --- a/testgitgraph.mm +++ b/testgitgraph.mm @@ -1,6 +1,6 @@ gitGraph BT: options -{"key": "value", +{ "nodeSpacing": 150 } end @@ -13,4 +13,7 @@ commit commit merge newbranch + reset newbranch^^ + commit + commit