mirror of
https://github.com/pcottle/learnGitBranching.git
synced 2025-06-26 16:08:34 +02:00
Recursive tree comparison algorithm that is hash agnostic to lay the groundwork for Issue #28
This commit is contained in:
parent
0d295197ac
commit
2a96052002
9 changed files with 334 additions and 91 deletions
272
build/bundle.js
272
build/bundle.js
|
@ -6501,16 +6501,17 @@ var init = function() {
|
||||||
events.trigger('resize', e);
|
events.trigger('resize', e);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
$(window).on('resize', _.throttle(function(e) {
|
$(window).on('resize', _.throttle(function(e) {
|
||||||
var width = $(window).width();
|
var width = $(window).width();
|
||||||
var height = $(window).height();
|
var height = $(window).height();
|
||||||
eventBaton.trigger('windowSizeCheck', {w: width, h: height});
|
eventBaton.trigger('windowSizeCheck', {w: width, h: height});
|
||||||
}, 500));
|
}, 500));
|
||||||
|
*/
|
||||||
|
|
||||||
eventBaton.stealBaton('docKeydown', function() { });
|
eventBaton.stealBaton('docKeydown', function() { });
|
||||||
eventBaton.stealBaton('docKeyup', function() { });
|
eventBaton.stealBaton('docKeyup', function() { });
|
||||||
|
|
||||||
//$('body').delegate('div.close', 'click', function() { alert('these dont actually work sorry lol.'); });
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* I am disabling this for now, it works on desktop but is
|
* I am disabling this for now, it works on desktop but is
|
||||||
hacky on iOS mobile and god knows the behavior on android...
|
hacky on iOS mobile and god knows the behavior on android...
|
||||||
|
@ -6528,7 +6529,7 @@ var init = function() {
|
||||||
});
|
});
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/* people were pissed about this apparently
|
||||||
eventBaton.stealBaton('windowSizeCheck', function(size) {
|
eventBaton.stealBaton('windowSizeCheck', function(size) {
|
||||||
if (size.w < Constants.VIEWPORT.minWidth ||
|
if (size.w < Constants.VIEWPORT.minWidth ||
|
||||||
size.h < Constants.VIEWPORT.minHeight) {
|
size.h < Constants.VIEWPORT.minHeight) {
|
||||||
|
@ -6591,6 +6592,7 @@ var init = function() {
|
||||||
eventBaton.trigger('commandSubmitted', command);
|
eventBaton.trigger('commandSubmitted', command);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (/(iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent) || /android/i.test(navigator.userAgent)) {
|
if (/(iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent) || /android/i.test(navigator.userAgent)) {
|
||||||
sandbox.mainVis.customEvents.on('gitEngineReady', function() {
|
sandbox.mainVis.customEvents.on('gitEngineReady', function() {
|
||||||
eventBaton.trigger('commandSubmitted', 'mobile alert');
|
eventBaton.trigger('commandSubmitted', 'mobile alert');
|
||||||
|
@ -7566,6 +7568,7 @@ GitEngine.prototype.initUniqueID = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
GitEngine.prototype.defaultInit = function() {
|
GitEngine.prototype.defaultInit = function() {
|
||||||
|
// lol 80 char limit
|
||||||
var defaultTree = JSON.parse(unescape("%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22master%22%2C%22type%22%3A%22branch%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22type%22%3A%22commit%22%2C%22parents%22%3A%5B%5D%2C%22author%22%3A%22Peter%20Cottle%22%2C%22createTime%22%3A%22Mon%20Nov%2005%202012%2000%3A56%3A47%20GMT-0800%20%28PST%29%22%2C%22commitMessage%22%3A%22Quick%20Commit.%20Go%20Bears%21%22%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22type%22%3A%22commit%22%2C%22parents%22%3A%5B%22C0%22%5D%2C%22author%22%3A%22Peter%20Cottle%22%2C%22createTime%22%3A%22Mon%20Nov%2005%202012%2000%3A56%3A47%20GMT-0800%20%28PST%29%22%2C%22commitMessage%22%3A%22Quick%20Commit.%20Go%20Bears%21%22%2C%22id%22%3A%22C1%22%7D%7D%2C%22HEAD%22%3A%7B%22id%22%3A%22HEAD%22%2C%22target%22%3A%22master%22%2C%22type%22%3A%22general%20ref%22%7D%7D"));
|
var defaultTree = JSON.parse(unescape("%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22master%22%2C%22type%22%3A%22branch%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22type%22%3A%22commit%22%2C%22parents%22%3A%5B%5D%2C%22author%22%3A%22Peter%20Cottle%22%2C%22createTime%22%3A%22Mon%20Nov%2005%202012%2000%3A56%3A47%20GMT-0800%20%28PST%29%22%2C%22commitMessage%22%3A%22Quick%20Commit.%20Go%20Bears%21%22%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22type%22%3A%22commit%22%2C%22parents%22%3A%5B%22C0%22%5D%2C%22author%22%3A%22Peter%20Cottle%22%2C%22createTime%22%3A%22Mon%20Nov%2005%202012%2000%3A56%3A47%20GMT-0800%20%28PST%29%22%2C%22commitMessage%22%3A%22Quick%20Commit.%20Go%20Bears%21%22%2C%22id%22%3A%22C1%22%7D%7D%2C%22HEAD%22%3A%7B%22id%22%3A%22HEAD%22%2C%22target%22%3A%22master%22%2C%22type%22%3A%22general%20ref%22%7D%7D"));
|
||||||
this.loadTree(defaultTree);
|
this.loadTree(defaultTree);
|
||||||
};
|
};
|
||||||
|
@ -7769,7 +7772,7 @@ GitEngine.prototype.getOrMakeRecursive = function(tree, createdSoFar, objID) {
|
||||||
return commit;
|
return commit;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error('ruh rho!! unsupported tyep for ' + objID);
|
throw new Error('ruh rho!! unsupported type for ' + objID);
|
||||||
};
|
};
|
||||||
|
|
||||||
GitEngine.prototype.tearDown = function() {
|
GitEngine.prototype.tearDown = function() {
|
||||||
|
@ -9623,31 +9626,6 @@ TreeCompare.prototype.compareBranchesWithinTrees = function(treeA, treeB, branch
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
TreeCompare.prototype.getRecurseCompare = function(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;
|
|
||||||
};
|
|
||||||
return recurseCompare;
|
|
||||||
};
|
|
||||||
|
|
||||||
TreeCompare.prototype.compareBranchWithinTrees = function(treeA, treeB, branchName) {
|
TreeCompare.prototype.compareBranchWithinTrees = function(treeA, treeB, branchName) {
|
||||||
treeA = this.convertTreeSafe(treeA);
|
treeA = this.convertTreeSafe(treeA);
|
||||||
treeB = this.convertTreeSafe(treeB);
|
treeB = this.convertTreeSafe(treeB);
|
||||||
|
@ -9661,6 +9639,106 @@ TreeCompare.prototype.compareBranchWithinTrees = function(treeA, treeB, branchNa
|
||||||
recurseCompare(treeA.commits[branchA.target], treeB.commits[branchB.target]);
|
recurseCompare(treeA.commits[branchA.target], treeB.commits[branchB.target]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TreeCompare.prototype.compareAllBranchesWithinTreesHashAgnostic = function(treeA, treeB) {
|
||||||
|
// we can't DRY unfortunately here because we need a special _.isEqual function
|
||||||
|
// for both the recursive compare and the branch compare
|
||||||
|
treeA = this.convertTreeSafe(treeA);
|
||||||
|
treeB = this.convertTreeSafe(treeB);
|
||||||
|
this.reduceTreeFields([treeA, treeB]);
|
||||||
|
|
||||||
|
// get a function to compare branch objects without hashes
|
||||||
|
var compareBranchObjs = _.bind(function(branchA, branchB) {
|
||||||
|
if (!branchA || !branchB) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
branchA.target = this.getBaseRef(branchA.target);
|
||||||
|
branchB.target = this.getBaseRef(branchB.target);
|
||||||
|
|
||||||
|
return _.isEqual(branchA, branchB);
|
||||||
|
}, this);
|
||||||
|
// and a function to compare recursively without worrying about hashes
|
||||||
|
var recurseCompare = this.getRecurseCompareHashAgnostic(treeA, treeB);
|
||||||
|
|
||||||
|
var allBranches = _.extend(
|
||||||
|
{},
|
||||||
|
treeA.branches,
|
||||||
|
treeB.branches
|
||||||
|
);
|
||||||
|
|
||||||
|
var result = true;
|
||||||
|
_.each(allBranches, function(branchObj, branchName) {
|
||||||
|
branchA = treeA.branches[branchName];
|
||||||
|
branchB = treeB.branches[branchName];
|
||||||
|
|
||||||
|
result = result && compareBranchObjs(branchA, branchB) &&
|
||||||
|
recurseCompare(treeA.commits[branchA.target], treeB.commits[branchB.target]);
|
||||||
|
}, this);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
TreeCompare.prototype.getBaseRef = function(ref) {
|
||||||
|
var idRegex = /^C(\d+)/;
|
||||||
|
var bits = idRegex.exec(ref);
|
||||||
|
if (!bits) { throw new Error('no regex matchy for ' + ref); }
|
||||||
|
// no matter what hash this is (aka C1', C1'', C1'^3, etc) we
|
||||||
|
// return C1
|
||||||
|
return 'C' + bits[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
TreeCompare.prototype.getRecurseCompareHashAgnostic = function(treeA, treeB) {
|
||||||
|
// here we pass in a special comparison function to pass into the base
|
||||||
|
// recursive compare.
|
||||||
|
|
||||||
|
// some buildup functions
|
||||||
|
var getStrippedCommitCopy = _.bind(function(commit) {
|
||||||
|
return _.extend(
|
||||||
|
{},
|
||||||
|
commit,
|
||||||
|
{id: this.getBaseRef(commit.id)
|
||||||
|
});
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
var isEqual = function(commitA, commitB) {
|
||||||
|
return _.isEqual(
|
||||||
|
getStrippedCommitCopy(commitA),
|
||||||
|
getStrippedCommitCopy(commitB)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
return this.getRecurseCompare(treeA, treeB, {isEqual: isEqual});
|
||||||
|
};
|
||||||
|
|
||||||
|
TreeCompare.prototype.getRecurseCompare = function(treeA, treeB, options) {
|
||||||
|
options = options || {};
|
||||||
|
|
||||||
|
// 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 = options.isEqual ?
|
||||||
|
options.isEqual(commitA, commitB) : _.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. for merge commits this will duplicate some of the
|
||||||
|
// checking (because we aren't doing graph search) but it's not a huge deal
|
||||||
|
var allParents = _.unique(commitA.parents.concat(commitB.parents));
|
||||||
|
_.each(allParents, function(pAid, index) {
|
||||||
|
var pBid = commitB.parents[index];
|
||||||
|
|
||||||
|
// if treeA or treeB doesn't have this parent,
|
||||||
|
// then we get an undefined child which is fine when we pass into _.isEqual
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
return recurseCompare;
|
||||||
|
};
|
||||||
|
|
||||||
TreeCompare.prototype.convertTreeSafe = function(tree) {
|
TreeCompare.prototype.convertTreeSafe = function(tree) {
|
||||||
if (typeof tree == 'string') {
|
if (typeof tree == 'string') {
|
||||||
return JSON.parse(unescape(tree));
|
return JSON.parse(unescape(tree));
|
||||||
|
@ -18576,16 +18654,17 @@ var init = function() {
|
||||||
events.trigger('resize', e);
|
events.trigger('resize', e);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
$(window).on('resize', _.throttle(function(e) {
|
$(window).on('resize', _.throttle(function(e) {
|
||||||
var width = $(window).width();
|
var width = $(window).width();
|
||||||
var height = $(window).height();
|
var height = $(window).height();
|
||||||
eventBaton.trigger('windowSizeCheck', {w: width, h: height});
|
eventBaton.trigger('windowSizeCheck', {w: width, h: height});
|
||||||
}, 500));
|
}, 500));
|
||||||
|
*/
|
||||||
|
|
||||||
eventBaton.stealBaton('docKeydown', function() { });
|
eventBaton.stealBaton('docKeydown', function() { });
|
||||||
eventBaton.stealBaton('docKeyup', function() { });
|
eventBaton.stealBaton('docKeyup', function() { });
|
||||||
|
|
||||||
//$('body').delegate('div.close', 'click', function() { alert('these dont actually work sorry lol.'); });
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* I am disabling this for now, it works on desktop but is
|
* I am disabling this for now, it works on desktop but is
|
||||||
hacky on iOS mobile and god knows the behavior on android...
|
hacky on iOS mobile and god knows the behavior on android...
|
||||||
|
@ -18603,7 +18682,7 @@ var init = function() {
|
||||||
});
|
});
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/* people were pissed about this apparently
|
||||||
eventBaton.stealBaton('windowSizeCheck', function(size) {
|
eventBaton.stealBaton('windowSizeCheck', function(size) {
|
||||||
if (size.w < Constants.VIEWPORT.minWidth ||
|
if (size.w < Constants.VIEWPORT.minWidth ||
|
||||||
size.h < Constants.VIEWPORT.minHeight) {
|
size.h < Constants.VIEWPORT.minHeight) {
|
||||||
|
@ -18666,6 +18745,7 @@ var init = function() {
|
||||||
eventBaton.trigger('commandSubmitted', command);
|
eventBaton.trigger('commandSubmitted', command);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (/(iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent) || /android/i.test(navigator.userAgent)) {
|
if (/(iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent) || /android/i.test(navigator.userAgent)) {
|
||||||
sandbox.mainVis.customEvents.on('gitEngineReady', function() {
|
sandbox.mainVis.customEvents.on('gitEngineReady', function() {
|
||||||
eventBaton.trigger('commandSubmitted', 'mobile alert');
|
eventBaton.trigger('commandSubmitted', 'mobile alert');
|
||||||
|
@ -19195,6 +19275,7 @@ GitEngine.prototype.initUniqueID = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
GitEngine.prototype.defaultInit = function() {
|
GitEngine.prototype.defaultInit = function() {
|
||||||
|
// lol 80 char limit
|
||||||
var defaultTree = JSON.parse(unescape("%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22master%22%2C%22type%22%3A%22branch%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22type%22%3A%22commit%22%2C%22parents%22%3A%5B%5D%2C%22author%22%3A%22Peter%20Cottle%22%2C%22createTime%22%3A%22Mon%20Nov%2005%202012%2000%3A56%3A47%20GMT-0800%20%28PST%29%22%2C%22commitMessage%22%3A%22Quick%20Commit.%20Go%20Bears%21%22%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22type%22%3A%22commit%22%2C%22parents%22%3A%5B%22C0%22%5D%2C%22author%22%3A%22Peter%20Cottle%22%2C%22createTime%22%3A%22Mon%20Nov%2005%202012%2000%3A56%3A47%20GMT-0800%20%28PST%29%22%2C%22commitMessage%22%3A%22Quick%20Commit.%20Go%20Bears%21%22%2C%22id%22%3A%22C1%22%7D%7D%2C%22HEAD%22%3A%7B%22id%22%3A%22HEAD%22%2C%22target%22%3A%22master%22%2C%22type%22%3A%22general%20ref%22%7D%7D"));
|
var defaultTree = JSON.parse(unescape("%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22master%22%2C%22type%22%3A%22branch%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22type%22%3A%22commit%22%2C%22parents%22%3A%5B%5D%2C%22author%22%3A%22Peter%20Cottle%22%2C%22createTime%22%3A%22Mon%20Nov%2005%202012%2000%3A56%3A47%20GMT-0800%20%28PST%29%22%2C%22commitMessage%22%3A%22Quick%20Commit.%20Go%20Bears%21%22%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22type%22%3A%22commit%22%2C%22parents%22%3A%5B%22C0%22%5D%2C%22author%22%3A%22Peter%20Cottle%22%2C%22createTime%22%3A%22Mon%20Nov%2005%202012%2000%3A56%3A47%20GMT-0800%20%28PST%29%22%2C%22commitMessage%22%3A%22Quick%20Commit.%20Go%20Bears%21%22%2C%22id%22%3A%22C1%22%7D%7D%2C%22HEAD%22%3A%7B%22id%22%3A%22HEAD%22%2C%22target%22%3A%22master%22%2C%22type%22%3A%22general%20ref%22%7D%7D"));
|
||||||
this.loadTree(defaultTree);
|
this.loadTree(defaultTree);
|
||||||
};
|
};
|
||||||
|
@ -19398,7 +19479,7 @@ GitEngine.prototype.getOrMakeRecursive = function(tree, createdSoFar, objID) {
|
||||||
return commit;
|
return commit;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error('ruh rho!! unsupported tyep for ' + objID);
|
throw new Error('ruh rho!! unsupported type for ' + objID);
|
||||||
};
|
};
|
||||||
|
|
||||||
GitEngine.prototype.tearDown = function() {
|
GitEngine.prototype.tearDown = function() {
|
||||||
|
@ -20899,31 +20980,6 @@ TreeCompare.prototype.compareBranchesWithinTrees = function(treeA, treeB, branch
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
TreeCompare.prototype.getRecurseCompare = function(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;
|
|
||||||
};
|
|
||||||
return recurseCompare;
|
|
||||||
};
|
|
||||||
|
|
||||||
TreeCompare.prototype.compareBranchWithinTrees = function(treeA, treeB, branchName) {
|
TreeCompare.prototype.compareBranchWithinTrees = function(treeA, treeB, branchName) {
|
||||||
treeA = this.convertTreeSafe(treeA);
|
treeA = this.convertTreeSafe(treeA);
|
||||||
treeB = this.convertTreeSafe(treeB);
|
treeB = this.convertTreeSafe(treeB);
|
||||||
|
@ -20937,6 +20993,106 @@ TreeCompare.prototype.compareBranchWithinTrees = function(treeA, treeB, branchNa
|
||||||
recurseCompare(treeA.commits[branchA.target], treeB.commits[branchB.target]);
|
recurseCompare(treeA.commits[branchA.target], treeB.commits[branchB.target]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TreeCompare.prototype.compareAllBranchesWithinTreesHashAgnostic = function(treeA, treeB) {
|
||||||
|
// we can't DRY unfortunately here because we need a special _.isEqual function
|
||||||
|
// for both the recursive compare and the branch compare
|
||||||
|
treeA = this.convertTreeSafe(treeA);
|
||||||
|
treeB = this.convertTreeSafe(treeB);
|
||||||
|
this.reduceTreeFields([treeA, treeB]);
|
||||||
|
|
||||||
|
// get a function to compare branch objects without hashes
|
||||||
|
var compareBranchObjs = _.bind(function(branchA, branchB) {
|
||||||
|
if (!branchA || !branchB) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
branchA.target = this.getBaseRef(branchA.target);
|
||||||
|
branchB.target = this.getBaseRef(branchB.target);
|
||||||
|
|
||||||
|
return _.isEqual(branchA, branchB);
|
||||||
|
}, this);
|
||||||
|
// and a function to compare recursively without worrying about hashes
|
||||||
|
var recurseCompare = this.getRecurseCompareHashAgnostic(treeA, treeB);
|
||||||
|
|
||||||
|
var allBranches = _.extend(
|
||||||
|
{},
|
||||||
|
treeA.branches,
|
||||||
|
treeB.branches
|
||||||
|
);
|
||||||
|
|
||||||
|
var result = true;
|
||||||
|
_.each(allBranches, function(branchObj, branchName) {
|
||||||
|
branchA = treeA.branches[branchName];
|
||||||
|
branchB = treeB.branches[branchName];
|
||||||
|
|
||||||
|
result = result && compareBranchObjs(branchA, branchB) &&
|
||||||
|
recurseCompare(treeA.commits[branchA.target], treeB.commits[branchB.target]);
|
||||||
|
}, this);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
TreeCompare.prototype.getBaseRef = function(ref) {
|
||||||
|
var idRegex = /^C(\d+)/;
|
||||||
|
var bits = idRegex.exec(ref);
|
||||||
|
if (!bits) { throw new Error('no regex matchy for ' + ref); }
|
||||||
|
// no matter what hash this is (aka C1', C1'', C1'^3, etc) we
|
||||||
|
// return C1
|
||||||
|
return 'C' + bits[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
TreeCompare.prototype.getRecurseCompareHashAgnostic = function(treeA, treeB) {
|
||||||
|
// here we pass in a special comparison function to pass into the base
|
||||||
|
// recursive compare.
|
||||||
|
|
||||||
|
// some buildup functions
|
||||||
|
var getStrippedCommitCopy = _.bind(function(commit) {
|
||||||
|
return _.extend(
|
||||||
|
{},
|
||||||
|
commit,
|
||||||
|
{id: this.getBaseRef(commit.id)
|
||||||
|
});
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
var isEqual = function(commitA, commitB) {
|
||||||
|
return _.isEqual(
|
||||||
|
getStrippedCommitCopy(commitA),
|
||||||
|
getStrippedCommitCopy(commitB)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
return this.getRecurseCompare(treeA, treeB, {isEqual: isEqual});
|
||||||
|
};
|
||||||
|
|
||||||
|
TreeCompare.prototype.getRecurseCompare = function(treeA, treeB, options) {
|
||||||
|
options = options || {};
|
||||||
|
|
||||||
|
// 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 = options.isEqual ?
|
||||||
|
options.isEqual(commitA, commitB) : _.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. for merge commits this will duplicate some of the
|
||||||
|
// checking (because we aren't doing graph search) but it's not a huge deal
|
||||||
|
var allParents = _.unique(commitA.parents.concat(commitB.parents));
|
||||||
|
_.each(allParents, function(pAid, index) {
|
||||||
|
var pBid = commitB.parents[index];
|
||||||
|
|
||||||
|
// if treeA or treeB doesn't have this parent,
|
||||||
|
// then we get an undefined child which is fine when we pass into _.isEqual
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
return recurseCompare;
|
||||||
|
};
|
||||||
|
|
||||||
TreeCompare.prototype.convertTreeSafe = function(tree) {
|
TreeCompare.prototype.convertTreeSafe = function(tree) {
|
||||||
if (typeof tree == 'string') {
|
if (typeof tree == 'string') {
|
||||||
return JSON.parse(unescape(tree));
|
return JSON.parse(unescape(tree));
|
||||||
|
|
File diff suppressed because one or more lines are too long
1
build/bundle.min.7e188d82.js
Normal file
1
build/bundle.min.7e188d82.js
Normal file
File diff suppressed because one or more lines are too long
2
build/bundle.min.js
vendored
2
build/bundle.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -409,7 +409,7 @@
|
||||||
For a much easier time perusing the source, see the individual files at:
|
For a much easier time perusing the source, see the individual files at:
|
||||||
https://github.com/pcottle/learnGitBranching
|
https://github.com/pcottle/learnGitBranching
|
||||||
-->
|
-->
|
||||||
<script src="build/bundle.min.04e3ef79.js"></script>
|
<script src="build/bundle.min.7e188d82.js"></script>
|
||||||
|
|
||||||
<!-- The advantage of github pages: super-easy, simple, slick static hostic.
|
<!-- The advantage of github pages: super-easy, simple, slick static hostic.
|
||||||
The downside? No raw logs to parse for analytics, so I have to include
|
The downside? No raw logs to parse for analytics, so I have to include
|
||||||
|
|
|
@ -63,16 +63,17 @@ var init = function() {
|
||||||
events.trigger('resize', e);
|
events.trigger('resize', e);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
$(window).on('resize', _.throttle(function(e) {
|
$(window).on('resize', _.throttle(function(e) {
|
||||||
var width = $(window).width();
|
var width = $(window).width();
|
||||||
var height = $(window).height();
|
var height = $(window).height();
|
||||||
eventBaton.trigger('windowSizeCheck', {w: width, h: height});
|
eventBaton.trigger('windowSizeCheck', {w: width, h: height});
|
||||||
}, 500));
|
}, 500));
|
||||||
|
*/
|
||||||
|
|
||||||
eventBaton.stealBaton('docKeydown', function() { });
|
eventBaton.stealBaton('docKeydown', function() { });
|
||||||
eventBaton.stealBaton('docKeyup', function() { });
|
eventBaton.stealBaton('docKeyup', function() { });
|
||||||
|
|
||||||
//$('body').delegate('div.close', 'click', function() { alert('these dont actually work sorry lol.'); });
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* I am disabling this for now, it works on desktop but is
|
* I am disabling this for now, it works on desktop but is
|
||||||
hacky on iOS mobile and god knows the behavior on android...
|
hacky on iOS mobile and god knows the behavior on android...
|
||||||
|
@ -90,7 +91,7 @@ var init = function() {
|
||||||
});
|
});
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/* people were pissed about this apparently
|
||||||
eventBaton.stealBaton('windowSizeCheck', function(size) {
|
eventBaton.stealBaton('windowSizeCheck', function(size) {
|
||||||
if (size.w < Constants.VIEWPORT.minWidth ||
|
if (size.w < Constants.VIEWPORT.minWidth ||
|
||||||
size.h < Constants.VIEWPORT.minHeight) {
|
size.h < Constants.VIEWPORT.minHeight) {
|
||||||
|
@ -153,6 +154,7 @@ var init = function() {
|
||||||
eventBaton.trigger('commandSubmitted', command);
|
eventBaton.trigger('commandSubmitted', command);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (/(iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent) || /android/i.test(navigator.userAgent)) {
|
if (/(iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent) || /android/i.test(navigator.userAgent)) {
|
||||||
sandbox.mainVis.customEvents.on('gitEngineReady', function() {
|
sandbox.mainVis.customEvents.on('gitEngineReady', function() {
|
||||||
eventBaton.trigger('commandSubmitted', 'mobile alert');
|
eventBaton.trigger('commandSubmitted', 'mobile alert');
|
||||||
|
|
|
@ -45,6 +45,7 @@ GitEngine.prototype.initUniqueID = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
GitEngine.prototype.defaultInit = function() {
|
GitEngine.prototype.defaultInit = function() {
|
||||||
|
// lol 80 char limit
|
||||||
var defaultTree = JSON.parse(unescape("%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22master%22%2C%22type%22%3A%22branch%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22type%22%3A%22commit%22%2C%22parents%22%3A%5B%5D%2C%22author%22%3A%22Peter%20Cottle%22%2C%22createTime%22%3A%22Mon%20Nov%2005%202012%2000%3A56%3A47%20GMT-0800%20%28PST%29%22%2C%22commitMessage%22%3A%22Quick%20Commit.%20Go%20Bears%21%22%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22type%22%3A%22commit%22%2C%22parents%22%3A%5B%22C0%22%5D%2C%22author%22%3A%22Peter%20Cottle%22%2C%22createTime%22%3A%22Mon%20Nov%2005%202012%2000%3A56%3A47%20GMT-0800%20%28PST%29%22%2C%22commitMessage%22%3A%22Quick%20Commit.%20Go%20Bears%21%22%2C%22id%22%3A%22C1%22%7D%7D%2C%22HEAD%22%3A%7B%22id%22%3A%22HEAD%22%2C%22target%22%3A%22master%22%2C%22type%22%3A%22general%20ref%22%7D%7D"));
|
var defaultTree = JSON.parse(unescape("%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C1%22%2C%22id%22%3A%22master%22%2C%22type%22%3A%22branch%22%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22type%22%3A%22commit%22%2C%22parents%22%3A%5B%5D%2C%22author%22%3A%22Peter%20Cottle%22%2C%22createTime%22%3A%22Mon%20Nov%2005%202012%2000%3A56%3A47%20GMT-0800%20%28PST%29%22%2C%22commitMessage%22%3A%22Quick%20Commit.%20Go%20Bears%21%22%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22type%22%3A%22commit%22%2C%22parents%22%3A%5B%22C0%22%5D%2C%22author%22%3A%22Peter%20Cottle%22%2C%22createTime%22%3A%22Mon%20Nov%2005%202012%2000%3A56%3A47%20GMT-0800%20%28PST%29%22%2C%22commitMessage%22%3A%22Quick%20Commit.%20Go%20Bears%21%22%2C%22id%22%3A%22C1%22%7D%7D%2C%22HEAD%22%3A%7B%22id%22%3A%22HEAD%22%2C%22target%22%3A%22master%22%2C%22type%22%3A%22general%20ref%22%7D%7D"));
|
||||||
this.loadTree(defaultTree);
|
this.loadTree(defaultTree);
|
||||||
};
|
};
|
||||||
|
@ -248,7 +249,7 @@ GitEngine.prototype.getOrMakeRecursive = function(tree, createdSoFar, objID) {
|
||||||
return commit;
|
return commit;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error('ruh rho!! unsupported tyep for ' + objID);
|
throw new Error('ruh rho!! unsupported type for ' + objID);
|
||||||
};
|
};
|
||||||
|
|
||||||
GitEngine.prototype.tearDown = function() {
|
GitEngine.prototype.tearDown = function() {
|
||||||
|
|
|
@ -38,31 +38,6 @@ TreeCompare.prototype.compareBranchesWithinTrees = function(treeA, treeB, branch
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
TreeCompare.prototype.getRecurseCompare = function(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;
|
|
||||||
};
|
|
||||||
return recurseCompare;
|
|
||||||
};
|
|
||||||
|
|
||||||
TreeCompare.prototype.compareBranchWithinTrees = function(treeA, treeB, branchName) {
|
TreeCompare.prototype.compareBranchWithinTrees = function(treeA, treeB, branchName) {
|
||||||
treeA = this.convertTreeSafe(treeA);
|
treeA = this.convertTreeSafe(treeA);
|
||||||
treeB = this.convertTreeSafe(treeB);
|
treeB = this.convertTreeSafe(treeB);
|
||||||
|
@ -76,6 +51,106 @@ TreeCompare.prototype.compareBranchWithinTrees = function(treeA, treeB, branchNa
|
||||||
recurseCompare(treeA.commits[branchA.target], treeB.commits[branchB.target]);
|
recurseCompare(treeA.commits[branchA.target], treeB.commits[branchB.target]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TreeCompare.prototype.compareAllBranchesWithinTreesHashAgnostic = function(treeA, treeB) {
|
||||||
|
// we can't DRY unfortunately here because we need a special _.isEqual function
|
||||||
|
// for both the recursive compare and the branch compare
|
||||||
|
treeA = this.convertTreeSafe(treeA);
|
||||||
|
treeB = this.convertTreeSafe(treeB);
|
||||||
|
this.reduceTreeFields([treeA, treeB]);
|
||||||
|
|
||||||
|
// get a function to compare branch objects without hashes
|
||||||
|
var compareBranchObjs = _.bind(function(branchA, branchB) {
|
||||||
|
if (!branchA || !branchB) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
branchA.target = this.getBaseRef(branchA.target);
|
||||||
|
branchB.target = this.getBaseRef(branchB.target);
|
||||||
|
|
||||||
|
return _.isEqual(branchA, branchB);
|
||||||
|
}, this);
|
||||||
|
// and a function to compare recursively without worrying about hashes
|
||||||
|
var recurseCompare = this.getRecurseCompareHashAgnostic(treeA, treeB);
|
||||||
|
|
||||||
|
var allBranches = _.extend(
|
||||||
|
{},
|
||||||
|
treeA.branches,
|
||||||
|
treeB.branches
|
||||||
|
);
|
||||||
|
|
||||||
|
var result = true;
|
||||||
|
_.each(allBranches, function(branchObj, branchName) {
|
||||||
|
branchA = treeA.branches[branchName];
|
||||||
|
branchB = treeB.branches[branchName];
|
||||||
|
|
||||||
|
result = result && compareBranchObjs(branchA, branchB) &&
|
||||||
|
recurseCompare(treeA.commits[branchA.target], treeB.commits[branchB.target]);
|
||||||
|
}, this);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
TreeCompare.prototype.getBaseRef = function(ref) {
|
||||||
|
var idRegex = /^C(\d+)/;
|
||||||
|
var bits = idRegex.exec(ref);
|
||||||
|
if (!bits) { throw new Error('no regex matchy for ' + ref); }
|
||||||
|
// no matter what hash this is (aka C1', C1'', C1'^3, etc) we
|
||||||
|
// return C1
|
||||||
|
return 'C' + bits[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
TreeCompare.prototype.getRecurseCompareHashAgnostic = function(treeA, treeB) {
|
||||||
|
// here we pass in a special comparison function to pass into the base
|
||||||
|
// recursive compare.
|
||||||
|
|
||||||
|
// some buildup functions
|
||||||
|
var getStrippedCommitCopy = _.bind(function(commit) {
|
||||||
|
return _.extend(
|
||||||
|
{},
|
||||||
|
commit,
|
||||||
|
{id: this.getBaseRef(commit.id)
|
||||||
|
});
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
var isEqual = function(commitA, commitB) {
|
||||||
|
return _.isEqual(
|
||||||
|
getStrippedCommitCopy(commitA),
|
||||||
|
getStrippedCommitCopy(commitB)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
return this.getRecurseCompare(treeA, treeB, {isEqual: isEqual});
|
||||||
|
};
|
||||||
|
|
||||||
|
TreeCompare.prototype.getRecurseCompare = function(treeA, treeB, options) {
|
||||||
|
options = options || {};
|
||||||
|
|
||||||
|
// 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 = options.isEqual ?
|
||||||
|
options.isEqual(commitA, commitB) : _.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. for merge commits this will duplicate some of the
|
||||||
|
// checking (because we aren't doing graph search) but it's not a huge deal
|
||||||
|
var allParents = _.unique(commitA.parents.concat(commitB.parents));
|
||||||
|
_.each(allParents, function(pAid, index) {
|
||||||
|
var pBid = commitB.parents[index];
|
||||||
|
|
||||||
|
// if treeA or treeB doesn't have this parent,
|
||||||
|
// then we get an undefined child which is fine when we pass into _.isEqual
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
return recurseCompare;
|
||||||
|
};
|
||||||
|
|
||||||
TreeCompare.prototype.convertTreeSafe = function(tree) {
|
TreeCompare.prototype.convertTreeSafe = function(tree) {
|
||||||
if (typeof tree == 'string') {
|
if (typeof tree == 'string') {
|
||||||
return JSON.parse(unescape(tree));
|
return JSON.parse(unescape(tree));
|
||||||
|
|
11
todo.txt
11
todo.txt
|
@ -1,11 +1,20 @@
|
||||||
|
Mega Things
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
[ ] origin support
|
||||||
|
|
||||||
|
|
||||||
Big Things
|
Big Things
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
[ ] compare settings for a level!!! integrated into builder...
|
[ ] compare settings for a level!!! integrated into builder...
|
||||||
|
[ ] hash agnostic comparison
|
||||||
|
[ ] rebase -i solution demonstration (blink and fade thing)
|
||||||
|
[ ] hash agnotisc comparison with asserts for ammends
|
||||||
|
[ ] tree pruning
|
||||||
|
|
||||||
Medium things:
|
Medium things:
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
[ ] fix clickthrough when goal and start are shown
|
[ ] fix clickthrough when goal and start are shown
|
||||||
[ ] animating lock refactor -- not just a boolean, but a stack
|
[ ] animating lock refactor -- not just a boolean, but a stack?
|
||||||
[ ] fix refreshing during solution animation
|
[ ] fix refreshing during solution animation
|
||||||
|
|
||||||
Cases to handle / things to edit
|
Cases to handle / things to edit
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue