aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java
diff options
context:
space:
mode:
authorStefan Lay <stefan.lay@sap.com>2013-12-02 17:24:09 +0100
committerMatthias Sohn <matthias.sohn@sap.com>2013-12-04 22:02:22 +0100
commitf86a488e32906593903acb31a93a82bed8d87915 (patch)
tree377792666836715cee1ec2f4d5582641d854dce3 /org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java
parentba0f50d7d34a0a3d47f53139ba78de04b3ebdff6 (diff)
downloadjgit-f86a488e32906593903acb31a93a82bed8d87915.tar.gz
jgit-f86a488e32906593903acb31a93a82bed8d87915.zip
Implement rebase.autostash
This feature was introduced in native git with version 1.8.4. Bug: 422951 Change-Id: I42f194174d64d7ada6631e2156c2a7bf93b5e91c Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
Diffstat (limited to 'org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java114
1 files changed, 92 insertions, 22 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java
index 55cf001c6c..10b273a744 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java
@@ -70,6 +70,7 @@ import org.eclipse.jgit.api.errors.NoHeadException;
import org.eclipse.jgit.api.errors.NoMessageException;
import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
import org.eclipse.jgit.api.errors.RefNotFoundException;
+import org.eclipse.jgit.api.errors.StashApplyFailureException;
import org.eclipse.jgit.api.errors.UnmergedPathsException;
import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
import org.eclipse.jgit.diff.DiffFormatter;
@@ -79,6 +80,7 @@ import org.eclipse.jgit.dircache.DirCacheIterator;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.AbbreviatedObjectId;
import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
@@ -158,6 +160,10 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
private static final String MESSAGE_SQUASH = "message-squash"; //$NON-NLS-1$
+ private static final String AUTOSTASH = "autostash"; //$NON-NLS-1$
+
+ private static final String AUTOSTASH_MSG = "On {0}: autostash";
+
/**
* The available operations
*/
@@ -257,6 +263,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
.resolve(upstreamCommitId));
break;
case BEGIN:
+ autoStash();
if (stopAfterInitialization
|| !walk.isMergedInto(
walk.parseCommit(repo.resolve(Constants.HEAD)),
@@ -272,8 +279,10 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
RebaseResult res = initFilesAndRewind();
if (stopAfterInitialization)
return RebaseResult.INTERACTIVE_PREPARED_RESULT;
- if (res != null)
+ if (res != null) {
+ autoStashApply();
return res;
+ }
}
if (monitor.isCancelled())
@@ -339,6 +348,57 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
}
}
+ private void autoStash() throws GitAPIException, IOException {
+ if (repo.getConfig().getBoolean(ConfigConstants.CONFIG_REBASE_SECTION,
+ ConfigConstants.CONFIG_KEY_AUTOSTASH, false)) {
+ String message = MessageFormat.format(
+ AUTOSTASH_MSG,
+ Repository
+ .shortenRefName(getHeadName(getHead())));
+ RevCommit stashCommit = Git.wrap(repo).stashCreate().setRef(null)
+ .setWorkingDirectoryMessage(
+ message)
+ .call();
+ if (stashCommit != null) {
+ FileUtils.mkdir(rebaseState.getDir());
+ rebaseState.createFile(AUTOSTASH, stashCommit.getName());
+ }
+ }
+ }
+
+ private boolean autoStashApply() throws IOException, GitAPIException {
+ boolean conflicts = false;
+ if (rebaseState.getFile(AUTOSTASH).exists()) {
+ String stash = rebaseState.readFile(AUTOSTASH);
+ try {
+ Git.wrap(repo).stashApply().setStashRef(stash)
+ .ignoreRepositoryState(true).call();
+ } catch (StashApplyFailureException e) {
+ conflicts = true;
+ RevWalk rw = new RevWalk(repo);
+ ObjectId stashId = repo.resolve(stash);
+ RevCommit commit = rw.parseCommit(stashId);
+ updateStashRef(commit, commit.getAuthorIdent(),
+ commit.getShortMessage());
+ }
+ }
+ return conflicts;
+ }
+
+ private void updateStashRef(ObjectId commitId, PersonIdent refLogIdent,
+ String refLogMessage) throws IOException {
+ Ref currentRef = repo.getRef(Constants.R_STASH);
+ RefUpdate refUpdate = repo.updateRef(Constants.R_STASH);
+ refUpdate.setNewObjectId(commitId);
+ refUpdate.setRefLogIdent(refLogIdent);
+ refUpdate.setRefLogMessage(refLogMessage, false);
+ if (currentRef != null)
+ refUpdate.setExpectedOldObjectId(currentRef.getObjectId());
+ else
+ refUpdate.setExpectedOldObjectId(ObjectId.zeroId());
+ refUpdate.forceUpdate();
+ }
+
private RebaseResult processStep(RebaseTodoLine step, boolean shouldPick)
throws IOException, GitAPIException {
if (Action.COMMENT.equals(step.getAction()))
@@ -432,10 +492,13 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
}
private RebaseResult finishRebase(RevCommit newHead,
- boolean lastStepWasForward) throws IOException {
+ boolean lastStepWasForward) throws IOException, GitAPIException {
String headName = rebaseState.readFile(HEAD_NAME);
updateHead(headName, newHead, upstreamCommit);
+ boolean stashConflicts = autoStashApply();
FileUtils.delete(rebaseState.getDir(), FileUtils.RECURSIVE);
+ if (stashConflicts)
+ return RebaseResult.STASH_APPLY_CONFLICTS_RESULT;
if (lastStepWasForward || newHead == null)
return RebaseResult.FAST_FORWARD_RESULT;
return RebaseResult.OK_RESULT;
@@ -809,16 +872,9 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
// we need to store everything into files so that we can implement
// --skip, --continue, and --abort
- Ref head = repo.getRef(Constants.HEAD);
- if (head == null || head.getObjectId() == null)
- throw new RefNotFoundException(MessageFormat.format(
- JGitText.get().refNotResolved, Constants.HEAD));
+ Ref head = getHead();
- String headName;
- if (head.isSymbolic())
- headName = head.getTarget().getName();
- else
- headName = head.getObjectId().getName();
+ String headName = getHeadName(head);
ObjectId headId = head.getObjectId();
if (headId == null)
throw new RefNotFoundException(MessageFormat.format(
@@ -857,7 +913,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
Collections.reverse(cherryPickList);
// create the folder for the meta information
- FileUtils.mkdir(rebaseState.getDir());
+ FileUtils.mkdir(rebaseState.getDir(), true);
repo.writeOrigHead(headId);
rebaseState.createFile(REBASE_HEAD, headId.name());
@@ -893,6 +949,23 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
return null;
}
+ private static String getHeadName(Ref head) {
+ String headName;
+ if (head.isSymbolic())
+ headName = head.getTarget().getName();
+ else
+ headName = head.getObjectId().getName();
+ return headName;
+ }
+
+ private Ref getHead() throws IOException, RefNotFoundException {
+ Ref head = repo.getRef(Constants.HEAD);
+ if (head == null || head.getObjectId() == null)
+ throw new RefNotFoundException(MessageFormat.format(
+ JGitText.get().refNotResolved, Constants.HEAD));
+ return head;
+ }
+
private boolean isInteractive() {
return interactiveHandler != null;
}
@@ -907,10 +980,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
*/
public RevCommit tryFastForward(RevCommit newCommit) throws IOException,
GitAPIException {
- Ref head = repo.getRef(Constants.HEAD);
- if (head == null || head.getObjectId() == null)
- throw new RefNotFoundException(MessageFormat.format(
- JGitText.get().refNotResolved, Constants.HEAD));
+ Ref head = getHead();
ObjectId headId = head.getObjectId();
if (headId == null)
@@ -920,11 +990,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
if (walk.isMergedInto(newCommit, headCommit))
return newCommit;
- String headName;
- if (head.isSymbolic())
- headName = head.getTarget().getName();
- else
- headName = head.getObjectId().getName();
+ String headName = getHeadName(head);
return tryFastForward(headName, headCommit, newCommit);
}
@@ -1004,7 +1070,8 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
}
}
- private RebaseResult abort(RebaseResult result) throws IOException {
+ private RebaseResult abort(RebaseResult result) throws IOException,
+ GitAPIException {
try {
ObjectId origHead = repo.readOrigHead();
String commitId = origHead != null ? origHead.name() : null;
@@ -1053,9 +1120,12 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
JGitText.get().abortingRebaseFailed);
}
}
+ boolean stashConflicts = autoStashApply();
// cleanup the files
FileUtils.delete(rebaseState.getDir(), FileUtils.RECURSIVE);
repo.writeCherryPickHead(null);
+ if (stashConflicts)
+ return RebaseResult.STASH_APPLY_CONFLICTS_RESULT;
return result;
} finally {