aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Duft2012-03-09 07:36:53 -0500
committerStefan Lay2012-03-09 07:56:37 -0500
commitedc1fee033a23189742cea1807d8029d1b77da00 (patch)
tree41ab32eb98c85110863877308ce0983e6eae437d
parentc1ed9483ff77487b38587a96a74b6ebb813985da (diff)
downloadjgit-edc1fee033a23189742cea1807d8029d1b77da00.zip
jgit-edc1fee033a23189742cea1807d8029d1b77da00.tar.gz
jgit-edc1fee033a23189742cea1807d8029d1b77da00.tar.xz
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
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java60
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java12
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseResult.java13
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;