| author | Markus Duft | 2012-03-09 07:36:53 (EST) |
|---|---|---|
| committer | Stefan Lay | 2012-03-09 07:56:37 (EST) |
| commit | edc1fee033a23189742cea1807d8029d1b77da00 (patch) (side-by-side diff) | |
| tree | 41ab32eb98c85110863877308ce0983e6eae437d | |
| parent | c1ed9483ff77487b38587a96a74b6ebb813985da (diff) | |
| download | jgit-edc1fee033a23189742cea1807d8029d1b77da00.zip jgit-edc1fee033a23189742cea1807d8029d1b77da00.tar.gz jgit-edc1fee033a23189742cea1807d8029d1b77da00.tar.bz2 | |
Fix rebase > continue when nothing left to commit.refs/changes/59/4959/7
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 672f4d8..648ef6f 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 ae73cac..936f5ca 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 e389d99..4739f16 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; |

