diff options
author | Markus Duft <markus.duft@salomon.at> | 2012-03-09 13:36:53 +0100 |
---|---|---|
committer | Stefan Lay <stefan.lay@sap.com> | 2012-03-09 13:56:37 +0100 |
commit | edc1fee033a23189742cea1807d8029d1b77da00 (patch) | |
tree | 41ab32eb98c85110863877308ce0983e6eae437d | |
parent | c1ed9483ff77487b38587a96a74b6ebb813985da (diff) | |
download | jgit-edc1fee033a23189742cea1807d8029d1b77da00.tar.gz jgit-edc1fee033a23189742cea1807d8029d1b77da00.zip |
Fix rebase > continue when nothing left to commit.
If after resolving all conflicts nothing is left to commit, return
an according result, so that downstreams (EGit, ...) can behave like
cgit, and display a nice message informing the user.
Currently, EGit displays a "HEAD advanced fast forward" message, which
is absolutely not helpful at all.
This is the basic API revamping required to get that state communicated
to the outside world (EGit).
Bug: 336812
Change-Id: If2665005cf54a5b51c0fe80bad019fa42b0205af
3 files changed, 82 insertions, 3 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java index 672f4d86aa..648ef6f01b 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java @@ -503,6 +503,55 @@ public class RebaseCommandTest extends RepositoryTestCase { } @Test + public void testStopOnConflictAndContinueWithNoDeltaToMaster() + throws Exception { + // create file1 on master + RevCommit firstInMaster = writeFileAndCommit(FILE1, "Add file1", "1", + "2", "3"); + // change in master + writeFileAndCommit(FILE1, "change file1 in master", "1master", "2", "3"); + + checkFile(FILE1, "1master", "2", "3"); + // create a topic branch based on the first commit + createBranch(firstInMaster, "refs/heads/topic"); + checkoutBranch("refs/heads/topic"); + // we have the old content again + checkFile(FILE1, "1", "2", "3"); + + // change first line (conflicting) + writeFileAndCommit(FILE1, + "change file1 in topic\n\nThis is conflicting", "1topic", "2", + "3", "4topic"); + + RebaseResult res = git.rebase().setUpstream("refs/heads/master").call(); + assertEquals(Status.STOPPED, res.getStatus()); + + // continue should throw a meaningful exception + try { + res = git.rebase().setOperation(Operation.CONTINUE).call(); + fail("Expected Exception not thrown"); + } catch (UnmergedPathsException e) { + // expected + } + + // merge the file; the second topic commit should go through + writeFileAndAdd(FILE1, "1master", "2", "3"); + + res = git.rebase().setOperation(Operation.CONTINUE).call(); + assertNotNull(res); + assertEquals(Status.NOTHING_TO_COMMIT, res.getStatus()); + assertEquals(RepositoryState.REBASING_INTERACTIVE, + db.getRepositoryState()); + + git.rebase().setOperation(Operation.SKIP).call(); + + ObjectId headId = db.resolve(Constants.HEAD); + RevWalk rw = new RevWalk(db); + RevCommit rc = rw.parseCommit(headId); + assertEquals("change file1 in master", rc.getFullMessage()); + } + + @Test public void testStopOnConflictAndFailContinueIfFileIsDirty() throws Exception { // create file1 on master @@ -775,8 +824,15 @@ public class RebaseCommandTest extends RepositoryTestCase { res = git.rebase().setOperation(Operation.CONTINUE).call(); assertNotNull(res); - assertEquals(Status.OK, res.getStatus()); - assertEquals(RepositoryState.SAFE, db.getRepositoryState()); + + // nothing to commit. this leaves the repo state in rebase, so that the + // user can decide what to do. if he accidentally committed, reset soft, + // and continue, if he really has nothing to commit, skip. + assertEquals(Status.NOTHING_TO_COMMIT, res.getStatus()); + assertEquals(RepositoryState.REBASING_INTERACTIVE, + db.getRepositoryState()); + + git.rebase().setOperation(Operation.SKIP).call(); ObjectId headId = db.resolve(Constants.HEAD); RevWalk rw = new RevWalk(db); 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 ae73cacbe0..936f5cab8d 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java @@ -220,9 +220,19 @@ public class RebaseCommand extends GitCommand<RebaseResult> { if (monitor.isCancelled()) return abort(RebaseResult.ABORTED_RESULT); - if (operation == Operation.CONTINUE) + if (operation == Operation.CONTINUE) { newHead = continueRebase(); + if (newHead == null) { + // continueRebase() returns null only if no commit was + // neccessary. This means that no changes where left over + // after resolving all conflicts. In this case, cgit stops + // and displays a nice message to the user, telling him to + // either do changes or skip the commit instead of continue. + return RebaseResult.NOTHING_TO_COMMIT_RESULT; + } + } + if (operation == Operation.SKIP) newHead = checkoutCurrentHead(); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseResult.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseResult.java index e389d9902a..4739f16172 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseResult.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseResult.java @@ -109,6 +109,16 @@ public class RebaseResult { public boolean isSuccessful() { return true; } + }, + + /** + * Continue with nothing left to commit (possibly want skip). + */ + NOTHING_TO_COMMIT { + @Override + public boolean isSuccessful() { + return false; + } }; /** @@ -127,6 +137,9 @@ public class RebaseResult { static final RebaseResult FAST_FORWARD_RESULT = new RebaseResult( Status.FAST_FORWARD); + static final RebaseResult NOTHING_TO_COMMIT_RESULT = new RebaseResult( + Status.NOTHING_TO_COMMIT); + private final Status status; private final RevCommit currentCommit; |