summaryrefslogtreecommitdiffstatsabout
diff options
context:
space:
mode:
authorMarkus Duft2012-03-09 07:36:53 (EST)
committer Stefan Lay2012-03-09 07:56:37 (EST)
commitedc1fee033a23189742cea1807d8029d1b77da00 (patch)
tree41ab32eb98c85110863877308ce0983e6eae437d
parentc1ed9483ff77487b38587a96a74b6ebb813985da (diff)
downloadjgit-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
-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;