diff options
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.java | 298 |
1 files changed, 269 insertions, 29 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 d574e45f6f..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 @@ -24,6 +24,8 @@ 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; @@ -55,6 +57,7 @@ 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; @@ -76,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 @@ -127,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()); @@ -173,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()); @@ -191,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. * @@ -270,13 +450,14 @@ public class RebaseCommandTest extends RepositoryTestCase { 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()); @@ -591,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()); } @@ -609,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()); } @@ -669,11 +852,12 @@ public class RebaseCommandTest extends RepositoryTestCase { 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()); @@ -721,8 +905,8 @@ public class RebaseCommandTest extends RepositoryTestCase { 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()); @@ -1428,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]); @@ -1440,12 +1624,14 @@ public class RebaseCommandTest extends RepositoryTestCase { 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]); @@ -1456,8 +1642,9 @@ public class RebaseCommandTest extends RepositoryTestCase { 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 @@ -2080,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"); @@ -2099,6 +2286,57 @@ 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}"); @@ -2424,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()); |