mirror of
https://github.com/pcottle/learnGitBranching.git
synced 2025-06-25 15:38:33 +02:00
[Origin] Implement basic git fetch force need to fix up animations
This commit is contained in:
parent
3a23973a9a
commit
6080d324ce
9 changed files with 468 additions and 73 deletions
354
build/bundle.js
354
build/bundle.js
|
@ -6427,6 +6427,7 @@ var Level = Sandbox.extend({
|
|||
finishAnimationChain
|
||||
.then(function() {
|
||||
if (!skipFinishDialog && nextLevel) {
|
||||
log.choseNextLevel(nextLevel.id);
|
||||
Main.getEventBaton().trigger(
|
||||
'commandSubmitted',
|
||||
'level ' + nextLevel.id
|
||||
|
@ -6567,6 +6568,10 @@ exports.showLevelSolution = function(levelName) {
|
|||
log('levels', 'showedLevelSolution', levelName);
|
||||
};
|
||||
|
||||
exports.choseNextLevel = function(levelID) {
|
||||
log('levels', 'nextLevelChosen', levelID);
|
||||
};
|
||||
|
||||
exports.levelSelected = function(levelName) {
|
||||
log('levels', 'levelSelected', levelName);
|
||||
};
|
||||
|
@ -7131,6 +7136,34 @@ GitEngine.prototype.isOrigin = function() {
|
|||
return !!this.localRepo;
|
||||
};
|
||||
|
||||
GitEngine.prototype.exportTreeForBranch = function(branchName) {
|
||||
// this method exports the tree and then prunes everything that
|
||||
// is not connected to branchname
|
||||
var tree = this.exportTree();
|
||||
// get the upstream set
|
||||
var set = this.getUpstreamSet(branchName);
|
||||
// now loop through and delete commits
|
||||
var commitsToLoop = tree.commits;
|
||||
tree.commits = {};
|
||||
_.each(commitsToLoop, function(commit, id) {
|
||||
if (set[id]) {
|
||||
// if included in target branch
|
||||
tree.commits[id] = commit;
|
||||
}
|
||||
});
|
||||
|
||||
var branchesToLoop = tree.branches;
|
||||
tree.branches = {};
|
||||
_.each(branchesToLoop, function(branch, id) {
|
||||
if (id === branchName) {
|
||||
tree.branches[id] = branch;
|
||||
}
|
||||
});
|
||||
|
||||
tree.HEAD.target = branchName;
|
||||
return tree;
|
||||
};
|
||||
|
||||
GitEngine.prototype.exportTree = function() {
|
||||
// need to export all commits, their connectivity / messages, branches, and state of head.
|
||||
// this would be simple if didn't have circular structures.... :P
|
||||
|
@ -7254,17 +7287,18 @@ GitEngine.prototype.makeOrigin = function(treeString) {
|
|||
msg: intl.str('git-error-origin-exists')
|
||||
});
|
||||
}
|
||||
treeString = treeString || this.printTree(this.exportTreeForBranch('master'));
|
||||
|
||||
// this is super super ugly but a necessary hack because of the way LGB was
|
||||
// originally designed. We need to get to the top level visualization from
|
||||
// the git engine -- aka we need to access our own visuals, then the
|
||||
// visualization and ask the main vis to create a new vis/git pair. Then
|
||||
// we grab the gitengine out of that and assign that as our origin repo
|
||||
// which connects the two
|
||||
// which connects the two. epic
|
||||
var masterVis = this.gitVisuals.getVisualization();
|
||||
var originVis = masterVis.makeOrigin({
|
||||
localRepo: this,
|
||||
treeString: treeString || this.printTree()
|
||||
treeString: treeString
|
||||
});
|
||||
|
||||
// defer the starting of our animation until origin has been created
|
||||
|
@ -7278,6 +7312,17 @@ GitEngine.prototype.makeOrigin = function(treeString) {
|
|||
this.animationQueue.start();
|
||||
}, this);
|
||||
|
||||
// TODO handle the case where the master target on origin is not present
|
||||
// locally, so we have to go up the chain. for now we assume the master on
|
||||
// origin is at least present
|
||||
var originTree = JSON.parse(unescape(treeString));
|
||||
var originMasterTarget = originTree.branches.master.target;
|
||||
var originMaster = this.makeBranch(
|
||||
'o/master',
|
||||
this.getCommitFromRef(originMasterTarget)
|
||||
);
|
||||
originMaster.set('remote', true);
|
||||
|
||||
// add a simple refresh animation
|
||||
this.animationFactory.refreshTree(this.animationQueue, this.gitVisuals);
|
||||
};
|
||||
|
@ -7422,7 +7467,7 @@ GitEngine.prototype.validateBranchName = function(name) {
|
|||
return name;
|
||||
};
|
||||
|
||||
GitEngine.prototype.makeBranch = function(id, target) {
|
||||
GitEngine.prototype.validateAndMakeBranch = function(id, target) {
|
||||
id = this.validateBranchName(id);
|
||||
if (this.refs[id]) {
|
||||
throw new GitError({
|
||||
|
@ -7433,6 +7478,10 @@ GitEngine.prototype.makeBranch = function(id, target) {
|
|||
});
|
||||
}
|
||||
|
||||
this.makeBranch(id, target);
|
||||
};
|
||||
|
||||
GitEngine.prototype.makeBranch = function(id, target) {
|
||||
var branch = new Branch({
|
||||
target: target,
|
||||
id: id
|
||||
|
@ -7483,7 +7532,20 @@ GitEngine.prototype.printBranches = function(branches) {
|
|||
|
||||
GitEngine.prototype.getUniqueID = function() {
|
||||
var id = this.uniqueId('C');
|
||||
while (this.refs[id]) {
|
||||
|
||||
var hasID = _.bind(function(idToCheck) {
|
||||
// loop through and see if we have it locally or
|
||||
// remotely
|
||||
if (this.refs[idToCheck]) {
|
||||
return true;
|
||||
}
|
||||
if (this.origin && this.origin.refs[idToCheck]) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}, this);
|
||||
|
||||
while (hasID(id)) {
|
||||
id = this.uniqueId('C');
|
||||
}
|
||||
return id;
|
||||
|
@ -7576,10 +7638,6 @@ GitEngine.prototype.revertStarter = function() {
|
|||
}
|
||||
};
|
||||
|
||||
GitEngine.prototype.originInitStarter = function() {
|
||||
this.makeOrigin(this.printTree());
|
||||
};
|
||||
|
||||
GitEngine.prototype.revert = function(whichCommits) {
|
||||
// for each commit, we want to revert it
|
||||
var toRebase = [];
|
||||
|
@ -7710,7 +7768,78 @@ GitEngine.prototype.cherrypickStarter = function() {
|
|||
this.animationFactory.rebaseAnimation(this.animationQueue, animationResponse, this, this.gitVisuals);
|
||||
};
|
||||
|
||||
/*************************************
|
||||
* Origin stuff!
|
||||
************************************/
|
||||
|
||||
GitEngine.prototype.fetchStarter = function() {
|
||||
if (!this.hasOrigin()) {
|
||||
throw new GitError({
|
||||
msg: intl.str('git-error-origin-required')
|
||||
});
|
||||
}
|
||||
this.acceptNoGeneralArgs();
|
||||
this.fetch();
|
||||
};
|
||||
|
||||
GitEngine.prototype.fetch = function() {
|
||||
// TODO refactor to use rebase animation stuff!!
|
||||
// ok so we essentially are always in "-force" mode, since we always assume
|
||||
// the origin commits are downstream of where we are. Here is the outline:
|
||||
//
|
||||
// first we get the commits we need by exporting the origin tree and
|
||||
// walking upwards until we hit the upstream set defined by origin/master.
|
||||
//
|
||||
// then we simply set the target of o/master to the target of master on
|
||||
// the origin branch
|
||||
var oldCommits = this.exportTree().commits;
|
||||
// HAX HAX omg we will abuse our tree instantiation here :D
|
||||
var originTree = this.origin.exportTree();
|
||||
_.each(originTree.commits, function(commit, id) {
|
||||
// if we have it, no worries
|
||||
if (this.refs[id]) {
|
||||
return;
|
||||
}
|
||||
// go make it!
|
||||
var downloadedCommit = this.getOrMakeRecursive(originTree, this.refs, id);
|
||||
this.commitCollection.add(downloadedCommit);
|
||||
}, this);
|
||||
|
||||
// since we now might have many commits more than before, lets
|
||||
// check all the ones that didn't use to exist and make animations
|
||||
var newCommits = this.exportTree().commits;
|
||||
var commitsToAnimate = [];
|
||||
_.each(newCommits, function(commit, id) {
|
||||
if (oldCommits[id]) {
|
||||
return;
|
||||
}
|
||||
commitsToAnimate.push(this.refs[id]);
|
||||
}, this);
|
||||
|
||||
// now sort by id...
|
||||
commitsToAnimate.sort(_.bind(this.idSortFunc, this));
|
||||
|
||||
_.each(commitsToAnimate, function(newCommit) {
|
||||
this.animationFactory.genCommitBirthAnimation(
|
||||
this.animationQueue,
|
||||
newCommit,
|
||||
this.gitVisuals
|
||||
);
|
||||
}, this);
|
||||
|
||||
var originLocation = this.origin.exportTree().branches.master.target;
|
||||
// yay! now we just set o/master and do a simple refresh
|
||||
this.setTargetLocation(this.refs['o/master'], this.refs[originLocation]);
|
||||
this.animationFactory.refreshTree(this.animationQueue, this.gitVisuals);
|
||||
};
|
||||
|
||||
GitEngine.prototype.originInitStarter = function() {
|
||||
this.acceptNoGeneralArgs();
|
||||
this.makeOrigin(this.printTree(this.exportTreeForBranch('master')));
|
||||
};
|
||||
|
||||
GitEngine.prototype.fakeTeamworkStarter = function() {
|
||||
this.acceptNoGeneralArgs();
|
||||
if (!this.hasOrigin()) {
|
||||
throw new GitError({
|
||||
msg: intl.str('git-error-origin-required')
|
||||
|
@ -7718,9 +7847,6 @@ GitEngine.prototype.fakeTeamworkStarter = function() {
|
|||
}
|
||||
|
||||
var id = this.getUniqueID();
|
||||
// fill refs so it is not grabbed again
|
||||
this.refs[id] = {};
|
||||
|
||||
this.origin.receiveTeamwork(id, this.animationQueue);
|
||||
};
|
||||
|
||||
|
@ -7862,6 +7988,7 @@ GitEngine.prototype.resolveRelativeRef = function(commit, relative) {
|
|||
};
|
||||
|
||||
GitEngine.prototype.resolveStringRef = function(ref) {
|
||||
ref = this.crappyUnescape(ref);
|
||||
if (this.refs[ref]) {
|
||||
return this.refs[ref];
|
||||
}
|
||||
|
@ -8440,7 +8567,7 @@ GitEngine.prototype.checkoutStarter = function() {
|
|||
|
||||
this.validateArgBounds(this.generalArgs, 1, 1);
|
||||
|
||||
this.checkout(this.unescapeQuotes(this.generalArgs[0]));
|
||||
this.checkout(this.crappyUnescape(this.generalArgs[0]));
|
||||
};
|
||||
|
||||
GitEngine.prototype.checkout = function(idOrTarget) {
|
||||
|
@ -8452,6 +8579,11 @@ GitEngine.prototype.checkout = function(idOrTarget) {
|
|||
}
|
||||
|
||||
var type = target.get('type');
|
||||
// check if this is an origin branch, and if so go to the commit referenced
|
||||
if (type === 'branch' && target.getIsRemote()) {
|
||||
target = this.getCommitFromRef(target.get('id'));
|
||||
}
|
||||
|
||||
if (type !== 'branch' && type !== 'commit') {
|
||||
throw new GitError({
|
||||
msg: intl.str('git-error-options')
|
||||
|
@ -8520,7 +8652,7 @@ GitEngine.prototype.forceBranch = function(branchName, where) {
|
|||
|
||||
GitEngine.prototype.branch = function(name, ref) {
|
||||
var target = this.getCommitFromRef(ref);
|
||||
this.makeBranch(name, target);
|
||||
this.validateAndMakeBranch(name, target);
|
||||
};
|
||||
|
||||
GitEngine.prototype.deleteBranch = function(name) {
|
||||
|
@ -8548,8 +8680,8 @@ GitEngine.prototype.deleteBranch = function(name) {
|
|||
}
|
||||
};
|
||||
|
||||
GitEngine.prototype.unescapeQuotes = function(str) {
|
||||
return str.replace(/'/g, "'");
|
||||
GitEngine.prototype.crappyUnescape = function(str) {
|
||||
return str.replace(/'/g, "'").replace(///g, '/');
|
||||
};
|
||||
|
||||
GitEngine.prototype.filterError = function(err) {
|
||||
|
@ -8802,11 +8934,11 @@ var Ref = Backbone.Model.extend({
|
|||
var Branch = Ref.extend({
|
||||
defaults: {
|
||||
visBranch: null,
|
||||
origin: null
|
||||
remote: false
|
||||
},
|
||||
|
||||
getIsRemote: function() {
|
||||
return this.get('origin') !== null;
|
||||
return this.get('remote');
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
|
@ -13215,6 +13347,7 @@ var regexMap = {
|
|||
'git status': /^git +status($|\s)/,
|
||||
'git cherry-pick': /^git +cherry-pick($|\s)/,
|
||||
'git fakeTeamwork': /^git +fakeTeamwork *?$/,
|
||||
'git fetch': /^git +fetch *?$/,
|
||||
'git originInit': /^git +originInit *?$/
|
||||
};
|
||||
|
||||
|
@ -13301,6 +13434,7 @@ GitOptionParser.prototype.getMasterOptionMap = function() {
|
|||
revert: {},
|
||||
show: {},
|
||||
originInit: {},
|
||||
fetch: {},
|
||||
fakeTeamwork: {}
|
||||
};
|
||||
};
|
||||
|
@ -16478,12 +16612,8 @@ var VisBranch = VisBase.extend({
|
|||
|
||||
// easy logic first
|
||||
if (!this.get('isHead')) {
|
||||
if (this.getIsRemote()) {
|
||||
return (overThreshold) ? 1 : -1;
|
||||
} else {
|
||||
return (overThreshold) ? -1 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
// now for HEAD....
|
||||
if (overThreshold) {
|
||||
|
@ -16687,8 +16817,9 @@ var VisBranch = VisBase.extend({
|
|||
getName: function() {
|
||||
var name = this.get('branch').getName();
|
||||
var selected = this.get('branch') === this.gitEngine.HEAD.get('target');
|
||||
var isRemote = this.getIsRemote();
|
||||
|
||||
var after = (selected && !this.getIsInOrigin()) ? '*' : '';
|
||||
var after = (selected && !this.getIsInOrigin() && !isRemote) ? '*' : '';
|
||||
return name + after;
|
||||
},
|
||||
|
||||
|
@ -16826,7 +16957,7 @@ var VisBranch = VisBase.extend({
|
|||
var rectSize = this.getRectSize();
|
||||
|
||||
var arrowPath = this.getArrowPath();
|
||||
var dashArray = (this.getIsRemote() || this.getIsInOrigin()) ?
|
||||
var dashArray = (this.getIsInOrigin()) ?
|
||||
GRAPHICS.originDash : '';
|
||||
var cursorStyle = (this.shouldDisableClick()) ?
|
||||
'auto' :
|
||||
|
@ -22379,6 +22510,7 @@ var regexMap = {
|
|||
'git status': /^git +status($|\s)/,
|
||||
'git cherry-pick': /^git +cherry-pick($|\s)/,
|
||||
'git fakeTeamwork': /^git +fakeTeamwork *?$/,
|
||||
'git fetch': /^git +fetch *?$/,
|
||||
'git originInit': /^git +originInit *?$/
|
||||
};
|
||||
|
||||
|
@ -22465,6 +22597,7 @@ GitOptionParser.prototype.getMasterOptionMap = function() {
|
|||
revert: {},
|
||||
show: {},
|
||||
originInit: {},
|
||||
fetch: {},
|
||||
fakeTeamwork: {}
|
||||
};
|
||||
};
|
||||
|
@ -22748,6 +22881,34 @@ GitEngine.prototype.isOrigin = function() {
|
|||
return !!this.localRepo;
|
||||
};
|
||||
|
||||
GitEngine.prototype.exportTreeForBranch = function(branchName) {
|
||||
// this method exports the tree and then prunes everything that
|
||||
// is not connected to branchname
|
||||
var tree = this.exportTree();
|
||||
// get the upstream set
|
||||
var set = this.getUpstreamSet(branchName);
|
||||
// now loop through and delete commits
|
||||
var commitsToLoop = tree.commits;
|
||||
tree.commits = {};
|
||||
_.each(commitsToLoop, function(commit, id) {
|
||||
if (set[id]) {
|
||||
// if included in target branch
|
||||
tree.commits[id] = commit;
|
||||
}
|
||||
});
|
||||
|
||||
var branchesToLoop = tree.branches;
|
||||
tree.branches = {};
|
||||
_.each(branchesToLoop, function(branch, id) {
|
||||
if (id === branchName) {
|
||||
tree.branches[id] = branch;
|
||||
}
|
||||
});
|
||||
|
||||
tree.HEAD.target = branchName;
|
||||
return tree;
|
||||
};
|
||||
|
||||
GitEngine.prototype.exportTree = function() {
|
||||
// need to export all commits, their connectivity / messages, branches, and state of head.
|
||||
// this would be simple if didn't have circular structures.... :P
|
||||
|
@ -22871,17 +23032,18 @@ GitEngine.prototype.makeOrigin = function(treeString) {
|
|||
msg: intl.str('git-error-origin-exists')
|
||||
});
|
||||
}
|
||||
treeString = treeString || this.printTree(this.exportTreeForBranch('master'));
|
||||
|
||||
// this is super super ugly but a necessary hack because of the way LGB was
|
||||
// originally designed. We need to get to the top level visualization from
|
||||
// the git engine -- aka we need to access our own visuals, then the
|
||||
// visualization and ask the main vis to create a new vis/git pair. Then
|
||||
// we grab the gitengine out of that and assign that as our origin repo
|
||||
// which connects the two
|
||||
// which connects the two. epic
|
||||
var masterVis = this.gitVisuals.getVisualization();
|
||||
var originVis = masterVis.makeOrigin({
|
||||
localRepo: this,
|
||||
treeString: treeString || this.printTree()
|
||||
treeString: treeString
|
||||
});
|
||||
|
||||
// defer the starting of our animation until origin has been created
|
||||
|
@ -22895,6 +23057,17 @@ GitEngine.prototype.makeOrigin = function(treeString) {
|
|||
this.animationQueue.start();
|
||||
}, this);
|
||||
|
||||
// TODO handle the case where the master target on origin is not present
|
||||
// locally, so we have to go up the chain. for now we assume the master on
|
||||
// origin is at least present
|
||||
var originTree = JSON.parse(unescape(treeString));
|
||||
var originMasterTarget = originTree.branches.master.target;
|
||||
var originMaster = this.makeBranch(
|
||||
'o/master',
|
||||
this.getCommitFromRef(originMasterTarget)
|
||||
);
|
||||
originMaster.set('remote', true);
|
||||
|
||||
// add a simple refresh animation
|
||||
this.animationFactory.refreshTree(this.animationQueue, this.gitVisuals);
|
||||
};
|
||||
|
@ -23039,7 +23212,7 @@ GitEngine.prototype.validateBranchName = function(name) {
|
|||
return name;
|
||||
};
|
||||
|
||||
GitEngine.prototype.makeBranch = function(id, target) {
|
||||
GitEngine.prototype.validateAndMakeBranch = function(id, target) {
|
||||
id = this.validateBranchName(id);
|
||||
if (this.refs[id]) {
|
||||
throw new GitError({
|
||||
|
@ -23050,6 +23223,10 @@ GitEngine.prototype.makeBranch = function(id, target) {
|
|||
});
|
||||
}
|
||||
|
||||
this.makeBranch(id, target);
|
||||
};
|
||||
|
||||
GitEngine.prototype.makeBranch = function(id, target) {
|
||||
var branch = new Branch({
|
||||
target: target,
|
||||
id: id
|
||||
|
@ -23100,7 +23277,20 @@ GitEngine.prototype.printBranches = function(branches) {
|
|||
|
||||
GitEngine.prototype.getUniqueID = function() {
|
||||
var id = this.uniqueId('C');
|
||||
while (this.refs[id]) {
|
||||
|
||||
var hasID = _.bind(function(idToCheck) {
|
||||
// loop through and see if we have it locally or
|
||||
// remotely
|
||||
if (this.refs[idToCheck]) {
|
||||
return true;
|
||||
}
|
||||
if (this.origin && this.origin.refs[idToCheck]) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}, this);
|
||||
|
||||
while (hasID(id)) {
|
||||
id = this.uniqueId('C');
|
||||
}
|
||||
return id;
|
||||
|
@ -23193,10 +23383,6 @@ GitEngine.prototype.revertStarter = function() {
|
|||
}
|
||||
};
|
||||
|
||||
GitEngine.prototype.originInitStarter = function() {
|
||||
this.makeOrigin(this.printTree());
|
||||
};
|
||||
|
||||
GitEngine.prototype.revert = function(whichCommits) {
|
||||
// for each commit, we want to revert it
|
||||
var toRebase = [];
|
||||
|
@ -23327,7 +23513,78 @@ GitEngine.prototype.cherrypickStarter = function() {
|
|||
this.animationFactory.rebaseAnimation(this.animationQueue, animationResponse, this, this.gitVisuals);
|
||||
};
|
||||
|
||||
/*************************************
|
||||
* Origin stuff!
|
||||
************************************/
|
||||
|
||||
GitEngine.prototype.fetchStarter = function() {
|
||||
if (!this.hasOrigin()) {
|
||||
throw new GitError({
|
||||
msg: intl.str('git-error-origin-required')
|
||||
});
|
||||
}
|
||||
this.acceptNoGeneralArgs();
|
||||
this.fetch();
|
||||
};
|
||||
|
||||
GitEngine.prototype.fetch = function() {
|
||||
// TODO refactor to use rebase animation stuff!!
|
||||
// ok so we essentially are always in "-force" mode, since we always assume
|
||||
// the origin commits are downstream of where we are. Here is the outline:
|
||||
//
|
||||
// first we get the commits we need by exporting the origin tree and
|
||||
// walking upwards until we hit the upstream set defined by origin/master.
|
||||
//
|
||||
// then we simply set the target of o/master to the target of master on
|
||||
// the origin branch
|
||||
var oldCommits = this.exportTree().commits;
|
||||
// HAX HAX omg we will abuse our tree instantiation here :D
|
||||
var originTree = this.origin.exportTree();
|
||||
_.each(originTree.commits, function(commit, id) {
|
||||
// if we have it, no worries
|
||||
if (this.refs[id]) {
|
||||
return;
|
||||
}
|
||||
// go make it!
|
||||
var downloadedCommit = this.getOrMakeRecursive(originTree, this.refs, id);
|
||||
this.commitCollection.add(downloadedCommit);
|
||||
}, this);
|
||||
|
||||
// since we now might have many commits more than before, lets
|
||||
// check all the ones that didn't use to exist and make animations
|
||||
var newCommits = this.exportTree().commits;
|
||||
var commitsToAnimate = [];
|
||||
_.each(newCommits, function(commit, id) {
|
||||
if (oldCommits[id]) {
|
||||
return;
|
||||
}
|
||||
commitsToAnimate.push(this.refs[id]);
|
||||
}, this);
|
||||
|
||||
// now sort by id...
|
||||
commitsToAnimate.sort(_.bind(this.idSortFunc, this));
|
||||
|
||||
_.each(commitsToAnimate, function(newCommit) {
|
||||
this.animationFactory.genCommitBirthAnimation(
|
||||
this.animationQueue,
|
||||
newCommit,
|
||||
this.gitVisuals
|
||||
);
|
||||
}, this);
|
||||
|
||||
var originLocation = this.origin.exportTree().branches.master.target;
|
||||
// yay! now we just set o/master and do a simple refresh
|
||||
this.setTargetLocation(this.refs['o/master'], this.refs[originLocation]);
|
||||
this.animationFactory.refreshTree(this.animationQueue, this.gitVisuals);
|
||||
};
|
||||
|
||||
GitEngine.prototype.originInitStarter = function() {
|
||||
this.acceptNoGeneralArgs();
|
||||
this.makeOrigin(this.printTree(this.exportTreeForBranch('master')));
|
||||
};
|
||||
|
||||
GitEngine.prototype.fakeTeamworkStarter = function() {
|
||||
this.acceptNoGeneralArgs();
|
||||
if (!this.hasOrigin()) {
|
||||
throw new GitError({
|
||||
msg: intl.str('git-error-origin-required')
|
||||
|
@ -23335,9 +23592,6 @@ GitEngine.prototype.fakeTeamworkStarter = function() {
|
|||
}
|
||||
|
||||
var id = this.getUniqueID();
|
||||
// fill refs so it is not grabbed again
|
||||
this.refs[id] = {};
|
||||
|
||||
this.origin.receiveTeamwork(id, this.animationQueue);
|
||||
};
|
||||
|
||||
|
@ -23479,6 +23733,7 @@ GitEngine.prototype.resolveRelativeRef = function(commit, relative) {
|
|||
};
|
||||
|
||||
GitEngine.prototype.resolveStringRef = function(ref) {
|
||||
ref = this.crappyUnescape(ref);
|
||||
if (this.refs[ref]) {
|
||||
return this.refs[ref];
|
||||
}
|
||||
|
@ -24057,7 +24312,7 @@ GitEngine.prototype.checkoutStarter = function() {
|
|||
|
||||
this.validateArgBounds(this.generalArgs, 1, 1);
|
||||
|
||||
this.checkout(this.unescapeQuotes(this.generalArgs[0]));
|
||||
this.checkout(this.crappyUnescape(this.generalArgs[0]));
|
||||
};
|
||||
|
||||
GitEngine.prototype.checkout = function(idOrTarget) {
|
||||
|
@ -24069,6 +24324,11 @@ GitEngine.prototype.checkout = function(idOrTarget) {
|
|||
}
|
||||
|
||||
var type = target.get('type');
|
||||
// check if this is an origin branch, and if so go to the commit referenced
|
||||
if (type === 'branch' && target.getIsRemote()) {
|
||||
target = this.getCommitFromRef(target.get('id'));
|
||||
}
|
||||
|
||||
if (type !== 'branch' && type !== 'commit') {
|
||||
throw new GitError({
|
||||
msg: intl.str('git-error-options')
|
||||
|
@ -24137,7 +24397,7 @@ GitEngine.prototype.forceBranch = function(branchName, where) {
|
|||
|
||||
GitEngine.prototype.branch = function(name, ref) {
|
||||
var target = this.getCommitFromRef(ref);
|
||||
this.makeBranch(name, target);
|
||||
this.validateAndMakeBranch(name, target);
|
||||
};
|
||||
|
||||
GitEngine.prototype.deleteBranch = function(name) {
|
||||
|
@ -24165,8 +24425,8 @@ GitEngine.prototype.deleteBranch = function(name) {
|
|||
}
|
||||
};
|
||||
|
||||
GitEngine.prototype.unescapeQuotes = function(str) {
|
||||
return str.replace(/'/g, "'");
|
||||
GitEngine.prototype.crappyUnescape = function(str) {
|
||||
return str.replace(/'/g, "'").replace(///g, '/');
|
||||
};
|
||||
|
||||
GitEngine.prototype.filterError = function(err) {
|
||||
|
@ -24419,11 +24679,11 @@ var Ref = Backbone.Model.extend({
|
|||
var Branch = Ref.extend({
|
||||
defaults: {
|
||||
visBranch: null,
|
||||
origin: null
|
||||
remote: false
|
||||
},
|
||||
|
||||
getIsRemote: function() {
|
||||
return this.get('origin') !== null;
|
||||
return this.get('remote');
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
|
@ -26467,6 +26727,7 @@ var Level = Sandbox.extend({
|
|||
finishAnimationChain
|
||||
.then(function() {
|
||||
if (!skipFinishDialog && nextLevel) {
|
||||
log.choseNextLevel(nextLevel.id);
|
||||
Main.getEventBaton().trigger(
|
||||
'commandSubmitted',
|
||||
'level ' + nextLevel.id
|
||||
|
@ -27308,6 +27569,10 @@ exports.showLevelSolution = function(levelName) {
|
|||
log('levels', 'showedLevelSolution', levelName);
|
||||
};
|
||||
|
||||
exports.choseNextLevel = function(levelID) {
|
||||
log('levels', 'nextLevelChosen', levelID);
|
||||
};
|
||||
|
||||
exports.levelSelected = function(levelName) {
|
||||
log('levels', 'levelSelected', levelName);
|
||||
};
|
||||
|
@ -32161,12 +32426,8 @@ var VisBranch = VisBase.extend({
|
|||
|
||||
// easy logic first
|
||||
if (!this.get('isHead')) {
|
||||
if (this.getIsRemote()) {
|
||||
return (overThreshold) ? 1 : -1;
|
||||
} else {
|
||||
return (overThreshold) ? -1 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
// now for HEAD....
|
||||
if (overThreshold) {
|
||||
|
@ -32370,8 +32631,9 @@ var VisBranch = VisBase.extend({
|
|||
getName: function() {
|
||||
var name = this.get('branch').getName();
|
||||
var selected = this.get('branch') === this.gitEngine.HEAD.get('target');
|
||||
var isRemote = this.getIsRemote();
|
||||
|
||||
var after = (selected && !this.getIsInOrigin()) ? '*' : '';
|
||||
var after = (selected && !this.getIsInOrigin() && !isRemote) ? '*' : '';
|
||||
return name + after;
|
||||
},
|
||||
|
||||
|
@ -32509,7 +32771,7 @@ var VisBranch = VisBase.extend({
|
|||
var rectSize = this.getRectSize();
|
||||
|
||||
var arrowPath = this.getArrowPath();
|
||||
var dashArray = (this.getIsRemote() || this.getIsInOrigin()) ?
|
||||
var dashArray = (this.getIsInOrigin()) ?
|
||||
GRAPHICS.originDash : '';
|
||||
var cursorStyle = (this.shouldDisableClick()) ?
|
||||
'auto' :
|
||||
|
|
1
build/bundle.min.6b104704.js
Normal file
1
build/bundle.min.6b104704.js
Normal file
File diff suppressed because one or more lines are too long
1
build/bundle.min.js
vendored
Normal file
1
build/bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -426,7 +426,7 @@
|
|||
For a much easier time perusing the source, see the individual files at:
|
||||
https://github.com/pcottle/learnGitBranching
|
||||
-->
|
||||
<script src="build/bundle.js"></script>
|
||||
<script src="build/bundle.min.6b104704.js"></script>
|
||||
|
||||
<!-- 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
|
||||
|
|
|
@ -63,6 +63,7 @@ var regexMap = {
|
|||
'git status': /^git +status($|\s)/,
|
||||
'git cherry-pick': /^git +cherry-pick($|\s)/,
|
||||
'git fakeTeamwork': /^git +fakeTeamwork *?$/,
|
||||
'git fetch': /^git +fetch *?$/,
|
||||
'git originInit': /^git +originInit *?$/
|
||||
};
|
||||
|
||||
|
@ -149,6 +150,7 @@ GitOptionParser.prototype.getMasterOptionMap = function() {
|
|||
revert: {},
|
||||
show: {},
|
||||
originInit: {},
|
||||
fetch: {},
|
||||
fakeTeamwork: {}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -87,6 +87,34 @@ GitEngine.prototype.isOrigin = function() {
|
|||
return !!this.localRepo;
|
||||
};
|
||||
|
||||
GitEngine.prototype.exportTreeForBranch = function(branchName) {
|
||||
// this method exports the tree and then prunes everything that
|
||||
// is not connected to branchname
|
||||
var tree = this.exportTree();
|
||||
// get the upstream set
|
||||
var set = this.getUpstreamSet(branchName);
|
||||
// now loop through and delete commits
|
||||
var commitsToLoop = tree.commits;
|
||||
tree.commits = {};
|
||||
_.each(commitsToLoop, function(commit, id) {
|
||||
if (set[id]) {
|
||||
// if included in target branch
|
||||
tree.commits[id] = commit;
|
||||
}
|
||||
});
|
||||
|
||||
var branchesToLoop = tree.branches;
|
||||
tree.branches = {};
|
||||
_.each(branchesToLoop, function(branch, id) {
|
||||
if (id === branchName) {
|
||||
tree.branches[id] = branch;
|
||||
}
|
||||
});
|
||||
|
||||
tree.HEAD.target = branchName;
|
||||
return tree;
|
||||
};
|
||||
|
||||
GitEngine.prototype.exportTree = function() {
|
||||
// need to export all commits, their connectivity / messages, branches, and state of head.
|
||||
// this would be simple if didn't have circular structures.... :P
|
||||
|
@ -210,17 +238,18 @@ GitEngine.prototype.makeOrigin = function(treeString) {
|
|||
msg: intl.str('git-error-origin-exists')
|
||||
});
|
||||
}
|
||||
treeString = treeString || this.printTree(this.exportTreeForBranch('master'));
|
||||
|
||||
// this is super super ugly but a necessary hack because of the way LGB was
|
||||
// originally designed. We need to get to the top level visualization from
|
||||
// the git engine -- aka we need to access our own visuals, then the
|
||||
// visualization and ask the main vis to create a new vis/git pair. Then
|
||||
// we grab the gitengine out of that and assign that as our origin repo
|
||||
// which connects the two
|
||||
// which connects the two. epic
|
||||
var masterVis = this.gitVisuals.getVisualization();
|
||||
var originVis = masterVis.makeOrigin({
|
||||
localRepo: this,
|
||||
treeString: treeString || this.printTree()
|
||||
treeString: treeString
|
||||
});
|
||||
|
||||
// defer the starting of our animation until origin has been created
|
||||
|
@ -234,6 +263,17 @@ GitEngine.prototype.makeOrigin = function(treeString) {
|
|||
this.animationQueue.start();
|
||||
}, this);
|
||||
|
||||
// TODO handle the case where the master target on origin is not present
|
||||
// locally, so we have to go up the chain. for now we assume the master on
|
||||
// origin is at least present
|
||||
var originTree = JSON.parse(unescape(treeString));
|
||||
var originMasterTarget = originTree.branches.master.target;
|
||||
var originMaster = this.makeBranch(
|
||||
'o/master',
|
||||
this.getCommitFromRef(originMasterTarget)
|
||||
);
|
||||
originMaster.set('remote', true);
|
||||
|
||||
// add a simple refresh animation
|
||||
this.animationFactory.refreshTree(this.animationQueue, this.gitVisuals);
|
||||
};
|
||||
|
@ -378,7 +418,7 @@ GitEngine.prototype.validateBranchName = function(name) {
|
|||
return name;
|
||||
};
|
||||
|
||||
GitEngine.prototype.makeBranch = function(id, target) {
|
||||
GitEngine.prototype.validateAndMakeBranch = function(id, target) {
|
||||
id = this.validateBranchName(id);
|
||||
if (this.refs[id]) {
|
||||
throw new GitError({
|
||||
|
@ -389,6 +429,10 @@ GitEngine.prototype.makeBranch = function(id, target) {
|
|||
});
|
||||
}
|
||||
|
||||
this.makeBranch(id, target);
|
||||
};
|
||||
|
||||
GitEngine.prototype.makeBranch = function(id, target) {
|
||||
var branch = new Branch({
|
||||
target: target,
|
||||
id: id
|
||||
|
@ -439,7 +483,20 @@ GitEngine.prototype.printBranches = function(branches) {
|
|||
|
||||
GitEngine.prototype.getUniqueID = function() {
|
||||
var id = this.uniqueId('C');
|
||||
while (this.refs[id]) {
|
||||
|
||||
var hasID = _.bind(function(idToCheck) {
|
||||
// loop through and see if we have it locally or
|
||||
// remotely
|
||||
if (this.refs[idToCheck]) {
|
||||
return true;
|
||||
}
|
||||
if (this.origin && this.origin.refs[idToCheck]) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}, this);
|
||||
|
||||
while (hasID(id)) {
|
||||
id = this.uniqueId('C');
|
||||
}
|
||||
return id;
|
||||
|
@ -532,10 +589,6 @@ GitEngine.prototype.revertStarter = function() {
|
|||
}
|
||||
};
|
||||
|
||||
GitEngine.prototype.originInitStarter = function() {
|
||||
this.makeOrigin(this.printTree());
|
||||
};
|
||||
|
||||
GitEngine.prototype.revert = function(whichCommits) {
|
||||
// for each commit, we want to revert it
|
||||
var toRebase = [];
|
||||
|
@ -666,7 +719,78 @@ GitEngine.prototype.cherrypickStarter = function() {
|
|||
this.animationFactory.rebaseAnimation(this.animationQueue, animationResponse, this, this.gitVisuals);
|
||||
};
|
||||
|
||||
/*************************************
|
||||
* Origin stuff!
|
||||
************************************/
|
||||
|
||||
GitEngine.prototype.fetchStarter = function() {
|
||||
if (!this.hasOrigin()) {
|
||||
throw new GitError({
|
||||
msg: intl.str('git-error-origin-required')
|
||||
});
|
||||
}
|
||||
this.acceptNoGeneralArgs();
|
||||
this.fetch();
|
||||
};
|
||||
|
||||
GitEngine.prototype.fetch = function() {
|
||||
// TODO refactor to use rebase animation stuff!!
|
||||
// ok so we essentially are always in "-force" mode, since we always assume
|
||||
// the origin commits are downstream of where we are. Here is the outline:
|
||||
//
|
||||
// first we get the commits we need by exporting the origin tree and
|
||||
// walking upwards until we hit the upstream set defined by origin/master.
|
||||
//
|
||||
// then we simply set the target of o/master to the target of master on
|
||||
// the origin branch
|
||||
var oldCommits = this.exportTree().commits;
|
||||
// HAX HAX omg we will abuse our tree instantiation here :D
|
||||
var originTree = this.origin.exportTree();
|
||||
_.each(originTree.commits, function(commit, id) {
|
||||
// if we have it, no worries
|
||||
if (this.refs[id]) {
|
||||
return;
|
||||
}
|
||||
// go make it!
|
||||
var downloadedCommit = this.getOrMakeRecursive(originTree, this.refs, id);
|
||||
this.commitCollection.add(downloadedCommit);
|
||||
}, this);
|
||||
|
||||
// since we now might have many commits more than before, lets
|
||||
// check all the ones that didn't use to exist and make animations
|
||||
var newCommits = this.exportTree().commits;
|
||||
var commitsToAnimate = [];
|
||||
_.each(newCommits, function(commit, id) {
|
||||
if (oldCommits[id]) {
|
||||
return;
|
||||
}
|
||||
commitsToAnimate.push(this.refs[id]);
|
||||
}, this);
|
||||
|
||||
// now sort by id...
|
||||
commitsToAnimate.sort(_.bind(this.idSortFunc, this));
|
||||
|
||||
_.each(commitsToAnimate, function(newCommit) {
|
||||
this.animationFactory.genCommitBirthAnimation(
|
||||
this.animationQueue,
|
||||
newCommit,
|
||||
this.gitVisuals
|
||||
);
|
||||
}, this);
|
||||
|
||||
var originLocation = this.origin.exportTree().branches.master.target;
|
||||
// yay! now we just set o/master and do a simple refresh
|
||||
this.setTargetLocation(this.refs['o/master'], this.refs[originLocation]);
|
||||
this.animationFactory.refreshTree(this.animationQueue, this.gitVisuals);
|
||||
};
|
||||
|
||||
GitEngine.prototype.originInitStarter = function() {
|
||||
this.acceptNoGeneralArgs();
|
||||
this.makeOrigin(this.printTree(this.exportTreeForBranch('master')));
|
||||
};
|
||||
|
||||
GitEngine.prototype.fakeTeamworkStarter = function() {
|
||||
this.acceptNoGeneralArgs();
|
||||
if (!this.hasOrigin()) {
|
||||
throw new GitError({
|
||||
msg: intl.str('git-error-origin-required')
|
||||
|
@ -674,9 +798,6 @@ GitEngine.prototype.fakeTeamworkStarter = function() {
|
|||
}
|
||||
|
||||
var id = this.getUniqueID();
|
||||
// fill refs so it is not grabbed again
|
||||
this.refs[id] = {};
|
||||
|
||||
this.origin.receiveTeamwork(id, this.animationQueue);
|
||||
};
|
||||
|
||||
|
@ -818,6 +939,7 @@ GitEngine.prototype.resolveRelativeRef = function(commit, relative) {
|
|||
};
|
||||
|
||||
GitEngine.prototype.resolveStringRef = function(ref) {
|
||||
ref = this.crappyUnescape(ref);
|
||||
if (this.refs[ref]) {
|
||||
return this.refs[ref];
|
||||
}
|
||||
|
@ -1396,7 +1518,7 @@ GitEngine.prototype.checkoutStarter = function() {
|
|||
|
||||
this.validateArgBounds(this.generalArgs, 1, 1);
|
||||
|
||||
this.checkout(this.unescapeQuotes(this.generalArgs[0]));
|
||||
this.checkout(this.crappyUnescape(this.generalArgs[0]));
|
||||
};
|
||||
|
||||
GitEngine.prototype.checkout = function(idOrTarget) {
|
||||
|
@ -1408,6 +1530,11 @@ GitEngine.prototype.checkout = function(idOrTarget) {
|
|||
}
|
||||
|
||||
var type = target.get('type');
|
||||
// check if this is an origin branch, and if so go to the commit referenced
|
||||
if (type === 'branch' && target.getIsRemote()) {
|
||||
target = this.getCommitFromRef(target.get('id'));
|
||||
}
|
||||
|
||||
if (type !== 'branch' && type !== 'commit') {
|
||||
throw new GitError({
|
||||
msg: intl.str('git-error-options')
|
||||
|
@ -1476,7 +1603,7 @@ GitEngine.prototype.forceBranch = function(branchName, where) {
|
|||
|
||||
GitEngine.prototype.branch = function(name, ref) {
|
||||
var target = this.getCommitFromRef(ref);
|
||||
this.makeBranch(name, target);
|
||||
this.validateAndMakeBranch(name, target);
|
||||
};
|
||||
|
||||
GitEngine.prototype.deleteBranch = function(name) {
|
||||
|
@ -1504,8 +1631,8 @@ GitEngine.prototype.deleteBranch = function(name) {
|
|||
}
|
||||
};
|
||||
|
||||
GitEngine.prototype.unescapeQuotes = function(str) {
|
||||
return str.replace(/'/g, "'");
|
||||
GitEngine.prototype.crappyUnescape = function(str) {
|
||||
return str.replace(/'/g, "'").replace(///g, '/');
|
||||
};
|
||||
|
||||
GitEngine.prototype.filterError = function(err) {
|
||||
|
@ -1758,11 +1885,11 @@ var Ref = Backbone.Model.extend({
|
|||
var Branch = Ref.extend({
|
||||
defaults: {
|
||||
visBranch: null,
|
||||
origin: null
|
||||
remote: false
|
||||
},
|
||||
|
||||
getIsRemote: function() {
|
||||
return this.get('origin') !== null;
|
||||
return this.get('remote');
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
|
|
|
@ -420,6 +420,7 @@ var Level = Sandbox.extend({
|
|||
finishAnimationChain
|
||||
.then(function() {
|
||||
if (!skipFinishDialog && nextLevel) {
|
||||
log.choseNextLevel(nextLevel.id);
|
||||
Main.getEventBaton().trigger(
|
||||
'commandSubmitted',
|
||||
'level ' + nextLevel.id
|
||||
|
|
|
@ -13,6 +13,10 @@ exports.showLevelSolution = function(levelName) {
|
|||
log('levels', 'showedLevelSolution', levelName);
|
||||
};
|
||||
|
||||
exports.choseNextLevel = function(levelID) {
|
||||
log('levels', 'nextLevelChosen', levelID);
|
||||
};
|
||||
|
||||
exports.levelSelected = function(levelName) {
|
||||
log('levels', 'levelSelected', levelName);
|
||||
};
|
||||
|
|
|
@ -87,12 +87,8 @@ var VisBranch = VisBase.extend({
|
|||
|
||||
// easy logic first
|
||||
if (!this.get('isHead')) {
|
||||
if (this.getIsRemote()) {
|
||||
return (overThreshold) ? 1 : -1;
|
||||
} else {
|
||||
return (overThreshold) ? -1 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
// now for HEAD....
|
||||
if (overThreshold) {
|
||||
|
@ -296,8 +292,9 @@ var VisBranch = VisBase.extend({
|
|||
getName: function() {
|
||||
var name = this.get('branch').getName();
|
||||
var selected = this.get('branch') === this.gitEngine.HEAD.get('target');
|
||||
var isRemote = this.getIsRemote();
|
||||
|
||||
var after = (selected && !this.getIsInOrigin()) ? '*' : '';
|
||||
var after = (selected && !this.getIsInOrigin() && !isRemote) ? '*' : '';
|
||||
return name + after;
|
||||
},
|
||||
|
||||
|
@ -435,7 +432,7 @@ var VisBranch = VisBase.extend({
|
|||
var rectSize = this.getRectSize();
|
||||
|
||||
var arrowPath = this.getArrowPath();
|
||||
var dashArray = (this.getIsRemote() || this.getIsInOrigin()) ?
|
||||
var dashArray = (this.getIsInOrigin()) ?
|
||||
GRAPHICS.originDash : '';
|
||||
var cursorStyle = (this.shouldDisableClick()) ?
|
||||
'auto' :
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue