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>
This commit is contained in:
parent
ba0f50d7d3
commit
f86a488e32
|
@ -68,9 +68,14 @@
|
||||||
import org.eclipse.jgit.api.errors.RefNotFoundException;
|
import org.eclipse.jgit.api.errors.RefNotFoundException;
|
||||||
import org.eclipse.jgit.api.errors.UnmergedPathsException;
|
import org.eclipse.jgit.api.errors.UnmergedPathsException;
|
||||||
import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
|
import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
|
||||||
|
import org.eclipse.jgit.diff.DiffEntry;
|
||||||
import org.eclipse.jgit.dircache.DirCacheCheckout;
|
import org.eclipse.jgit.dircache.DirCacheCheckout;
|
||||||
|
import org.eclipse.jgit.errors.AmbiguousObjectException;
|
||||||
|
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
|
||||||
|
import org.eclipse.jgit.errors.MissingObjectException;
|
||||||
import org.eclipse.jgit.junit.RepositoryTestCase;
|
import org.eclipse.jgit.junit.RepositoryTestCase;
|
||||||
import org.eclipse.jgit.lib.AbbreviatedObjectId;
|
import org.eclipse.jgit.lib.AbbreviatedObjectId;
|
||||||
|
import org.eclipse.jgit.lib.ConfigConstants;
|
||||||
import org.eclipse.jgit.lib.Constants;
|
import org.eclipse.jgit.lib.Constants;
|
||||||
import org.eclipse.jgit.lib.ObjectId;
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
import org.eclipse.jgit.lib.PersonIdent;
|
import org.eclipse.jgit.lib.PersonIdent;
|
||||||
|
@ -82,6 +87,8 @@
|
||||||
import org.eclipse.jgit.merge.MergeStrategy;
|
import org.eclipse.jgit.merge.MergeStrategy;
|
||||||
import org.eclipse.jgit.revwalk.RevCommit;
|
import org.eclipse.jgit.revwalk.RevCommit;
|
||||||
import org.eclipse.jgit.revwalk.RevWalk;
|
import org.eclipse.jgit.revwalk.RevWalk;
|
||||||
|
import org.eclipse.jgit.treewalk.TreeWalk;
|
||||||
|
import org.eclipse.jgit.treewalk.filter.TreeFilter;
|
||||||
import org.eclipse.jgit.util.FileUtils;
|
import org.eclipse.jgit.util.FileUtils;
|
||||||
import org.eclipse.jgit.util.IO;
|
import org.eclipse.jgit.util.IO;
|
||||||
import org.eclipse.jgit.util.RawParseUtils;
|
import org.eclipse.jgit.util.RawParseUtils;
|
||||||
|
@ -1567,6 +1574,136 @@ public void testRebaseWithUncommittedDelete() throws Exception {
|
||||||
assertEquals(RepositoryState.SAFE, db.getRepositoryState());
|
assertEquals(RepositoryState.SAFE, db.getRepositoryState());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRebaseWithAutoStash()
|
||||||
|
throws Exception {
|
||||||
|
// create file0, add and commit
|
||||||
|
db.getConfig().setBoolean(ConfigConstants.CONFIG_REBASE_SECTION, null,
|
||||||
|
ConfigConstants.CONFIG_KEY_AUTOSTASH, true);
|
||||||
|
writeTrashFile("file0", "file0");
|
||||||
|
git.add().addFilepattern("file0").call();
|
||||||
|
git.commit().setMessage("commit0").call();
|
||||||
|
// create file1, add and commit
|
||||||
|
writeTrashFile(FILE1, "file1");
|
||||||
|
git.add().addFilepattern(FILE1).call();
|
||||||
|
RevCommit commit = git.commit().setMessage("commit1").call();
|
||||||
|
|
||||||
|
// create topic branch and checkout / create file2, add and commit
|
||||||
|
createBranch(commit, "refs/heads/topic");
|
||||||
|
checkoutBranch("refs/heads/topic");
|
||||||
|
writeTrashFile("file2", "file2");
|
||||||
|
git.add().addFilepattern("file2").call();
|
||||||
|
git.commit().setMessage("commit2").call();
|
||||||
|
|
||||||
|
// checkout master branch / modify file1, add and commit
|
||||||
|
checkoutBranch("refs/heads/master");
|
||||||
|
writeTrashFile(FILE1, "modified file1");
|
||||||
|
git.add().addFilepattern(FILE1).call();
|
||||||
|
git.commit().setMessage("commit3").call();
|
||||||
|
|
||||||
|
// checkout topic branch / modify file0
|
||||||
|
checkoutBranch("refs/heads/topic");
|
||||||
|
writeTrashFile("file0", "unstaged modified file0");
|
||||||
|
|
||||||
|
// rebase
|
||||||
|
assertEquals(Status.OK,
|
||||||
|
git.rebase().setUpstream("refs/heads/master").call()
|
||||||
|
.getStatus());
|
||||||
|
checkFile(new File(db.getWorkTree(), "file0"),
|
||||||
|
"unstaged modified file0");
|
||||||
|
checkFile(new File(db.getWorkTree(), FILE1), "modified file1");
|
||||||
|
checkFile(new File(db.getWorkTree(), "file2"), "file2");
|
||||||
|
assertEquals("[file0, mode:100644, content:file0]"
|
||||||
|
+ "[file1, mode:100644, content:modified file1]"
|
||||||
|
+ "[file2, mode:100644, content:file2]",
|
||||||
|
indexState(CONTENT));
|
||||||
|
assertEquals(RepositoryState.SAFE, db.getRepositoryState());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRebaseWithAutoStashConflictOnApply() throws Exception {
|
||||||
|
// create file0, add and commit
|
||||||
|
db.getConfig().setBoolean(ConfigConstants.CONFIG_REBASE_SECTION, null,
|
||||||
|
ConfigConstants.CONFIG_KEY_AUTOSTASH, true);
|
||||||
|
writeTrashFile("file0", "file0");
|
||||||
|
git.add().addFilepattern("file0").call();
|
||||||
|
git.commit().setMessage("commit0").call();
|
||||||
|
// create file1, add and commit
|
||||||
|
writeTrashFile(FILE1, "file1");
|
||||||
|
git.add().addFilepattern(FILE1).call();
|
||||||
|
RevCommit commit = git.commit().setMessage("commit1").call();
|
||||||
|
|
||||||
|
// create topic branch and checkout / create file2, add and commit
|
||||||
|
createBranch(commit, "refs/heads/topic");
|
||||||
|
checkoutBranch("refs/heads/topic");
|
||||||
|
writeTrashFile("file2", "file2");
|
||||||
|
git.add().addFilepattern("file2").call();
|
||||||
|
git.commit().setMessage("commit2").call();
|
||||||
|
|
||||||
|
// checkout master branch / modify file1, add and commit
|
||||||
|
checkoutBranch("refs/heads/master");
|
||||||
|
writeTrashFile(FILE1, "modified file1");
|
||||||
|
git.add().addFilepattern(FILE1).call();
|
||||||
|
git.commit().setMessage("commit3").call();
|
||||||
|
|
||||||
|
// checkout topic branch / modify file0
|
||||||
|
checkoutBranch("refs/heads/topic");
|
||||||
|
writeTrashFile("file1", "unstaged modified file1");
|
||||||
|
|
||||||
|
// rebase
|
||||||
|
assertEquals(Status.STASH_APPLY_CONFLICTS,
|
||||||
|
git.rebase().setUpstream("refs/heads/master").call()
|
||||||
|
.getStatus());
|
||||||
|
checkFile(new File(db.getWorkTree(), "file0"), "file0");
|
||||||
|
checkFile(
|
||||||
|
new File(db.getWorkTree(), FILE1),
|
||||||
|
"<<<<<<< HEAD\nmodified file1\n=======\nunstaged modified file1\n>>>>>>> stash\n");
|
||||||
|
checkFile(new File(db.getWorkTree(), "file2"), "file2");
|
||||||
|
assertEquals(
|
||||||
|
"[file0, mode:100644, content:file0]"
|
||||||
|
+ "[file1, mode:100644, stage:1, content:file1]"
|
||||||
|
+ "[file1, mode:100644, stage:2, content:modified file1]"
|
||||||
|
+ "[file1, mode:100644, stage:3, content:unstaged modified file1]"
|
||||||
|
+ "[file2, mode:100644, content:file2]",
|
||||||
|
indexState(CONTENT));
|
||||||
|
assertEquals(RepositoryState.SAFE, db.getRepositoryState());
|
||||||
|
|
||||||
|
List<DiffEntry> diffs = getStashedDiff();
|
||||||
|
assertEquals(1, diffs.size());
|
||||||
|
assertEquals(DiffEntry.ChangeType.MODIFY, diffs.get(0).getChangeType());
|
||||||
|
assertEquals("file1", diffs.get(0).getOldPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<DiffEntry> getStashedDiff() throws AmbiguousObjectException,
|
||||||
|
IncorrectObjectTypeException, IOException, MissingObjectException {
|
||||||
|
ObjectId stashId = db.resolve("stash@{0}");
|
||||||
|
RevWalk revWalk = new RevWalk(db);
|
||||||
|
RevCommit stashCommit = revWalk.parseCommit(stashId);
|
||||||
|
List<DiffEntry> diffs = diffWorkingAgainstHead(stashCommit, revWalk);
|
||||||
|
return diffs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TreeWalk createTreeWalk() {
|
||||||
|
TreeWalk walk = new TreeWalk(db);
|
||||||
|
walk.setRecursive(true);
|
||||||
|
walk.setFilter(TreeFilter.ANY_DIFF);
|
||||||
|
return walk;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<DiffEntry> diffWorkingAgainstHead(final RevCommit commit,
|
||||||
|
RevWalk revWalk)
|
||||||
|
throws IOException {
|
||||||
|
TreeWalk walk = createTreeWalk();
|
||||||
|
RevCommit parentCommit = revWalk.parseCommit(commit.getParent(0));
|
||||||
|
try {
|
||||||
|
walk.addTree(parentCommit.getTree());
|
||||||
|
walk.addTree(commit.getTree());
|
||||||
|
return DiffEntry.scan(walk);
|
||||||
|
} finally {
|
||||||
|
walk.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private int countPicks() throws IOException {
|
private int countPicks() throws IOException {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
File todoFile = getTodoFile();
|
File todoFile = getTodoFile();
|
||||||
|
|
|
@ -70,6 +70,7 @@
|
||||||
import org.eclipse.jgit.api.errors.NoMessageException;
|
import org.eclipse.jgit.api.errors.NoMessageException;
|
||||||
import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
|
import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
|
||||||
import org.eclipse.jgit.api.errors.RefNotFoundException;
|
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.UnmergedPathsException;
|
||||||
import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
|
import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
|
||||||
import org.eclipse.jgit.diff.DiffFormatter;
|
import org.eclipse.jgit.diff.DiffFormatter;
|
||||||
|
@ -79,6 +80,7 @@
|
||||||
import org.eclipse.jgit.internal.JGitText;
|
import org.eclipse.jgit.internal.JGitText;
|
||||||
import org.eclipse.jgit.lib.AbbreviatedObjectId;
|
import org.eclipse.jgit.lib.AbbreviatedObjectId;
|
||||||
import org.eclipse.jgit.lib.AnyObjectId;
|
import org.eclipse.jgit.lib.AnyObjectId;
|
||||||
|
import org.eclipse.jgit.lib.ConfigConstants;
|
||||||
import org.eclipse.jgit.lib.Constants;
|
import org.eclipse.jgit.lib.Constants;
|
||||||
import org.eclipse.jgit.lib.NullProgressMonitor;
|
import org.eclipse.jgit.lib.NullProgressMonitor;
|
||||||
import org.eclipse.jgit.lib.ObjectId;
|
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 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
|
* The available operations
|
||||||
*/
|
*/
|
||||||
|
@ -257,6 +263,7 @@ public RebaseResult call() throws GitAPIException, NoHeadException,
|
||||||
.resolve(upstreamCommitId));
|
.resolve(upstreamCommitId));
|
||||||
break;
|
break;
|
||||||
case BEGIN:
|
case BEGIN:
|
||||||
|
autoStash();
|
||||||
if (stopAfterInitialization
|
if (stopAfterInitialization
|
||||||
|| !walk.isMergedInto(
|
|| !walk.isMergedInto(
|
||||||
walk.parseCommit(repo.resolve(Constants.HEAD)),
|
walk.parseCommit(repo.resolve(Constants.HEAD)),
|
||||||
|
@ -272,8 +279,10 @@ public RebaseResult call() throws GitAPIException, NoHeadException,
|
||||||
RebaseResult res = initFilesAndRewind();
|
RebaseResult res = initFilesAndRewind();
|
||||||
if (stopAfterInitialization)
|
if (stopAfterInitialization)
|
||||||
return RebaseResult.INTERACTIVE_PREPARED_RESULT;
|
return RebaseResult.INTERACTIVE_PREPARED_RESULT;
|
||||||
if (res != null)
|
if (res != null) {
|
||||||
|
autoStashApply();
|
||||||
return res;
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (monitor.isCancelled())
|
if (monitor.isCancelled())
|
||||||
|
@ -339,6 +348,57 @@ public RebaseResult call() throws GitAPIException, NoHeadException,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
private RebaseResult processStep(RebaseTodoLine step, boolean shouldPick)
|
||||||
throws IOException, GitAPIException {
|
throws IOException, GitAPIException {
|
||||||
if (Action.COMMENT.equals(step.getAction()))
|
if (Action.COMMENT.equals(step.getAction()))
|
||||||
|
@ -432,10 +492,13 @@ private RebaseResult cherryPickCommit(RevCommit commitToPick)
|
||||||
}
|
}
|
||||||
|
|
||||||
private RebaseResult finishRebase(RevCommit newHead,
|
private RebaseResult finishRebase(RevCommit newHead,
|
||||||
boolean lastStepWasForward) throws IOException {
|
boolean lastStepWasForward) throws IOException, GitAPIException {
|
||||||
String headName = rebaseState.readFile(HEAD_NAME);
|
String headName = rebaseState.readFile(HEAD_NAME);
|
||||||
updateHead(headName, newHead, upstreamCommit);
|
updateHead(headName, newHead, upstreamCommit);
|
||||||
|
boolean stashConflicts = autoStashApply();
|
||||||
FileUtils.delete(rebaseState.getDir(), FileUtils.RECURSIVE);
|
FileUtils.delete(rebaseState.getDir(), FileUtils.RECURSIVE);
|
||||||
|
if (stashConflicts)
|
||||||
|
return RebaseResult.STASH_APPLY_CONFLICTS_RESULT;
|
||||||
if (lastStepWasForward || newHead == null)
|
if (lastStepWasForward || newHead == null)
|
||||||
return RebaseResult.FAST_FORWARD_RESULT;
|
return RebaseResult.FAST_FORWARD_RESULT;
|
||||||
return RebaseResult.OK_RESULT;
|
return RebaseResult.OK_RESULT;
|
||||||
|
@ -809,16 +872,9 @@ private RebaseResult initFilesAndRewind() throws IOException,
|
||||||
// we need to store everything into files so that we can implement
|
// we need to store everything into files so that we can implement
|
||||||
// --skip, --continue, and --abort
|
// --skip, --continue, and --abort
|
||||||
|
|
||||||
Ref head = repo.getRef(Constants.HEAD);
|
Ref head = getHead();
|
||||||
if (head == null || head.getObjectId() == null)
|
|
||||||
throw new RefNotFoundException(MessageFormat.format(
|
|
||||||
JGitText.get().refNotResolved, Constants.HEAD));
|
|
||||||
|
|
||||||
String headName;
|
String headName = getHeadName(head);
|
||||||
if (head.isSymbolic())
|
|
||||||
headName = head.getTarget().getName();
|
|
||||||
else
|
|
||||||
headName = head.getObjectId().getName();
|
|
||||||
ObjectId headId = head.getObjectId();
|
ObjectId headId = head.getObjectId();
|
||||||
if (headId == null)
|
if (headId == null)
|
||||||
throw new RefNotFoundException(MessageFormat.format(
|
throw new RefNotFoundException(MessageFormat.format(
|
||||||
|
@ -857,7 +913,7 @@ else if (!isInteractive() && walk.isMergedInto(headCommit, upstream)) {
|
||||||
|
|
||||||
Collections.reverse(cherryPickList);
|
Collections.reverse(cherryPickList);
|
||||||
// create the folder for the meta information
|
// create the folder for the meta information
|
||||||
FileUtils.mkdir(rebaseState.getDir());
|
FileUtils.mkdir(rebaseState.getDir(), true);
|
||||||
|
|
||||||
repo.writeOrigHead(headId);
|
repo.writeOrigHead(headId);
|
||||||
rebaseState.createFile(REBASE_HEAD, headId.name());
|
rebaseState.createFile(REBASE_HEAD, headId.name());
|
||||||
|
@ -893,6 +949,23 @@ else if (!isInteractive() && walk.isMergedInto(headCommit, upstream)) {
|
||||||
return null;
|
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() {
|
private boolean isInteractive() {
|
||||||
return interactiveHandler != null;
|
return interactiveHandler != null;
|
||||||
}
|
}
|
||||||
|
@ -907,10 +980,7 @@ private boolean isInteractive() {
|
||||||
*/
|
*/
|
||||||
public RevCommit tryFastForward(RevCommit newCommit) throws IOException,
|
public RevCommit tryFastForward(RevCommit newCommit) throws IOException,
|
||||||
GitAPIException {
|
GitAPIException {
|
||||||
Ref head = repo.getRef(Constants.HEAD);
|
Ref head = getHead();
|
||||||
if (head == null || head.getObjectId() == null)
|
|
||||||
throw new RefNotFoundException(MessageFormat.format(
|
|
||||||
JGitText.get().refNotResolved, Constants.HEAD));
|
|
||||||
|
|
||||||
ObjectId headId = head.getObjectId();
|
ObjectId headId = head.getObjectId();
|
||||||
if (headId == null)
|
if (headId == null)
|
||||||
|
@ -920,11 +990,7 @@ public RevCommit tryFastForward(RevCommit newCommit) throws IOException,
|
||||||
if (walk.isMergedInto(newCommit, headCommit))
|
if (walk.isMergedInto(newCommit, headCommit))
|
||||||
return newCommit;
|
return newCommit;
|
||||||
|
|
||||||
String headName;
|
String headName = getHeadName(head);
|
||||||
if (head.isSymbolic())
|
|
||||||
headName = head.getTarget().getName();
|
|
||||||
else
|
|
||||||
headName = head.getObjectId().getName();
|
|
||||||
return tryFastForward(headName, headCommit, newCommit);
|
return tryFastForward(headName, headCommit, newCommit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1004,7 +1070,8 @@ private void checkParameters() throws WrongRepositoryStateException {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private RebaseResult abort(RebaseResult result) throws IOException {
|
private RebaseResult abort(RebaseResult result) throws IOException,
|
||||||
|
GitAPIException {
|
||||||
try {
|
try {
|
||||||
ObjectId origHead = repo.readOrigHead();
|
ObjectId origHead = repo.readOrigHead();
|
||||||
String commitId = origHead != null ? origHead.name() : null;
|
String commitId = origHead != null ? origHead.name() : null;
|
||||||
|
@ -1053,9 +1120,12 @@ private RebaseResult abort(RebaseResult result) throws IOException {
|
||||||
JGitText.get().abortingRebaseFailed);
|
JGitText.get().abortingRebaseFailed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
boolean stashConflicts = autoStashApply();
|
||||||
// cleanup the files
|
// cleanup the files
|
||||||
FileUtils.delete(rebaseState.getDir(), FileUtils.RECURSIVE);
|
FileUtils.delete(rebaseState.getDir(), FileUtils.RECURSIVE);
|
||||||
repo.writeCherryPickHead(null);
|
repo.writeCherryPickHead(null);
|
||||||
|
if (stashConflicts)
|
||||||
|
return RebaseResult.STASH_APPLY_CONFLICTS_RESULT;
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -165,6 +165,18 @@ public boolean isSuccessful() {
|
||||||
public boolean isSuccessful() {
|
public boolean isSuccessful() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applying stash resulted in conflicts
|
||||||
|
*
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
STASH_APPLY_CONFLICTS {
|
||||||
|
@Override
|
||||||
|
public boolean isSuccessful() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -189,6 +201,9 @@ public boolean isSuccessful() {
|
||||||
static final RebaseResult INTERACTIVE_PREPARED_RESULT = new RebaseResult(
|
static final RebaseResult INTERACTIVE_PREPARED_RESULT = new RebaseResult(
|
||||||
Status.INTERACTIVE_PREPARED);
|
Status.INTERACTIVE_PREPARED);
|
||||||
|
|
||||||
|
static final RebaseResult STASH_APPLY_CONFLICTS_RESULT = new RebaseResult(
|
||||||
|
Status.STASH_APPLY_CONFLICTS);
|
||||||
|
|
||||||
private final Status status;
|
private final Status status;
|
||||||
|
|
||||||
private final RevCommit currentCommit;
|
private final RevCommit currentCommit;
|
||||||
|
|
|
@ -90,6 +90,8 @@ public class StashApplyCommand extends GitCommand<ObjectId> {
|
||||||
|
|
||||||
private boolean applyIndex = true;
|
private boolean applyIndex = true;
|
||||||
|
|
||||||
|
private boolean ignoreRepositoryState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create command to apply the changes of a stashed commit
|
* Create command to apply the changes of a stashed commit
|
||||||
*
|
*
|
||||||
|
@ -113,6 +115,16 @@ public StashApplyCommand setStashRef(final String stashRef) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ignoreRepositoryState
|
||||||
|
* @return {@code this}
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
public StashApplyCommand ignoreRepositoryState(boolean ignoreRepositoryState) {
|
||||||
|
this.ignoreRepositoryState = ignoreRepositoryState;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
private ObjectId getStashId() throws GitAPIException {
|
private ObjectId getStashId() throws GitAPIException {
|
||||||
final String revision = stashRef != null ? stashRef : DEFAULT_REF;
|
final String revision = stashRef != null ? stashRef : DEFAULT_REF;
|
||||||
final ObjectId stashId;
|
final ObjectId stashId;
|
||||||
|
@ -143,7 +155,8 @@ public ObjectId call() throws GitAPIException,
|
||||||
StashApplyFailureException {
|
StashApplyFailureException {
|
||||||
checkCallable();
|
checkCallable();
|
||||||
|
|
||||||
if (repo.getRepositoryState() != RepositoryState.SAFE)
|
if (!ignoreRepositoryState
|
||||||
|
&& repo.getRepositoryState() != RepositoryState.SAFE)
|
||||||
throw new WrongRepositoryStateException(MessageFormat.format(
|
throw new WrongRepositoryStateException(MessageFormat.format(
|
||||||
JGitText.get().stashApplyOnUnsafeRepository,
|
JGitText.get().stashApplyOnUnsafeRepository,
|
||||||
repo.getRepositoryState()));
|
repo.getRepositoryState()));
|
||||||
|
|
|
@ -154,6 +154,7 @@ public StashCreateCommand setPerson(PersonIdent person) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the reference to update with the stashed commit id
|
* Set the reference to update with the stashed commit id
|
||||||
|
* If null, no reference is updated
|
||||||
* <p>
|
* <p>
|
||||||
* This value defaults to {@link Constants#R_STASH}
|
* This value defaults to {@link Constants#R_STASH}
|
||||||
*
|
*
|
||||||
|
@ -185,6 +186,8 @@ private CommitBuilder createBuilder(ObjectId headId) {
|
||||||
|
|
||||||
private void updateStashRef(ObjectId commitId, PersonIdent refLogIdent,
|
private void updateStashRef(ObjectId commitId, PersonIdent refLogIdent,
|
||||||
String refLogMessage) throws IOException {
|
String refLogMessage) throws IOException {
|
||||||
|
if (ref == null)
|
||||||
|
return;
|
||||||
Ref currentRef = repo.getRef(ref);
|
Ref currentRef = repo.getRef(ref);
|
||||||
RefUpdate refUpdate = repo.updateRef(ref);
|
RefUpdate refUpdate = repo.updateRef(ref);
|
||||||
refUpdate.setNewObjectId(commitId);
|
refUpdate.setNewObjectId(commitId);
|
||||||
|
|
|
@ -77,6 +77,13 @@ public class ConfigConstants {
|
||||||
/** The "submodule" section */
|
/** The "submodule" section */
|
||||||
public static final String CONFIG_SUBMODULE_SECTION = "submodule";
|
public static final String CONFIG_SUBMODULE_SECTION = "submodule";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The "rebase" section
|
||||||
|
*
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
public static final String CONFIG_REBASE_SECTION = "rebase";
|
||||||
|
|
||||||
/** The "gc" section */
|
/** The "gc" section */
|
||||||
public static final String CONFIG_GC_SECTION = "gc";
|
public static final String CONFIG_GC_SECTION = "gc";
|
||||||
|
|
||||||
|
@ -136,6 +143,14 @@ public class ConfigConstants {
|
||||||
|
|
||||||
/** The "autosetuprebase" key */
|
/** The "autosetuprebase" key */
|
||||||
public static final String CONFIG_KEY_AUTOSETUPREBASE = "autosetuprebase";
|
public static final String CONFIG_KEY_AUTOSETUPREBASE = "autosetuprebase";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The "autostash" key
|
||||||
|
*
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
public static final String CONFIG_KEY_AUTOSTASH = "autostash";
|
||||||
|
|
||||||
/** The "name" key */
|
/** The "name" key */
|
||||||
public static final String CONFIG_KEY_NAME = "name";
|
public static final String CONFIG_KEY_NAME = "name";
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue