diff --git a/src/git.js b/src/git.js index 8d5e52ff..d16e2978 100644 --- a/src/git.js +++ b/src/git.js @@ -81,6 +81,86 @@ GitEngine.prototype.exportTree = function() { return totalExport; }; +GitEngine.prototype.compareBranchesWithinTrees = function(treeA, treeB, branches) { + var result = true; + _.each(branches, function(branchName) { + result = result && this.compareBranchWithinTrees(treeA, treeB, branchName); + }, this); + + return result; +}; + +GitEngine.prototype.compareBranchWithinTrees = function(treeA, treeB, branchName) { + treeA = this.convertTreeSafe(treeA); + treeB = this.convertTreeSafe(treeB); + + this.stripTreeFields([treeA, treeB]); + + // we need a recursive comparison function to bubble up the branch + var recurseCompare = function(commitA, commitB) { + // this is the short-circuit base case + var result = _.isEqual(commitA, commitB); + if (!result) { + return false; + } + + // we loop through each parent ID. we sort the parent ID's beforehand + // so the index lookup is valid + _.each(commitA.parents, function(pAid, index) { + var pBid = commitB.parents[index]; + + var childA = treeA.commits[pAid]; + var childB = treeB.commits[pBid]; + + result = result && recurseCompare(childA, childB); + }, this); + // if each of our children recursively are equal, we are good + return result; + }; + + var branchA = treeA.branches[branchName]; + var branchB = treeB.branches[branchName]; + + return _.isEqual(branchA, branchB) && + recurseCompare(treeA.commits[branchA.target], treeB.commits[branchB.target]); +}; + +GitEngine.prototype.convertTreeSafe = function(tree) { + if (typeof tree == 'string') { + return JSON.parse(unescape(tree)); + } + return tree; +}; + +GitEngine.prototype.stripTreeFields = function(trees) { + var stripFields = ['createTime', 'author', 'commitMessage']; + var sortFields = ['children', 'parents']; + + _.each(trees, function(tree) { + _.each(tree.commits, function(commit) { + _.each(stripFields, function(field) { + commit[field] = undefined; + }); + _.each(sortFields, function(field) { + if (commit[field]) { + commit[field] = commit[field].sort(); + } + }); + }); + }); +}; + +GitEngine.prototype.compareTrees = function(treeA, treeB) { + treeA = this.convertTreeSafe(treeA); + treeB = this.convertTreeSafe(treeB); + + // now we need to strip out the fields we don't care about, aka things + // like createTime, message, author + this.stripTreeFields([treeA, treeB]); + + return _.isEqual(treeA, treeB); +}; + GitEngine.prototype.printTree = function() { var str = escape(JSON.stringify(this.exportTree())); return str; @@ -92,7 +172,6 @@ GitEngine.prototype.printAndCopyTree = function() { GitEngine.prototype.loadTree = function(tree) { // first clear everything - // debugger this.removeAll(); this.instantiateFromTree(tree); diff --git a/src/index.html b/src/index.html index af6f041b..184daa23 100644 --- a/src/index.html +++ b/src/index.html @@ -144,5 +144,8 @@ + + + diff --git a/src/levels.js b/src/levels.js new file mode 100644 index 00000000..028cd472 --- /dev/null +++ b/src/levels.js @@ -0,0 +1,87 @@ +// static class... +function LevelEngine() { + +} + +LevelEngine.prototype.compareBranchesWithinTrees = function(treeA, treeB, branches) { + var result = true; + _.each(branches, function(branchName) { + result = result && this.compareBranchWithinTrees(treeA, treeB, branchName); + }, this); + + return result; +}; + +LevelEngine.prototype.compareBranchWithinTrees = function(treeA, treeB, branchName) { + treeA = this.convertTreeSafe(treeA); + treeB = this.convertTreeSafe(treeB); + + this.stripTreeFields([treeA, treeB]); + + // we need a recursive comparison function to bubble up the branch + var recurseCompare = function(commitA, commitB) { + // this is the short-circuit base case + var result = _.isEqual(commitA, commitB); + if (!result) { + return false; + } + + // we loop through each parent ID. we sort the parent ID's beforehand + // so the index lookup is valid + _.each(commitA.parents, function(pAid, index) { + var pBid = commitB.parents[index]; + + var childA = treeA.commits[pAid]; + var childB = treeB.commits[pBid]; + + result = result && recurseCompare(childA, childB); + }, this); + // if each of our children recursively are equal, we are good + return result; + }; + + var branchA = treeA.branches[branchName]; + var branchB = treeB.branches[branchName]; + + return _.isEqual(branchA, branchB) && + recurseCompare(treeA.commits[branchA.target], treeB.commits[branchB.target]); +}; + +LevelEngine.prototype.convertTreeSafe = function(tree) { + if (typeof tree == 'string') { + return JSON.parse(unescape(tree)); + } + return tree; +}; + +LevelEngine.prototype.stripTreeFields = function(trees) { + var stripFields = ['createTime', 'author', 'commitMessage']; + var sortFields = ['children', 'parents']; + + _.each(trees, function(tree) { + _.each(tree.commits, function(commit) { + _.each(stripFields, function(field) { + commit[field] = undefined; + }); + _.each(sortFields, function(field) { + if (commit[field]) { + commit[field] = commit[field].sort(); + } + }); + }); + }); +}; + +LevelEngine.prototype.compareTrees = function(treeA, treeB) { + treeA = this.convertTreeSafe(treeA); + treeB = this.convertTreeSafe(treeB); + + // now we need to strip out the fields we don't care about, aka things + // like createTime, message, author + this.stripTreeFields([treeA, treeB]); + + return _.isEqual(treeA, treeB); +}; + +var levelEngine = new LevelEngine(); +