NICE have rebase working and some legit refactoring. git is gettingt here

This commit is contained in:
Peter Cottle 2012-09-14 17:57:49 -07:00
parent 46c583f93d
commit acd04d6d00
3 changed files with 107 additions and 26 deletions

View file

@ -48,6 +48,7 @@ Command.prototype.getSandboxCommands = function() {
}); });
}], }],
[/^git$/, function() { [/^git$/, function() {
// TODO better git description. also help, hint, etc
throw new CommandResult({ throw new CommandResult({
msg: _.escape("\ msg: _.escape("\
Git Version \n \ Git Version \n \

View file

@ -116,15 +116,10 @@ GitEngine.prototype.logBranches = function() {
}); });
}; };
GitEngine.prototype.makeCommit = function() { GitEngine.prototype.makeCommit = function(parents, id) {
// manually copy arguments
var parents = [];
_.each(arguments, function(arg) {
parents.push(arg);
});
var commit = new Commit({ var commit = new Commit({
parents: parents parents: parents,
id: id
}); });
this.refs[commit.get('id')] = commit; this.refs[commit.get('id')] = commit;
this.collection.add(commit); this.collection.add(commit);
@ -139,6 +134,10 @@ GitEngine.prototype.acceptNoGeneralArgs = function() {
} }
}; };
GitEngine.prototype.resetStarter = function() {
};
GitEngine.prototype.commitStarter = function() { GitEngine.prototype.commitStarter = function() {
this.acceptNoGeneralArgs(); this.acceptNoGeneralArgs();
if (this.commandOptions['-a']) { if (this.commandOptions['-a']) {
@ -157,7 +156,7 @@ GitEngine.prototype.commit = function() {
targetCommit = this.resolveId('HEAD~1'); targetCommit = this.resolveId('HEAD~1');
} }
var newCommit = this.makeCommit(targetCommit); var newCommit = this.makeCommit([targetCommit]);
if (this.getDetachedHead()) { if (this.getDetachedHead()) {
events.trigger('commandProcessWarn', 'Warning!! Detached HEAD state'); events.trigger('commandProcessWarn', 'Warning!! Detached HEAD state');
this.HEAD.set('target', newCommit); this.HEAD.set('target', newCommit);
@ -225,9 +224,17 @@ GitEngine.prototype.getCommitFromRef = function(ref) {
return start; return start;
}; };
GitEngine.prototype.setLocationTarget = function(ref, target) {
var ref = this.getOneBeforeCommit(ref);
ref.set('target', target);
}
GitEngine.prototype.getOneBeforeCommit = function(ref) { GitEngine.prototype.getOneBeforeCommit = function(ref) {
// you can call this command on HEAD in detached, HEAD, or on a branch
// and it will return the ref that is one above a commit. aka
// it resolves HEAD to something that we can move the ref with
var start = this.resolveId(ref); var start = this.resolveId(ref);
if (start === this.HEAD) { if (start === this.HEAD && !this.getDetachedHead()) {
start = start.get('target'); start = start.get('target');
} }
return start; return start;
@ -272,6 +279,34 @@ GitEngine.prototype.numBackFrom = function(commit, numBack) {
return pQueue.shift(0); return pQueue.shift(0);
}; };
GitEngine.prototype.rebaseAltId = function(id) {
// this function alters an ID to add a quote to the end,
// indicating that it was rebased.
var regexMap = [
[/^C(\d+)[']{0,2}$/, function(bits) {
// this id can use another quote, so just add it
return bits[0] + "'";
}],
[/^C(\d+)[']{3}$/, function(bits) {
// here we switch from C''' to C'^4
return bits[0].slice(0, -3) + "'^4";
}],
[/^C(\d+)['][^](\d+)$/, function(bits) {
return 'C' + String(bits[1]) + "'^" + String(bits[2] + 1);
}]
];
for (var i = 0; i < regexMap.length; i++) {
var regex = regexMap[i][0];
var func = regexMap[i][1];
var results = regex.exec(id);
if (results) {
return func(results);
}
}
throw new Error('could not modify the id ' + id);
};
GitEngine.prototype.idSortFunc = function(cA, cB) { GitEngine.prototype.idSortFunc = function(cA, cB) {
// commit IDs can come in many forms: // commit IDs can come in many forms:
// C4 // C4
@ -282,16 +317,16 @@ GitEngine.prototype.idSortFunc = function(cA, cB) {
var scale = 1000; var scale = 1000;
var regexMap = [ var regexMap = [
[/^C(\d)+$/, function(bits) { [/^C(\d+)$/, function(bits) {
// return the 4 from C4 // return the 4 from C4
return scale * bits[1]; return scale * bits[1];
}], }],
[/^C(\d)([']+)$/, function(bits) { [/^C(\d+)([']+)$/, function(bits) {
// return the 4 from C4, plus the length of the quotes // return the 4 from C4, plus the length of the quotes
return scale * bits[1] + bits[2].length; return scale * bits[1] + bits[2].length;
}], }],
[/^C(\d)['][^](\d+)$/, function(bits) { [/^C(\d+)['][^](\d+)$/, function(bits) {
return scale * bits[1] + bits[2]; return scale * bits[1] + Number(bits[2]);
}] }]
]; ];
@ -324,7 +359,7 @@ GitEngine.prototype.rebaseStarter = function() {
if (this.generalArgs.length == 1) { if (this.generalArgs.length == 1) {
this.generalArgs.push('HEAD'); this.generalArgs.push('HEAD');
} }
this.rebase(generalArgs[0], generalArgs[1]); this.rebase(this.generalArgs[0], this.generalArgs[1]);
}; };
GitEngine.prototype.rebase = function(targetSource, currentLocation) { GitEngine.prototype.rebase = function(targetSource, currentLocation) {
@ -336,8 +371,7 @@ GitEngine.prototype.rebase = function(targetSource, currentLocation) {
} }
if (this.isUpstreamOf(currentLocation, targetSource)) { if (this.isUpstreamOf(currentLocation, targetSource)) {
// just set the target of this current location to the source // just set the target of this current location to the source
var currLoc = this.getOneBeforeCommit(currentLocation); this.setLocationTarget(currentLocation, this.getCommitFromRef(targetSource));
currLoc.set('target', this.getCommitFromRef(targetSource));
throw new CommandResult({ throw new CommandResult({
msg: 'Fast-forwarding...' msg: 'Fast-forwarding...'
}); });
@ -349,9 +383,50 @@ GitEngine.prototype.rebase = function(targetSource, currentLocation) {
// we need to BFS because we need to include all commits below // we need to BFS because we need to include all commits below
// pop these commits on top of targetSource and modify their ids with quotes // pop these commits on top of targetSource and modify their ids with quotes
var commonAncestor = this.getCommonAncestor(targetSource, currentLocation) var stopSet = this.getUpstreamSet(targetSource)
// now BFS from
// now BFS from here on out
var toRebaseRough = [];
var pQueue = [this.getCommitFromRef(currentLocation)];
while (pQueue.length) {
var popped = pQueue.pop();
// if its in the set, dont add it
if (stopSet[popped.get('id')]) {
continue;
}
// it's not in the set, so we need to rebase this commit
toRebaseRough.push(popped);
// keep searching
pQueue = pQueue.concat(popped.get('parents'));
pQueue.sort(this.idSortFunc);
}
// now we have the all the commits between currentLocation and the set of target.
// we need to throw out merge commits
var toRebase = [];
_.each(toRebaseRough, function(commit) {
if (commit.get('parents').length == 1) {
toRebase.push(commit);
}
});
// now sort
toRebase.sort(this.idSortFunc);
// now pop all of these commits onto targetLocation
var base = this.getCommitFromRef(targetSource);
for (var i = 0; i < toRebase.length; i++) {
var old = toRebase[i];
var newId = this.rebaseAltId(old.get('id'));
var newCommit = this.makeCommit([base], newId);
base = newCommit;
}
// now we just need to update where we are
this.setLocationTarget(currentLocation, base);
// done! haha
}; };
GitEngine.prototype.mergeStarter = function() { GitEngine.prototype.mergeStarter = function() {
@ -388,8 +463,7 @@ GitEngine.prototype.merge = function(targetSource, currentLocation) {
if (this.isUpstreamOf(currentLocation, targetSource)) { if (this.isUpstreamOf(currentLocation, targetSource)) {
// just set the target of this current location to the source // just set the target of this current location to the source
var currLoc = this.getOneBeforeCommit(currentLocation); this.setLocationTarget(currentLocation, this.getCommitFromRef(targetSource));
currLoc.set('target', this.getCommitFromRef(targetSource));
throw new CommandResult({ throw new CommandResult({
msg: 'Fast-forwarding...' msg: 'Fast-forwarding...'
}); });
@ -399,9 +473,8 @@ GitEngine.prototype.merge = function(targetSource, currentLocation) {
var parent1 = this.getCommitFromRef(currentLocation); var parent1 = this.getCommitFromRef(currentLocation);
var parent2 = this.getCommitFromRef(targetSource); var parent2 = this.getCommitFromRef(targetSource);
var commit = this.makeCommit(parent1, parent2); var commit = this.makeCommit([parent1, parent2]);
var currLoc = this.getOneBeforeCommit(currentLocation); this.setLocationTarget(currentLocation, commit)
currLoc.set('target', commit);
}; };
GitEngine.prototype.checkoutStarter = function() { GitEngine.prototype.checkoutStarter = function() {

View file

@ -76,13 +76,20 @@ var CommandLineView = Backbone.View.extend({
var value = this.$('#commandTextField').val().replace('\n', ''); var value = this.$('#commandTextField').val().replace('\n', '');
this.clear(); this.clear();
// if we are entering a real command, add it to our history
if (value.length) { if (value.length) {
this.commands.unshift(value); this.commands.unshift(value);
} }
this.index = -1; this.index = -1;
events.trigger('commandSubmitted', value); _.each(value.split(';'), function(command) {
events.trigger('commandReadyForProcess', value); command = command.replace(/^(\s+)/, '');
command = command.replace(/(\s+)$/, '');
if (command.length) {
events.trigger('commandSubmitted', command);
events.trigger('commandReadyForProcess', command);
}
});
}, },
parseOrCatch: function(value) { parseOrCatch: function(value) {