[Origin] Implement basic git fetch force need to fix up animations

This commit is contained in:
Peter Cottle 2013-05-26 23:44:07 -07:00
parent 3a23973a9a
commit 6080d324ce
9 changed files with 468 additions and 73 deletions

View file

@ -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' :

File diff suppressed because one or more lines are too long

1
build/bundle.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -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

View file

@ -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: {}
};
};

View file

@ -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(/&#x27;/g, "'");
GitEngine.prototype.crappyUnescape = function(str) {
return str.replace(/&#x27;/g, "'").replace(/&#x2F;/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() {

View file

@ -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

View file

@ -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);
};

View file

@ -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' :