aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java')
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java963
1 files changed, 703 insertions, 260 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 8b0ed5f39d..4c8cf06a67 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
@@ -1,47 +1,15 @@
/*
- * Copyright (C) 2010, 2013 Mathias Kinzler <mathias.kinzler@sap.com>
- * and other copyright owners as documented in the project's IP log.
+ * Copyright (C) 2010, 2013 Mathias Kinzler <mathias.kinzler@sap.com> and others
*
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
*
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- * names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * SPDX-License-Identifier: BSD-3-Clause
*/
package org.eclipse.jgit.api;
+import static java.nio.charset.StandardCharsets.UTF_8;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -56,12 +24,15 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.time.Instant;
+import java.time.ZoneOffset;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.eclipse.jgit.api.MergeResult.MergeStatus;
import org.eclipse.jgit.api.RebaseCommand.InteractiveHandler;
+import org.eclipse.jgit.api.RebaseCommand.InteractiveHandler2;
import org.eclipse.jgit.api.RebaseCommand.Operation;
import org.eclipse.jgit.api.RebaseResult.Status;
import org.eclipse.jgit.api.errors.InvalidRebaseStepException;
@@ -74,8 +45,11 @@ import org.eclipse.jgit.errors.AmbiguousObjectException;
import org.eclipse.jgit.errors.IllegalTodoFileModification;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.events.ChangeRecorder;
+import org.eclipse.jgit.events.ListenerHandle;
import org.eclipse.jgit.junit.RepositoryTestCase;
import org.eclipse.jgit.lib.AbbreviatedObjectId;
+import org.eclipse.jgit.lib.CommitConfig.CleanupMode;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
@@ -83,9 +57,11 @@ import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.RebaseTodoLine;
import org.eclipse.jgit.lib.RebaseTodoLine.Action;
+import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.ReflogEntry;
import org.eclipse.jgit.lib.RepositoryState;
+import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.merge.MergeStrategy;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevSort;
@@ -103,6 +79,10 @@ public class RebaseCommandTest extends RepositoryTestCase {
private static final String FILE1 = "file1";
+ private static final String FILE2 = "file2";
+
+ private static final String FILE3 = "file3";
+
protected Git git;
@Override
@@ -154,11 +134,12 @@ public class RebaseCommandTest extends RepositoryTestCase {
checkFile(file2, "file2");
assertEquals(Status.FAST_FORWARD, res.getStatus());
- List<ReflogEntry> headLog = db.getReflogReader(Constants.HEAD)
+ RefDatabase refDb = db.getRefDatabase();
+ List<ReflogEntry> headLog = refDb.getReflogReader(Constants.HEAD)
.getReverseEntries();
- List<ReflogEntry> topicLog = db.getReflogReader("refs/heads/topic")
+ List<ReflogEntry> topicLog = refDb.getReflogReader("refs/heads/topic")
.getReverseEntries();
- List<ReflogEntry> masterLog = db.getReflogReader("refs/heads/master")
+ List<ReflogEntry> masterLog = refDb.getReflogReader("refs/heads/master")
.getReverseEntries();
assertEquals("rebase finished: returning to refs/heads/topic", headLog
.get(0).getComment());
@@ -200,11 +181,12 @@ public class RebaseCommandTest extends RepositoryTestCase {
checkFile(file2, "file2 new content");
assertEquals(Status.FAST_FORWARD, res.getStatus());
- List<ReflogEntry> headLog = db.getReflogReader(Constants.HEAD)
+ RefDatabase refDb = db.getRefDatabase();
+ List<ReflogEntry> headLog = refDb.getReflogReader(Constants.HEAD)
.getReverseEntries();
- List<ReflogEntry> topicLog = db.getReflogReader("refs/heads/topic")
+ List<ReflogEntry> topicLog = refDb.getReflogReader("refs/heads/topic")
.getReverseEntries();
- List<ReflogEntry> masterLog = db.getReflogReader("refs/heads/master")
+ List<ReflogEntry> masterLog = refDb.getReflogReader("refs/heads/master")
.getReverseEntries();
assertEquals("rebase finished: returning to refs/heads/topic", headLog
.get(0).getComment());
@@ -218,6 +200,177 @@ public class RebaseCommandTest extends RepositoryTestCase {
}
/**
+ * Rebase a single root commit onto an independent branch.
+ *
+ * <pre>
+ * A (master)
+ *
+ * B - C (orphan)
+ * </pre>
+ *
+ * to
+ *
+ * <pre>
+ * A
+ *
+ * B - C (orphan) - A' (master)
+ * </pre>
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testRebaseRootCommit() throws Exception {
+ writeTrashFile(FILE1, FILE1);
+ writeTrashFile(FILE2, FILE2);
+ git.add().addFilepattern(FILE1).addFilepattern(FILE2).call();
+ RevCommit first = git.commit().setMessage("Add files").call();
+ File file1 = new File(db.getWorkTree(), FILE1);
+ File file2 = new File(db.getWorkTree(), FILE2);
+ assertTrue(file1.exists());
+ assertTrue(file2.exists());
+ // Create an independent branch
+ git.checkout().setOrphan(true).setName("orphan").call();
+ git.rm().addFilepattern(FILE1).addFilepattern(FILE2).call();
+ assertFalse(file1.exists());
+ assertFalse(file2.exists());
+ writeTrashFile(FILE1, "something else");
+ git.add().addFilepattern(FILE1).call();
+ RevCommit orphanBase = git.commit().setMessage("Orphan base").call();
+ writeTrashFile(FILE1, FILE1);
+ git.add().addFilepattern(FILE1).call();
+ RevCommit orphanTop = git.commit().setMessage("Same file1").call();
+ checkoutBranch("refs/heads/master");
+ assertEquals(first.getId(), db.resolve("HEAD"));
+ RebaseResult res = git.rebase().setUpstream("refs/heads/orphan").call();
+ assertEquals(Status.OK, res.getStatus());
+ Iterable<RevCommit> log = git.log().add(db.resolve("HEAD")).call();
+ ObjectId[] ids = { orphanTop.getId(), orphanBase.getId() };
+ int nOfCommits = 0;
+ for (RevCommit c : log) {
+ nOfCommits++;
+ if (nOfCommits == 1) {
+ assertEquals("Add files", c.getFullMessage());
+ } else {
+ assertEquals(ids[nOfCommits - 2], c.getId());
+ }
+ }
+ assertEquals(3, nOfCommits);
+ assertTrue(file1.exists());
+ checkFile(file1, FILE1);
+ assertTrue(file2.exists());
+ checkFile(file2, FILE2);
+ }
+
+ /**
+ * Rebase a branch onto an independent branch.
+ *
+ * <pre>
+ * A - B (master)
+ *
+ * C - D (orphan)
+ * </pre>
+ *
+ * to
+ *
+ * <pre>
+ * A - B
+ *
+ * C - D (orphan) - A' - B' (master)
+ * </pre>
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testRebaseNoMergeBase() throws Exception {
+ writeTrashFile(FILE1, FILE1);
+ writeTrashFile(FILE2, FILE2);
+ git.add().addFilepattern(FILE1).addFilepattern(FILE2).call();
+ git.commit().setMessage("Add files").call();
+ writeTrashFile(FILE3, FILE3);
+ git.add().addFilepattern(FILE3).call();
+ RevCommit first = git.commit().setMessage("File3").call();
+ File file1 = new File(db.getWorkTree(), FILE1);
+ File file2 = new File(db.getWorkTree(), FILE2);
+ File file3 = new File(db.getWorkTree(), FILE3);
+ assertTrue(file1.exists());
+ assertTrue(file2.exists());
+ assertTrue(file3.exists());
+ // Create an independent branch
+ git.checkout().setOrphan(true).setName("orphan").call();
+ git.rm()
+ .addFilepattern(FILE1)
+ .addFilepattern(FILE2)
+ .addFilepattern(FILE3)
+ .call();
+ assertFalse(file1.exists());
+ assertFalse(file2.exists());
+ assertFalse(file3.exists());
+ writeTrashFile(FILE1, "something else");
+ git.add().addFilepattern(FILE1).call();
+ RevCommit orphanBase = git.commit().setMessage("Orphan base").call();
+ writeTrashFile(FILE1, FILE1);
+ git.add().addFilepattern(FILE1).call();
+ RevCommit orphanTop = git.commit().setMessage("Same file1").call();
+ checkoutBranch("refs/heads/master");
+ assertEquals(first.getId(), db.resolve("HEAD"));
+ RebaseResult res = git.rebase().setUpstream("refs/heads/orphan").call();
+ assertEquals(Status.OK, res.getStatus());
+ Iterable<RevCommit> log = git.log().add(db.resolve("HEAD")).call();
+ String[] msgs = { "File3", "Add files" };
+ ObjectId[] ids = { orphanTop.getId(), orphanBase.getId() };
+ int nOfCommits = 0;
+ for (RevCommit c : log) {
+ nOfCommits++;
+ if (nOfCommits <= msgs.length) {
+ assertEquals(msgs[nOfCommits - 1], c.getFullMessage());
+ } else {
+ assertEquals(ids[nOfCommits - msgs.length - 1], c.getId());
+ }
+ }
+ assertEquals(4, nOfCommits);
+ assertTrue(file1.exists());
+ checkFile(file1, FILE1);
+ assertTrue(file2.exists());
+ checkFile(file2, FILE2);
+ assertTrue(file3.exists());
+ checkFile(file3, FILE3);
+ }
+
+ /**
+ * Create a commit A and an unrelated commit B creating the same file with
+ * different content. Then rebase A onto B. The rebase should stop with a
+ * conflict.
+ *
+ * @throws Exception
+ * on errors
+ */
+ @Test
+ public void testRebaseNoMergeBaseConflict() throws Exception {
+ writeTrashFile(FILE1, FILE1);
+ git.add().addFilepattern(FILE1).call();
+ RevCommit first = git.commit().setMessage("Add file").call();
+ File file1 = new File(db.getWorkTree(), FILE1);
+ assertTrue(file1.exists());
+ // Create an independent branch
+ git.checkout().setOrphan(true).setName("orphan").call();
+ git.rm().addFilepattern(FILE1).call();
+ assertFalse(file1.exists());
+ writeTrashFile(FILE1, "something else");
+ git.add().addFilepattern(FILE1).call();
+ git.commit().setMessage("Orphan").call();
+ checkoutBranch("refs/heads/master");
+ assertEquals(first.getId(), db.resolve("HEAD"));
+ RebaseResult res = git.rebase().setUpstream("refs/heads/orphan").call();
+ assertEquals(Status.STOPPED, res.getStatus());
+ assertEquals(first, res.getCurrentCommit());
+ checkFile(file1, "<<<<<<< Upstream, based on orphan\n"
+ + "something else\n"
+ + "=======\n"
+ + "file1\n"
+ + ">>>>>>> " + first.abbreviate(7).name() + " Add file\n");
+ }
+
+ /**
* Create the following commits and then attempt to rebase topic onto
* master. This will serialize the branches.
*
@@ -288,21 +441,23 @@ public class RebaseCommandTest extends RepositoryTestCase {
RebaseResult res = git.rebase().setUpstream("refs/heads/master").call();
assertEquals(Status.OK, res.getStatus());
- RevWalk rw = new RevWalk(db);
- rw.markStart(rw.parseCommit(db.resolve("refs/heads/topic")));
- assertDerivedFrom(rw.next(), e);
- assertDerivedFrom(rw.next(), d);
- assertDerivedFrom(rw.next(), c);
- assertEquals(b, rw.next());
- assertEquals(a, rw.next());
+ try (RevWalk rw = new RevWalk(db)) {
+ rw.markStart(rw.parseCommit(db.resolve("refs/heads/topic")));
+ assertDerivedFrom(rw.next(), e);
+ assertDerivedFrom(rw.next(), d);
+ assertDerivedFrom(rw.next(), c);
+ assertEquals(b, rw.next());
+ assertEquals(a, rw.next());
+ }
- List<ReflogEntry> headLog = db.getReflogReader(Constants.HEAD)
+ RefDatabase refDb = db.getRefDatabase();
+ List<ReflogEntry> headLog = refDb.getReflogReader(Constants.HEAD)
.getReverseEntries();
- List<ReflogEntry> sideLog = db.getReflogReader("refs/heads/side")
+ List<ReflogEntry> sideLog = refDb.getReflogReader("refs/heads/side")
.getReverseEntries();
- List<ReflogEntry> topicLog = db.getReflogReader("refs/heads/topic")
+ List<ReflogEntry> topicLog = refDb.getReflogReader("refs/heads/topic")
.getReverseEntries();
- List<ReflogEntry> masterLog = db.getReflogReader("refs/heads/master")
+ List<ReflogEntry> masterLog = refDb.getReflogReader("refs/heads/master")
.getReverseEntries();
assertEquals("rebase finished: returning to refs/heads/topic", headLog
.get(0).getComment());
@@ -354,8 +509,6 @@ public class RebaseCommandTest extends RepositoryTestCase {
*/
private void doTestRebasePreservingMerges(boolean testConflict)
throws Exception {
- RevWalk rw = new RevWalk(db);
-
// create file1 on master
writeTrashFile(FILE1, FILE1);
git.add().addFilepattern(FILE1).call();
@@ -409,7 +562,9 @@ public class RebaseCommandTest extends RepositoryTestCase {
f = git.commit().setMessage("commit f").call();
} else {
assertEquals(MergeStatus.MERGED, result.getMergeStatus());
- f = rw.parseCommit(result.getNewHead());
+ try (RevWalk rw = new RevWalk(db)) {
+ f = rw.parseCommit(result.getNewHead());
+ }
}
RebaseResult res = git.rebase().setUpstream("refs/heads/master")
@@ -453,23 +608,25 @@ public class RebaseCommandTest extends RepositoryTestCase {
assertEquals("file2", read("file2"));
assertEquals("more change", read("file3"));
- rw.markStart(rw.parseCommit(db.resolve("refs/heads/topic")));
- RevCommit newF = rw.next();
- assertDerivedFrom(newF, f);
- assertEquals(2, newF.getParentCount());
- RevCommit newD = rw.next();
- assertDerivedFrom(newD, d);
- if (testConflict)
- assertEquals("d new", readFile("conflict", newD));
- RevCommit newE = rw.next();
- assertDerivedFrom(newE, e);
- if (testConflict)
- assertEquals("e new", readFile("conflict", newE));
- assertEquals(newD, newF.getParent(0));
- assertEquals(newE, newF.getParent(1));
- assertDerivedFrom(rw.next(), c);
- assertEquals(b, rw.next());
- assertEquals(a, rw.next());
+ try (RevWalk rw = new RevWalk(db)) {
+ rw.markStart(rw.parseCommit(db.resolve("refs/heads/topic")));
+ RevCommit newF = rw.next();
+ assertDerivedFrom(newF, f);
+ assertEquals(2, newF.getParentCount());
+ RevCommit newD = rw.next();
+ assertDerivedFrom(newD, d);
+ if (testConflict)
+ assertEquals("d new", readFile("conflict", newD));
+ RevCommit newE = rw.next();
+ assertDerivedFrom(newE, e);
+ if (testConflict)
+ assertEquals("e new", readFile("conflict", newE));
+ assertEquals(newD, newF.getParent(0));
+ assertEquals(newE, newF.getParent(1));
+ assertDerivedFrom(rw.next(), c);
+ assertEquals(b, rw.next());
+ assertEquals(a, rw.next());
+ }
}
private String readFile(String path, RevCommit commit) throws IOException {
@@ -517,88 +674,89 @@ public class RebaseCommandTest extends RepositoryTestCase {
*/
private void doTestRebasePreservingMergesWithUnrelatedSide(
boolean testConflict) throws Exception {
- RevWalk rw = new RevWalk(db);
- rw.sort(RevSort.TOPO);
-
- writeTrashFile(FILE1, FILE1);
- git.add().addFilepattern(FILE1).call();
- RevCommit a = git.commit().setMessage("commit a").call();
-
- writeTrashFile("file2", "blah");
- git.add().addFilepattern("file2").call();
- RevCommit b = git.commit().setMessage("commit b").call();
-
- // create a topic branch
- createBranch(b, "refs/heads/topic");
- checkoutBranch("refs/heads/topic");
+ try (RevWalk rw = new RevWalk(db)) {
+ rw.sort(RevSort.TOPO);
- writeTrashFile("file3", "more changess");
- writeTrashFile(FILE1, "preparing conflict");
- git.add().addFilepattern("file3").addFilepattern(FILE1).call();
- RevCommit c = git.commit().setMessage("commit c").call();
+ writeTrashFile(FILE1, FILE1);
+ git.add().addFilepattern(FILE1).call();
+ RevCommit a = git.commit().setMessage("commit a").call();
- createBranch(a, "refs/heads/side");
- checkoutBranch("refs/heads/side");
- writeTrashFile("conflict", "e");
- writeTrashFile(FILE1, FILE1 + "\n" + "line 2");
- git.add().addFilepattern(".").call();
- RevCommit e = git.commit().setMessage("commit e").call();
+ writeTrashFile("file2", "blah");
+ git.add().addFilepattern("file2").call();
+ RevCommit b = git.commit().setMessage("commit b").call();
- // switch back to topic and merge in side, creating d
- checkoutBranch("refs/heads/topic");
- MergeResult result = git.merge().include(e)
- .setStrategy(MergeStrategy.RESOLVE).call();
+ // create a topic branch
+ createBranch(b, "refs/heads/topic");
+ checkoutBranch("refs/heads/topic");
- assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
- assertEquals(result.getConflicts().keySet(),
- Collections.singleton(FILE1));
- writeTrashFile(FILE1, "merge resolution");
- git.add().addFilepattern(FILE1).call();
- RevCommit d = git.commit().setMessage("commit d").call();
+ writeTrashFile("file3", "more changess");
+ writeTrashFile(FILE1, "preparing conflict");
+ git.add().addFilepattern("file3").addFilepattern(FILE1).call();
+ RevCommit c = git.commit().setMessage("commit c").call();
- RevCommit f = commitFile("file2", "new content two", "topic");
+ createBranch(a, "refs/heads/side");
+ checkoutBranch("refs/heads/side");
+ writeTrashFile("conflict", "e");
+ writeTrashFile(FILE1, FILE1 + "\n" + "line 2");
+ git.add().addFilepattern(".").call();
+ RevCommit e = git.commit().setMessage("commit e").call();
- checkoutBranch("refs/heads/master");
- writeTrashFile("fileg", "fileg");
- if (testConflict)
- writeTrashFile("conflict", "g");
- git.add().addFilepattern(".").call();
- RevCommit g = git.commit().setMessage("commit g").call();
+ // switch back to topic and merge in side, creating d
+ checkoutBranch("refs/heads/topic");
+ MergeResult result = git.merge().include(e)
+ .setStrategy(MergeStrategy.RESOLVE).call();
- checkoutBranch("refs/heads/topic");
- RebaseResult res = git.rebase().setUpstream("refs/heads/master")
- .setPreserveMerges(true).call();
- if (testConflict) {
- assertEquals(Status.STOPPED, res.getStatus());
- assertEquals(Collections.singleton("conflict"), git.status().call()
- .getConflicting());
- // resolve
- writeTrashFile("conflict", "e");
- git.add().addFilepattern("conflict").call();
- res = git.rebase().setOperation(Operation.CONTINUE).call();
+ assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
+ assertEquals(result.getConflicts().keySet(),
+ Collections.singleton(FILE1));
+ writeTrashFile(FILE1, "merge resolution");
+ git.add().addFilepattern(FILE1).call();
+ RevCommit d = git.commit().setMessage("commit d").call();
+
+ RevCommit f = commitFile("file2", "new content two", "topic");
+
+ checkoutBranch("refs/heads/master");
+ writeTrashFile("fileg", "fileg");
+ if (testConflict)
+ writeTrashFile("conflict", "g");
+ git.add().addFilepattern(".").call();
+ RevCommit g = git.commit().setMessage("commit g").call();
+
+ checkoutBranch("refs/heads/topic");
+ RebaseResult res = git.rebase().setUpstream("refs/heads/master")
+ .setPreserveMerges(true).call();
+ if (testConflict) {
+ assertEquals(Status.STOPPED, res.getStatus());
+ assertEquals(Collections.singleton("conflict"), git.status().call()
+ .getConflicting());
+ // resolve
+ writeTrashFile("conflict", "e");
+ git.add().addFilepattern("conflict").call();
+ res = git.rebase().setOperation(Operation.CONTINUE).call();
+ }
+ assertEquals(Status.OK, res.getStatus());
+
+ assertEquals("merge resolution", read(FILE1));
+ assertEquals("new content two", read("file2"));
+ assertEquals("more changess", read("file3"));
+ assertEquals("fileg", read("fileg"));
+
+ rw.markStart(rw.parseCommit(db.resolve("refs/heads/topic")));
+ RevCommit newF = rw.next();
+ assertDerivedFrom(newF, f);
+ RevCommit newD = rw.next();
+ assertDerivedFrom(newD, d);
+ assertEquals(2, newD.getParentCount());
+ RevCommit newC = rw.next();
+ assertDerivedFrom(newC, c);
+ RevCommit newE = rw.next();
+ assertEquals(e, newE);
+ assertEquals(newC, newD.getParent(0));
+ assertEquals(e, newD.getParent(1));
+ assertEquals(g, rw.next());
+ assertEquals(b, rw.next());
+ assertEquals(a, rw.next());
}
- assertEquals(Status.OK, res.getStatus());
-
- assertEquals("merge resolution", read(FILE1));
- assertEquals("new content two", read("file2"));
- assertEquals("more changess", read("file3"));
- assertEquals("fileg", read("fileg"));
-
- rw.markStart(rw.parseCommit(db.resolve("refs/heads/topic")));
- RevCommit newF = rw.next();
- assertDerivedFrom(newF, f);
- RevCommit newD = rw.next();
- assertDerivedFrom(newD, d);
- assertEquals(2, newD.getParentCount());
- RevCommit newC = rw.next();
- assertDerivedFrom(newC, c);
- RevCommit newE = rw.next();
- assertEquals(e, newE);
- assertEquals(newC, newD.getParent(0));
- assertEquals(e, newD.getParent(1));
- assertEquals(g, rw.next());
- assertEquals(b, rw.next());
- assertEquals(a, rw.next());
}
@Test
@@ -614,9 +772,10 @@ public class RebaseCommandTest extends RepositoryTestCase {
RebaseResult result = git.rebase().setUpstream(parent).call();
assertEquals(Status.UP_TO_DATE, result.getStatus());
- assertEquals(2, db.getReflogReader(Constants.HEAD).getReverseEntries()
- .size());
- assertEquals(2, db.getReflogReader("refs/heads/master")
+ RefDatabase refDb = db.getRefDatabase();
+ assertEquals(2, refDb.getReflogReader(Constants.HEAD)
+ .getReverseEntries().size());
+ assertEquals(2, refDb.getReflogReader("refs/heads/master")
.getReverseEntries().size());
}
@@ -632,9 +791,10 @@ public class RebaseCommandTest extends RepositoryTestCase {
RebaseResult res = git.rebase().setUpstream(first).call();
assertEquals(Status.UP_TO_DATE, res.getStatus());
- assertEquals(1, db.getReflogReader(Constants.HEAD).getReverseEntries()
- .size());
- assertEquals(1, db.getReflogReader("refs/heads/master")
+ RefDatabase refDb = db.getRefDatabase();
+ assertEquals(1, refDb.getReflogReader(Constants.HEAD)
+ .getReverseEntries().size());
+ assertEquals(1, refDb.getReflogReader("refs/heads/master")
.getReverseEntries().size());
}
@@ -687,14 +847,17 @@ public class RebaseCommandTest extends RepositoryTestCase {
checkFile(theFile, "1master\n2\n3\ntopic\n");
// our old branch should be checked out again
assertEquals("refs/heads/topic", db.getFullBranch());
- assertEquals(lastMasterChange, new RevWalk(db).parseCommit(
- db.resolve(Constants.HEAD)).getParent(0));
+ try (RevWalk rw = new RevWalk(db)) {
+ assertEquals(lastMasterChange, rw.parseCommit(
+ db.resolve(Constants.HEAD)).getParent(0));
+ }
assertEquals(origHead, db.readOrigHead());
- List<ReflogEntry> headLog = db.getReflogReader(Constants.HEAD)
+ RefDatabase refDb = db.getRefDatabase();
+ List<ReflogEntry> headLog = refDb.getReflogReader(Constants.HEAD)
.getReverseEntries();
- List<ReflogEntry> topicLog = db.getReflogReader("refs/heads/topic")
+ List<ReflogEntry> topicLog = refDb.getReflogReader("refs/heads/topic")
.getReverseEntries();
- List<ReflogEntry> masterLog = db.getReflogReader("refs/heads/master")
+ List<ReflogEntry> masterLog = refDb.getReflogReader("refs/heads/master")
.getReverseEntries();
assertEquals(2, masterLog.size());
assertEquals(3, topicLog.size());
@@ -737,11 +900,13 @@ public class RebaseCommandTest extends RepositoryTestCase {
RebaseResult res = git.rebase().setUpstream("refs/heads/master").call();
assertEquals(Status.OK, res.getStatus());
checkFile(theFile, "1master\n2\n3\ntopic\n");
- assertEquals(lastMasterChange, new RevWalk(db).parseCommit(
- db.resolve(Constants.HEAD)).getParent(0));
+ try (RevWalk rw = new RevWalk(db)) {
+ assertEquals(lastMasterChange, rw.parseCommit(
+ db.resolve(Constants.HEAD)).getParent(0));
+ }
- List<ReflogEntry> headLog = db.getReflogReader(Constants.HEAD)
- .getReverseEntries();
+ List<ReflogEntry> headLog = db.getRefDatabase()
+ .getReflogReader(Constants.HEAD).getReverseEntries();
assertEquals(8, headLog.size());
assertEquals("rebase: change file1 in topic", headLog.get(0)
.getComment());
@@ -785,8 +950,10 @@ public class RebaseCommandTest extends RepositoryTestCase {
// our old branch should be checked out again
assertEquals("refs/heads/file3", db.getFullBranch());
- assertEquals(addFile2, new RevWalk(db).parseCommit(
- db.resolve(Constants.HEAD)).getParent(0));
+ try (RevWalk rw = new RevWalk(db)) {
+ assertEquals(addFile2, rw.parseCommit(
+ db.resolve(Constants.HEAD)).getParent(0));
+ }
checkoutBranch("refs/heads/file2");
assertTrue(new File(db.getWorkTree(), FILE1).exists());
@@ -846,9 +1013,10 @@ public class RebaseCommandTest extends RepositoryTestCase {
assertEquals(res.getStatus(), Status.ABORTED);
assertEquals("refs/heads/topic", db.getFullBranch());
checkFile(FILE1, "1topic", "2", "3", "topic4");
- RevWalk rw = new RevWalk(db);
- assertEquals(lastTopicCommit, rw
- .parseCommit(db.resolve(Constants.HEAD)));
+ try (RevWalk rw = new RevWalk(db)) {
+ assertEquals(lastTopicCommit,
+ rw.parseCommit(db.resolve(Constants.HEAD)));
+ }
assertEquals(RepositoryState.SAFE, db.getRepositoryState());
// rebase- dir in .git must be deleted
@@ -909,9 +1077,10 @@ public class RebaseCommandTest extends RepositoryTestCase {
assertEquals(res.getStatus(), Status.ABORTED);
assertEquals(lastTopicCommit.getName(), db.getFullBranch());
checkFile(FILE1, "1topic", "2", "3", "topic4");
- RevWalk rw = new RevWalk(db);
- assertEquals(lastTopicCommit,
- rw.parseCommit(db.resolve(Constants.HEAD)));
+ try (RevWalk rw = new RevWalk(db)) {
+ assertEquals(lastTopicCommit,
+ rw.parseCommit(db.resolve(Constants.HEAD)));
+ }
assertEquals(RepositoryState.SAFE, db.getRepositoryState());
// rebase- dir in .git must be deleted
@@ -966,11 +1135,12 @@ public class RebaseCommandTest extends RepositoryTestCase {
assertEquals(RepositoryState.SAFE, db.getRepositoryState());
ObjectId headId = db.resolve(Constants.HEAD);
- RevWalk rw = new RevWalk(db);
- RevCommit rc = rw.parseCommit(headId);
- RevCommit parent = rw.parseCommit(rc.getParent(0));
- assertEquals("change file1 in topic\n\nThis is conflicting", parent
- .getFullMessage());
+ try (RevWalk rw = new RevWalk(db)) {
+ RevCommit rc = rw.parseCommit(headId);
+ RevCommit parent = rw.parseCommit(rc.getParent(0));
+ assertEquals("change file1 in topic\n\nThis is conflicting", parent
+ .getFullMessage());
+ }
}
@Test
@@ -1017,9 +1187,10 @@ public class RebaseCommandTest extends RepositoryTestCase {
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());
+ try (RevWalk rw = new RevWalk(db)) {
+ RevCommit rc = rw.parseCommit(headId);
+ assertEquals("change file1 in master", rc.getFullMessage());
+ }
}
@Test
@@ -1308,10 +1479,11 @@ public class RebaseCommandTest extends RepositoryTestCase {
git.rebase().setOperation(Operation.SKIP).call();
ObjectId headId = db.resolve(Constants.HEAD);
- RevWalk rw = new RevWalk(db);
- RevCommit rc = rw.parseCommit(headId);
- RevCommit parent = rw.parseCommit(rc.getParent(0));
- assertEquals("A different commit message", parent.getFullMessage());
+ try (RevWalk rw = new RevWalk(db)) {
+ RevCommit rc = rw.parseCommit(headId);
+ RevCommit parent = rw.parseCommit(rc.getParent(0));
+ assertEquals("A different commit message", parent.getFullMessage());
+ }
}
private RevCommit writeFileAndCommit(String fileName, String commitMessage,
@@ -1420,9 +1592,10 @@ public class RebaseCommandTest extends RepositoryTestCase {
res = git.rebase().setOperation(Operation.ABORT).call();
assertEquals(res.getStatus(), Status.ABORTED);
assertEquals("refs/heads/topic", db.getFullBranch());
- RevWalk rw = new RevWalk(db);
- assertEquals(conflicting, rw.parseCommit(db.resolve(Constants.HEAD)));
- assertEquals(RepositoryState.SAFE, db.getRepositoryState());
+ try (RevWalk rw = new RevWalk(db)) {
+ assertEquals(conflicting, rw.parseCommit(db.resolve(Constants.HEAD)));
+ assertEquals(RepositoryState.SAFE, db.getRepositoryState());
+ }
// rebase- dir in .git must be deleted
assertFalse(new File(db.getDirectory(), "rebase-merge").exists());
@@ -1439,7 +1612,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
public void testAuthorScriptConverter() throws Exception {
// -1 h timezone offset
PersonIdent ident = new PersonIdent("Author name", "a.mail@some.com",
- 123456789123L, -60);
+ Instant.ofEpochMilli(123456789123L), ZoneOffset.ofHours(-1));
String convertedAuthor = git.rebase().toAuthorScript(ident);
String[] lines = convertedAuthor.split("\n");
assertEquals("GIT_AUTHOR_NAME='Author name'", lines[0]);
@@ -1447,16 +1620,18 @@ public class RebaseCommandTest extends RepositoryTestCase {
assertEquals("GIT_AUTHOR_DATE='@123456789 -0100'", lines[2]);
PersonIdent parsedIdent = git.rebase().parseAuthor(
- convertedAuthor.getBytes("UTF-8"));
+ convertedAuthor.getBytes(UTF_8));
assertEquals(ident.getName(), parsedIdent.getName());
assertEquals(ident.getEmailAddress(), parsedIdent.getEmailAddress());
// this is rounded to the last second
- assertEquals(123456789000L, parsedIdent.getWhen().getTime());
- assertEquals(ident.getTimeZoneOffset(), parsedIdent.getTimeZoneOffset());
+ assertEquals(123456789000L,
+ parsedIdent.getWhenAsInstant().toEpochMilli());
+ assertEquals(ident.getZoneId(), parsedIdent.getZoneId());
// + 9.5h timezone offset
ident = new PersonIdent("Author name", "a.mail@some.com",
- 123456789123L, +570);
+ Instant.ofEpochMilli(123456789123L),
+ ZoneOffset.ofHoursMinutes(9, 30));
convertedAuthor = git.rebase().toAuthorScript(ident);
lines = convertedAuthor.split("\n");
assertEquals("GIT_AUTHOR_NAME='Author name'", lines[0]);
@@ -1464,11 +1639,12 @@ public class RebaseCommandTest extends RepositoryTestCase {
assertEquals("GIT_AUTHOR_DATE='@123456789 +0930'", lines[2]);
parsedIdent = git.rebase().parseAuthor(
- convertedAuthor.getBytes("UTF-8"));
+ convertedAuthor.getBytes(UTF_8));
assertEquals(ident.getName(), parsedIdent.getName());
assertEquals(ident.getEmailAddress(), parsedIdent.getEmailAddress());
- assertEquals(123456789000L, parsedIdent.getWhen().getTime());
- assertEquals(ident.getTimeZoneOffset(), parsedIdent.getTimeZoneOffset());
+ assertEquals(123456789000L,
+ parsedIdent.getWhenAsInstant().toEpochMilli());
+ assertEquals(ident.getZoneId(), parsedIdent.getZoneId());
}
@Test
@@ -1964,6 +2140,60 @@ public class RebaseCommandTest extends RepositoryTestCase {
}
@Test
+ public void testRebaseWithAutoStashAndSubdirs() throws Exception {
+ // create file0, add and commit
+ db.getConfig().setBoolean(ConfigConstants.CONFIG_REBASE_SECTION, null,
+ ConfigConstants.CONFIG_KEY_AUTOSTASH, true);
+ writeTrashFile("sub/file0", "file0");
+ git.add().addFilepattern("sub/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("sub/file0", "unstaged modified file0");
+
+ ChangeRecorder recorder = new ChangeRecorder();
+ ListenerHandle handle = db.getListenerList()
+ .addWorkingTreeModifiedListener(recorder);
+ try {
+ // rebase
+ assertEquals(Status.OK, git.rebase()
+ .setUpstream("refs/heads/master").call().getStatus());
+ } finally {
+ handle.remove();
+ }
+ checkFile(new File(new File(db.getWorkTree(), "sub"), "file0"),
+ "unstaged modified file0");
+ checkFile(new File(db.getWorkTree(), FILE1), "modified file1");
+ checkFile(new File(db.getWorkTree(), "file2"), "file2");
+ assertEquals(
+ "[file1, mode:100644, content:modified file1]"
+ + "[file2, mode:100644, content:file2]"
+ + "[sub/file0, mode:100644, content:file0]",
+ indexState(CONTENT));
+ assertEquals(RepositoryState.SAFE, db.getRepositoryState());
+ recorder.assertEvent(new String[] { "file1", "file2", "sub/file0" },
+ new String[0]);
+ }
+
+ @Test
public void testRebaseWithAutoStashConflictOnApply() throws Exception {
// create file0, add and commit
db.getConfig().setBoolean(ConfigConstants.CONFIG_REBASE_SECTION, null,
@@ -2037,7 +2267,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
checkoutBranch("refs/heads/master");
writeTrashFile(FILE1, "modified file1");
git.add().addFilepattern(FILE1).call();
- git.commit().setMessage("commit3").call();
+ git.commit().setMessage("commit2").call();
// checkout topic branch / modify file0
checkoutBranch("refs/heads/topic");
@@ -2056,13 +2286,66 @@ public class RebaseCommandTest extends RepositoryTestCase {
assertEquals(RepositoryState.SAFE, db.getRepositoryState());
}
+ @Test
+ public void testFastForwardRebaseWithAutoStashConflict() 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
+ createBranch(commit, "refs/heads/topic");
+
+ // checkout master branch / modify file1, add and commit
+ checkoutBranch("refs/heads/master");
+ writeTrashFile(FILE1, "modified file1");
+ git.add().addFilepattern(FILE1).call();
+ RevCommit master = git.commit().setMessage("commit2").call();
+
+ // checkout topic branch / modify file0 and file1
+ checkoutBranch("refs/heads/topic");
+ writeTrashFile("file0", "unstaged modified file0");
+ 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"),
+ "unstaged modified file0");
+ checkFile(new File(db.getWorkTree(), FILE1),
+ "<<<<<<< HEAD\n"
+ + "modified file1\n"
+ + "=======\n"
+ + "unstaged modified file1\n"
+ + ">>>>>>> stash\n");
+ // If there is a merge conflict, the index is not reset, and thus file0
+ // is staged here. This is the same behavior as in C git.
+ String expected = "[file0, mode:100644, content:unstaged modified 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]";
+ assertEquals(expected, indexState(CONTENT));
+ assertEquals(RepositoryState.SAFE, db.getRepositoryState());
+ assertEquals(master, db.resolve(Constants.HEAD));
+ assertEquals(master, db.resolve("refs/heads/topic"));
+ }
+
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;
+ try (RevWalk revWalk = new RevWalk(db)) {
+ RevCommit stashCommit = revWalk.parseCommit(stashId);
+ List<DiffEntry> diffs = diffWorkingAgainstHead(stashCommit,
+ revWalk);
+ return diffs;
+ }
}
private TreeWalk createTreeWalk() {
@@ -2086,9 +2369,8 @@ public class RebaseCommandTest extends RepositoryTestCase {
private int countPicks() throws IOException {
int count = 0;
File todoFile = getTodoFile();
- BufferedReader br = new BufferedReader(new InputStreamReader(
- new FileInputStream(todoFile), "UTF-8"));
- try {
+ try (BufferedReader br = new BufferedReader(new InputStreamReader(
+ new FileInputStream(todoFile), UTF_8))) {
String line = br.readLine();
while (line != null) {
int firstBlank = line.indexOf(' ');
@@ -2106,8 +2388,6 @@ public class RebaseCommandTest extends RepositoryTestCase {
line = br.readLine();
}
return count;
- } finally {
- br.close();
}
}
@@ -2253,11 +2533,13 @@ public class RebaseCommandTest extends RepositoryTestCase {
RebaseResult res = git.rebase().setUpstream("HEAD~2")
.runInteractively(new InteractiveHandler() {
+ @Override
public void prepareSteps(List<RebaseTodoLine> steps) {
steps.add(0, new RebaseTodoLine(
"# Comment that should not be processed"));
}
+ @Override
public String modifyCommitMessage(String commit) {
fail("modifyCommitMessage() was not expected to be called");
return commit;
@@ -2268,6 +2550,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
RebaseResult res2 = git.rebase().setUpstream("HEAD~2")
.runInteractively(new InteractiveHandler() {
+ @Override
public void prepareSteps(List<RebaseTodoLine> steps) {
try {
// delete RevCommit c4
@@ -2277,6 +2560,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
}
}
+ @Override
public String modifyCommitMessage(String commit) {
fail("modifyCommitMessage() was not expected to be called");
return commit;
@@ -2286,14 +2570,15 @@ public class RebaseCommandTest extends RepositoryTestCase {
assertEquals(RebaseResult.Status.OK, res2.getStatus());
ObjectId headId = db.resolve(Constants.HEAD);
- RevWalk rw = new RevWalk(db);
- RevCommit rc = rw.parseCommit(headId);
+ try (RevWalk rw = new RevWalk(db)) {
+ RevCommit rc = rw.parseCommit(headId);
- ObjectId head1Id = db.resolve(Constants.HEAD + "~1");
- RevCommit rc1 = rw.parseCommit(head1Id);
+ ObjectId head1Id = db.resolve(Constants.HEAD + "~1");
+ RevCommit rc1 = rw.parseCommit(head1Id);
- assertEquals(rc.getFullMessage(), c4.getFullMessage());
- assertEquals(rc1.getFullMessage(), c2.getFullMessage());
+ assertEquals(rc.getFullMessage(), c4.getFullMessage());
+ assertEquals(rc1.getFullMessage(), c2.getFullMessage());
+ }
}
@Test
@@ -2377,7 +2662,9 @@ public class RebaseCommandTest extends RepositoryTestCase {
assertEquals("1111111", firstLine.getCommit().name());
assertEquals("pick", firstLine.getAction().toToken());
} catch (Exception e) {
- fail("Valid parsable RebaseTodoLine that has been commented out should allow to change the action, but failed");
+ throw new AssertionError(
+ "Valid parsable RebaseTodoLine that has been commented out should allow to change the action, but failed",
+ e);
}
assertEquals("2222222", steps.get(1).getCommit().name());
@@ -2497,6 +2784,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
RebaseResult res = git.rebase().setUpstream("HEAD~2")
.runInteractively(new InteractiveHandler() {
+ @Override
public void prepareSteps(List<RebaseTodoLine> steps) {
try {
steps.get(0).setAction(Action.REWORD);
@@ -2505,6 +2793,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
}
}
+ @Override
public String modifyCommitMessage(String commit) {
return "rewritten commit message";
}
@@ -2543,6 +2832,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
RebaseResult res = git.rebase().setUpstream("HEAD~2")
.runInteractively(new InteractiveHandler() {
+ @Override
public void prepareSteps(List<RebaseTodoLine> steps) {
try {
steps.get(0).setAction(Action.EDIT);
@@ -2551,6 +2841,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
}
}
+ @Override
public String modifyCommitMessage(String commit) {
return ""; // not used
}
@@ -2607,6 +2898,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
git.rebase().setUpstream("HEAD~3")
.runInteractively(new InteractiveHandler() {
+ @Override
public void prepareSteps(List<RebaseTodoLine> steps) {
try {
steps.get(1).setAction(Action.SQUASH);
@@ -2615,6 +2907,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
}
}
+ @Override
public String modifyCommitMessage(String commit) {
final File messageSquashFile = new File(db
.getDirectory(), "rebase-merge/message-squash");
@@ -2643,15 +2936,16 @@ public class RebaseCommandTest extends RepositoryTestCase {
}
}).call();
- RevWalk walk = new RevWalk(db);
- ObjectId headId = db.resolve(Constants.HEAD);
- RevCommit headCommit = walk.parseCommit(headId);
- assertEquals(headCommit.getFullMessage(),
- "update file2 on master\nnew line");
-
- ObjectId head2Id = db.resolve(Constants.HEAD + "^1");
- RevCommit head1Commit = walk.parseCommit(head2Id);
- assertEquals("changed", head1Commit.getFullMessage());
+ try (RevWalk walk = new RevWalk(db)) {
+ ObjectId headId = db.resolve(Constants.HEAD);
+ RevCommit headCommit = walk.parseCommit(headId);
+ assertEquals(headCommit.getFullMessage(),
+ "update file2 on master\nnew line");
+
+ ObjectId head2Id = db.resolve(Constants.HEAD + "^1");
+ RevCommit head1Commit = walk.parseCommit(head2Id);
+ assertEquals("changed", head1Commit.getFullMessage());
+ }
}
@Test
@@ -2686,6 +2980,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
git.rebase().setUpstream("HEAD~4")
.runInteractively(new InteractiveHandler() {
+ @Override
public void prepareSteps(List<RebaseTodoLine> steps) {
try {
steps.get(1).setAction(Action.SQUASH);
@@ -2695,6 +2990,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
}
}
+ @Override
public String modifyCommitMessage(String commit) {
final File messageSquashFile = new File(db.getDirectory(),
"rebase-merge/message-squash");
@@ -2722,17 +3018,18 @@ public class RebaseCommandTest extends RepositoryTestCase {
}
}).call();
- RevWalk walk = new RevWalk(db);
- ObjectId headId = db.resolve(Constants.HEAD);
- RevCommit headCommit = walk.parseCommit(headId);
- assertEquals(headCommit.getFullMessage(),
- "update file2 on master\nnew line");
-
- ObjectId head2Id = db.resolve(Constants.HEAD + "^1");
- RevCommit head1Commit = walk.parseCommit(head2Id);
- assertEquals(
- "Add file1\nnew line\nAdd file2\nnew line\nupdated file1 on master\nnew line",
- head1Commit.getFullMessage());
+ try (RevWalk walk = new RevWalk(db)) {
+ ObjectId headId = db.resolve(Constants.HEAD);
+ RevCommit headCommit = walk.parseCommit(headId);
+ assertEquals(headCommit.getFullMessage(),
+ "update file2 on master\nnew line");
+
+ ObjectId head2Id = db.resolve(Constants.HEAD + "^1");
+ RevCommit head1Commit = walk.parseCommit(head2Id);
+ assertEquals(
+ "Add file1\nnew line\nAdd file2\nnew line\nupdated file1 on master\nnew line",
+ head1Commit.getFullMessage());
+ }
}
@Test
@@ -2767,6 +3064,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
git.rebase().setUpstream("HEAD~4")
.runInteractively(new InteractiveHandler() {
+ @Override
public void prepareSteps(List<RebaseTodoLine> steps) {
try {
steps.get(1).setAction(Action.FIXUP);
@@ -2776,6 +3074,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
}
}
+ @Override
public String modifyCommitMessage(String commit) {
final File messageSquashFile = new File(db
.getDirectory(), "rebase-merge/message-squash");
@@ -2804,15 +3103,16 @@ public class RebaseCommandTest extends RepositoryTestCase {
}
}).call();
- RevWalk walk = new RevWalk(db);
- ObjectId headId = db.resolve(Constants.HEAD);
- RevCommit headCommit = walk.parseCommit(headId);
- assertEquals(headCommit.getFullMessage(),
- "update file2 on master\nnew line");
-
- ObjectId head2Id = db.resolve(Constants.HEAD + "^1");
- RevCommit head1Commit = walk.parseCommit(head2Id);
- assertEquals("changed", head1Commit.getFullMessage());
+ try (RevWalk walk = new RevWalk(db)) {
+ ObjectId headId = db.resolve(Constants.HEAD);
+ RevCommit headCommit = walk.parseCommit(headId);
+ assertEquals(headCommit.getFullMessage(),
+ "update file2 on master\nnew line");
+
+ ObjectId head2Id = db.resolve(Constants.HEAD + "^1");
+ RevCommit head1Commit = walk.parseCommit(head2Id);
+ assertEquals("changed", head1Commit.getFullMessage());
+ }
}
@Test
@@ -2841,6 +3141,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
git.rebase().setUpstream("HEAD~3")
.runInteractively(new InteractiveHandler() {
+ @Override
public void prepareSteps(List<RebaseTodoLine> steps) {
try {
steps.get(1).setAction(Action.FIXUP);
@@ -2849,26 +3150,28 @@ public class RebaseCommandTest extends RepositoryTestCase {
}
}
+ @Override
public String modifyCommitMessage(String commit) {
fail("No callback to modify commit message expected for single fixup");
return commit;
}
}).call();
- RevWalk walk = new RevWalk(db);
- ObjectId headId = db.resolve(Constants.HEAD);
- RevCommit headCommit = walk.parseCommit(headId);
- assertEquals("update file2 on master\nnew line",
- headCommit.getFullMessage());
-
- ObjectId head1Id = db.resolve(Constants.HEAD + "^1");
- RevCommit head1Commit = walk.parseCommit(head1Id);
- assertEquals("Add file2\nnew line",
- head1Commit.getFullMessage());
+ try (RevWalk walk = new RevWalk(db)) {
+ ObjectId headId = db.resolve(Constants.HEAD);
+ RevCommit headCommit = walk.parseCommit(headId);
+ assertEquals("update file2 on master\nnew line",
+ headCommit.getFullMessage());
+
+ ObjectId head1Id = db.resolve(Constants.HEAD + "^1");
+ RevCommit head1Commit = walk.parseCommit(head1Id);
+ assertEquals("Add file2\nnew line",
+ head1Commit.getFullMessage());
+ }
}
- @Test
- public void testRebaseInteractiveFixupWithBlankLines() throws Exception {
+ private void simpleFixup(String firstMessage, String secondMessage)
+ throws Exception {
// create file1 on master
writeTrashFile(FILE1, FILE1);
git.add().addFilepattern(FILE1).call();
@@ -2878,17 +3181,18 @@ public class RebaseCommandTest extends RepositoryTestCase {
// create file2 on master
writeTrashFile("file2", "file2");
git.add().addFilepattern("file2").call();
- git.commit().setMessage("Add file2").call();
+ git.commit().setMessage(firstMessage).call();
assertTrue(new File(db.getWorkTree(), "file2").exists());
// update FILE1 on master
writeTrashFile(FILE1, "blah");
git.add().addFilepattern(FILE1).call();
- git.commit().setMessage("updated file1 on master\n\nsome text").call();
+ git.commit().setMessage(secondMessage).call();
git.rebase().setUpstream("HEAD~2")
.runInteractively(new InteractiveHandler() {
+ @Override
public void prepareSteps(List<RebaseTodoLine> steps) {
try {
steps.get(1).setAction(Action.FIXUP);
@@ -2897,17 +3201,41 @@ public class RebaseCommandTest extends RepositoryTestCase {
}
}
+ @Override
public String modifyCommitMessage(String commit) {
fail("No callback to modify commit message expected for single fixup");
return commit;
}
}).call();
- RevWalk walk = new RevWalk(db);
- ObjectId headId = db.resolve(Constants.HEAD);
- RevCommit headCommit = walk.parseCommit(headId);
- assertEquals("Add file2",
- headCommit.getFullMessage());
+ try (RevWalk walk = new RevWalk(db)) {
+ ObjectId headId = db.resolve(Constants.HEAD);
+ RevCommit headCommit = walk.parseCommit(headId);
+ assertEquals(firstMessage, headCommit.getFullMessage());
+ }
+
+ }
+
+ @Test
+ public void testRebaseInteractiveFixupWithBlankLines() throws Exception {
+ simpleFixup("Add file2", "updated file1 on master\n\nsome text");
+ }
+
+ @Test
+ public void testRebaseInteractiveFixupWithBlankLines2() throws Exception {
+ simpleFixup("Add file2\n\nBody\n",
+ "updated file1 on master\n\nsome text");
+ }
+
+ @Test
+ public void testRebaseInteractiveFixupWithHash() throws Exception {
+ simpleFixup("#Add file2", "updated file1 on master");
+ }
+
+ @Test
+ public void testRebaseInteractiveFixupWithHash2() throws Exception {
+ simpleFixup("#Add file2\n\nHeader has hash\n",
+ "#updated file1 on master");
}
@Test(expected = InvalidRebaseStepException.class)
@@ -2928,6 +3256,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
git.rebase().setUpstream("HEAD~1")
.runInteractively(new InteractiveHandler() {
+ @Override
public void prepareSteps(List<RebaseTodoLine> steps) {
try {
steps.get(0).setAction(Action.FIXUP);
@@ -2936,6 +3265,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
}
}
+ @Override
public String modifyCommitMessage(String commit) {
return commit;
}
@@ -2960,6 +3290,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
git.rebase().setUpstream("HEAD~1")
.runInteractively(new InteractiveHandler() {
+ @Override
public void prepareSteps(List<RebaseTodoLine> steps) {
try {
steps.get(0).setAction(Action.SQUASH);
@@ -2968,6 +3299,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
}
}
+ @Override
public String modifyCommitMessage(String commit) {
return commit;
}
@@ -2991,6 +3323,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
git.rebase().setUpstream("HEAD~1")
.runInteractively(new InteractiveHandler() {
+ @Override
public void prepareSteps(List<RebaseTodoLine> steps) {
try {
steps.get(0).setAction(Action.EDIT);
@@ -2999,6 +3332,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
}
}
+ @Override
public String modifyCommitMessage(String commit) {
return commit;
}
@@ -3033,6 +3367,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
RebaseResult result = git.rebase().setUpstream("HEAD~2")
.runInteractively(new InteractiveHandler() {
+ @Override
public void prepareSteps(List<RebaseTodoLine> steps) {
steps.remove(0);
try {
@@ -3042,6 +3377,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
}
}
+ @Override
public String modifyCommitMessage(String commit) {
return commit;
}
@@ -3075,6 +3411,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
RebaseResult result = git.rebase().setUpstream("HEAD~2")
.runInteractively(new InteractiveHandler() {
+ @Override
public void prepareSteps(List<RebaseTodoLine> steps) {
steps.remove(0);
try {
@@ -3084,6 +3421,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
}
}
+ @Override
public String modifyCommitMessage(String commit) {
return "rewritten commit message";
}
@@ -3092,6 +3430,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
git.add().addFilepattern(FILE1).call();
result = git.rebase().runInteractively(new InteractiveHandler() {
+ @Override
public void prepareSteps(List<RebaseTodoLine> steps) {
steps.remove(0);
try {
@@ -3101,6 +3440,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
}
}
+ @Override
public String modifyCommitMessage(String commit) {
return "rewritten commit message";
}
@@ -3138,6 +3478,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
RebaseResult result = git.rebase().setUpstream("HEAD~3")
.runInteractively(new InteractiveHandler() {
+ @Override
public void prepareSteps(List<RebaseTodoLine> steps) {
try {
steps.get(0).setAction(Action.PICK);
@@ -3148,6 +3489,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
}
}
+ @Override
public String modifyCommitMessage(String commit) {
return "squashed message";
}
@@ -3156,6 +3498,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
git.add().addFilepattern(FILE1).call();
result = git.rebase().runInteractively(new InteractiveHandler() {
+ @Override
public void prepareSteps(List<RebaseTodoLine> steps) {
try {
steps.get(0).setAction(Action.PICK);
@@ -3166,6 +3509,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
}
}
+ @Override
public String modifyCommitMessage(String commit) {
return "squashed message";
}
@@ -3204,6 +3548,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
RebaseResult result = git.rebase().setUpstream("HEAD~3")
.runInteractively(new InteractiveHandler() {
+ @Override
public void prepareSteps(List<RebaseTodoLine> steps) {
try {
steps.get(0).setAction(Action.PICK);
@@ -3214,6 +3559,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
}
}
+ @Override
public String modifyCommitMessage(String commit) {
return commit;
}
@@ -3222,6 +3568,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
git.add().addFilepattern(FILE1).call();
result = git.rebase().runInteractively(new InteractiveHandler() {
+ @Override
public void prepareSteps(List<RebaseTodoLine> steps) {
try {
steps.get(0).setAction(Action.PICK);
@@ -3232,6 +3579,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
}
}
+ @Override
public String modifyCommitMessage(String commit) {
return "commit";
}
@@ -3275,6 +3623,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
RebaseResult result = git.rebase().setUpstream("HEAD~2")
.runInteractively(new InteractiveHandler() {
+ @Override
public void prepareSteps(List<RebaseTodoLine> steps) {
try {
steps.get(0).setAction(Action.EDIT);
@@ -3284,6 +3633,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
}
}
+ @Override
public String modifyCommitMessage(String commit) {
return commit;
}
@@ -3303,6 +3653,99 @@ public class RebaseCommandTest extends RepositoryTestCase {
}
+ @Test
+ public void testInteractiveRebaseSquashFixupSequence() throws Exception {
+ // create file1, add and commit
+ writeTrashFile(FILE1, "file1");
+ git.add().addFilepattern(FILE1).call();
+ git.commit().setMessage("commit1").call();
+
+ // modify file1, add and commit
+ writeTrashFile(FILE1, "modified file1");
+ git.add().addFilepattern(FILE1).call();
+ git.commit().setMessage("commit2").call();
+
+ // modify file1, add and commit
+ writeTrashFile(FILE1, "modified file1 a second time");
+ git.add().addFilepattern(FILE1).call();
+ // Make it difficult; use git standard comment characters in the commit
+ // messages
+ git.commit().setMessage("#commit3").call();
+
+ // modify file1, add and commit
+ writeTrashFile(FILE1, "modified file1 a third time");
+ git.add().addFilepattern(FILE1).call();
+ git.commit().setMessage("@commit4").call();
+
+ // modify file1, add and commit
+ writeTrashFile(FILE1, "modified file1 a fourth time");
+ git.add().addFilepattern(FILE1).call();
+ git.commit().setMessage(";commit5").call();
+
+ StoredConfig config = git.getRepository().getConfig();
+ config.setString("core", null, "commentChar", "auto");
+ // With "auto", we should end up with '@' being used as comment
+ // character (commit4 is skipped, so it should not advance the
+ // character).
+ RebaseResult result = git.rebase().setUpstream("HEAD~4")
+ .runInteractively(new InteractiveHandler2() {
+
+ @Override
+ public void prepareSteps(List<RebaseTodoLine> steps) {
+ try {
+ steps.get(0).setAction(Action.PICK);
+ steps.get(1).setAction(Action.SQUASH);
+ steps.get(2).setAction(Action.FIXUP);
+ steps.get(3).setAction(Action.SQUASH);
+ } catch (IllegalTodoFileModification e) {
+ fail("unexpected exception: " + e);
+ }
+ }
+
+ @Override
+ public String modifyCommitMessage(String commit) {
+ fail("should not be called");
+ return commit;
+ }
+
+ @Override
+ public ModifyResult editCommitMessage(String message,
+ CleanupMode mode, char commentChar) {
+ assertEquals('@', commentChar);
+ assertEquals("@ This is a combination of 4 commits.\n"
+ + "@ The first commit's message is:\n"
+ + "commit2\n"
+ + "@ This is the 2nd commit message:\n"
+ + "#commit3\n"
+ + "@ The 3rd commit message will be skipped:\n"
+ + "@ @commit4\n"
+ + "@ This is the 4th commit message:\n"
+ + ";commit5", message);
+ return new ModifyResult() {
+
+ @Override
+ public String getMessage() {
+ return message;
+ }
+
+ @Override
+ public CleanupMode getCleanupMode() {
+ return mode;
+ }
+
+ @Override
+ public boolean shouldAddChangeId() {
+ return false;
+ }
+ };
+ }
+ }).call();
+ assertEquals(Status.OK, result.getStatus());
+ Iterator<RevCommit> logIterator = git.log().all().call().iterator();
+ String actualCommitMsg = logIterator.next().getFullMessage();
+ assertEquals("commit2\n#commit3\n;commit5", actualCommitMsg);
+ }
+
private File getTodoFile() {
File todoFile = new File(db.getDirectory(), GIT_REBASE_TODO);
return todoFile;