From 545358577376bec8fc140a76ce0f72bf81cc0a94 Mon Sep 17 00:00:00 2001 From: Tomasz Zarna Date: Thu, 12 Jan 2012 18:32:53 +0100 Subject: Add the no-commit option to MergeCommand Added also tests and the associated option for the command line Merge command. Bug: 335091 Change-Id: Ie321c572284a6f64765a81674089fc408a10d059 Signed-off-by: Christian Halstrick Signed-off-by: Matthias Sohn --- .../eclipse/jgit/lib/CLIRepositoryTestCase.java | 5 +- .../tst/org/eclipse/jgit/pgm/MergeTest.java | 34 ++++++ org.eclipse.jgit.pgm/.settings/.api_filters | 5 + .../org/eclipse/jgit/pgm/CLIText.properties | 2 + .../src/org/eclipse/jgit/pgm/CLIText.java | 1 + .../src/org/eclipse/jgit/pgm/Merge.java | 9 +- .../tst/org/eclipse/jgit/api/MergeCommandTest.java | 125 +++++++++++++++++++++ .../src/org/eclipse/jgit/api/MergeCommand.java | 45 ++++++-- .../src/org/eclipse/jgit/api/MergeResult.java | 27 +++++ 9 files changed, 241 insertions(+), 12 deletions(-) diff --git a/org.eclipse.jgit.pgm.test/src/org/eclipse/jgit/lib/CLIRepositoryTestCase.java b/org.eclipse.jgit.pgm.test/src/org/eclipse/jgit/lib/CLIRepositoryTestCase.java index 755174bcbc..a328baec27 100644 --- a/org.eclipse.jgit.pgm.test/src/org/eclipse/jgit/lib/CLIRepositoryTestCase.java +++ b/org.eclipse.jgit.pgm.test/src/org/eclipse/jgit/lib/CLIRepositoryTestCase.java @@ -49,7 +49,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; -import org.eclipse.jgit.internal.storage.file.FileRepository; import org.eclipse.jgit.junit.JGitTestUtil; import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase; import org.eclipse.jgit.pgm.CLIGitCommand; @@ -57,7 +56,7 @@ import org.junit.Before; public class CLIRepositoryTestCase extends LocalDiskRepositoryTestCase { /** Test repository, initialized for this test case. */ - protected FileRepository db; + protected Repository db; /** Working directory of {@link #db}. */ protected File trash; @@ -165,7 +164,7 @@ public class CLIRepositoryTestCase extends LocalDiskRepositoryTestCase { assertEquals(toText(expected), toText(actual)); } - private String toText(String[] lines) { + private static String toText(String[] lines) { StringBuilder b = new StringBuilder(); for (String s : lines) { b.append(s); diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/MergeTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/MergeTest.java index 28a107bcb1..d0b363baa9 100644 --- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/MergeTest.java +++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/MergeTest.java @@ -101,6 +101,40 @@ public class MergeTest extends CLIRepositoryTestCase { + "' strategy.", execute("git merge master")[0]); } + @Test + public void testMergeNoCommit() throws Exception { + git.branchCreate().setName("side").call(); + writeTrashFile("master", "content"); + git.add().addFilepattern("master").call(); + git.commit().setMessage("master commit").call(); + git.checkout().setName("side").call(); + writeTrashFile("side", "content"); + git.add().addFilepattern("side").call(); + git.commit().setMessage("side commit").call(); + + assertEquals( + "Automatic merge went well; stopped before committing as requested", + execute("git merge --no-commit master")[0]); + } + + @Test + public void testMergeNoCommitSquash() throws Exception { + git.branchCreate().setName("side").call(); + writeTrashFile("master", "content"); + git.add().addFilepattern("master").call(); + git.commit().setMessage("master commit").call(); + git.checkout().setName("side").call(); + writeTrashFile("side", "content"); + git.add().addFilepattern("side").call(); + git.commit().setMessage("side commit").call(); + + assertArrayEquals( + new String[] { + "Squash commit -- not updating HEAD", + "Automatic merge went well; stopped before committing as requested", + "" }, execute("git merge --no-commit --squash master")); + } + @Test public void testSquash() throws Exception { git.branchCreate().setName("side").call(); diff --git a/org.eclipse.jgit.pgm/.settings/.api_filters b/org.eclipse.jgit.pgm/.settings/.api_filters index 5e044ee2ad..35db29c922 100644 --- a/org.eclipse.jgit.pgm/.settings/.api_filters +++ b/org.eclipse.jgit.pgm/.settings/.api_filters @@ -1,6 +1,11 @@ + + + + + diff --git a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/CLIText.properties b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/CLIText.properties index d9684054c1..eed05e89f5 100644 --- a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/CLIText.properties +++ b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/CLIText.properties @@ -68,6 +68,7 @@ mergeConflict=CONFLICT(content): Merge conflict in {0} mergeFailed=Automatic merge failed; fix conflicts and then commit the result mergeMadeBy=Merge made by the ''{0}'' strategy. mergedSquashed=Squash commit -- not updating HEAD\nAutomatic merge went well; stopped before committing as requested +mergeWentWellStoppedBeforeCommitting=Automatic merge went well; stopped before committing as requested metaVar_DAG=DAG metaVar_KEY=KEY metaVar_archiveFormat=format @@ -248,6 +249,7 @@ usage_manageReflogInformation=Manage reflog information usage_mergeStrategy=Use the given merge strategy. Can be supplied more than once to specify them in the order they should be tried. If there is no -s option, the resolve strategy is used. Currently the following strategies are supported: ours, theirs, simple-two-way-in-core, resolve usage_moveRenameABranch=move/rename a branch usage_nameStatus=show only name and status of files +usage_noCommit=Don't commit after a successful merge usage_noPrefix=do not show any source or destination prefix usage_noRenames=disable rename detection usage_noShowStandardNotes=Disable showing notes from the standard /refs/notes/commits branch diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/CLIText.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/CLIText.java index 807fe39db9..64bd18e867 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/CLIText.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/CLIText.java @@ -137,6 +137,7 @@ public class CLIText extends TranslationBundle { /***/ public String mergeFailed; /***/ public String mergeMadeBy; /***/ public String mergedSquashed; + /***/ public String mergeWentWellStoppedBeforeCommitting; /***/ public String metaVar_KEY; /***/ public String metaVar_archiveFormat; /***/ public String metaVar_arg; diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Merge.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Merge.java index 7eaa5fa351..97198259d3 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Merge.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Merge.java @@ -71,6 +71,9 @@ class Merge extends TextBuiltin { @Option(name = "--squash", usage = "usage_squash") private boolean squash; + @Option(name = "--no-commit", usage = "usage_noCommit") + private boolean noCommit = false; + private MergeStrategy mergeStrategy = MergeStrategy.RESOLVE; @Argument(required = true) @@ -111,7 +114,7 @@ class Merge extends TextBuiltin { Ref oldHead = db.getRef(Constants.HEAD); Git git = new Git(db); MergeCommand mergeCmd = git.merge().setStrategy(mergeStrategy) - .setSquash(squash).setFastForward(ff); + .setSquash(squash).setFastForward(ff).setCommit(!noCommit); if (srcRef != null) mergeCmd.include(srcRef); else @@ -160,8 +163,12 @@ class Merge extends TextBuiltin { name = "recursive"; //$NON-NLS-1$ outw.println(MessageFormat.format(CLIText.get().mergeMadeBy, name)); break; + case MERGED_NOT_COMMITTED: + outw.println(CLIText.get().mergeWentWellStoppedBeforeCommitting); + break; case MERGED_SQUASHED: case FAST_FORWARD_SQUASHED: + case MERGED_SQUASHED_NOT_COMMITTED: outw.println(CLIText.get().mergedSquashed); break; case ABORTED: diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java index cf9573e44c..ba0847bd8d 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java @@ -141,6 +141,28 @@ public class MergeCommandTest extends RepositoryTestCase { db.getReflogReader(db.getBranch()).getLastEntry().getComment()); } + @Test + public void testFastForwardNoCommit() throws Exception { + Git git = new Git(db); + RevCommit first = git.commit().setMessage("initial commit").call(); + createBranch(first, "refs/heads/branch1"); + + RevCommit second = git.commit().setMessage("second commit").call(); + + checkoutBranch("refs/heads/branch1"); + + MergeResult result = git.merge().include(db.getRef(Constants.MASTER)) + .setCommit(false).call(); + + assertEquals(MergeResult.MergeStatus.FAST_FORWARD, + result.getMergeStatus()); + assertEquals(second, result.getNewHead()); + assertEquals("merge refs/heads/master: Fast-forward", db + .getReflogReader(Constants.HEAD).getLastEntry().getComment()); + assertEquals("merge refs/heads/master: Fast-forward", db + .getReflogReader(db.getBranch()).getLastEntry().getComment()); + } + @Test public void testFastForwardWithFiles() throws Exception { Git git = new Git(db); @@ -234,6 +256,31 @@ public class MergeCommandTest extends RepositoryTestCase { db.getReflogReader(db.getBranch()).getLastEntry().getComment()); } + @Theory + public void testMergeSuccessAllStrategiesNoCommit( + MergeStrategy mergeStrategy) throws Exception { + Git git = new Git(db); + + RevCommit first = git.commit().setMessage("first").call(); + createBranch(first, "refs/heads/side"); + + writeTrashFile("a", "a"); + git.add().addFilepattern("a").call(); + git.commit().setMessage("second").call(); + + checkoutBranch("refs/heads/side"); + writeTrashFile("b", "b"); + git.add().addFilepattern("b").call(); + RevCommit thirdCommit = git.commit().setMessage("third").call(); + + MergeResult result = git.merge().setStrategy(mergeStrategy) + .setCommit(false) + .include(db.getRef(Constants.MASTER)).call(); + assertEquals(MergeStatus.MERGED_NOT_COMMITTED, result.getMergeStatus()); + assertEquals(db.getRef(Constants.HEAD).getTarget().getObjectId(), + thirdCommit.getId()); + } + @Test public void testContentMerge() throws Exception { Git git = new Git(db); @@ -480,6 +527,56 @@ public class MergeCommandTest extends RepositoryTestCase { // test index state } + @Test + public void testSuccessfulContentMergeNoCommit() throws Exception { + Git git = new Git(db); + + writeTrashFile("a", "1\na\n3\n"); + writeTrashFile("b", "1\nb\n3\n"); + writeTrashFile("c/c/c", "1\nc\n3\n"); + git.add().addFilepattern("a").addFilepattern("b") + .addFilepattern("c/c/c").call(); + RevCommit initialCommit = git.commit().setMessage("initial").call(); + + createBranch(initialCommit, "refs/heads/side"); + checkoutBranch("refs/heads/side"); + + writeTrashFile("a", "1(side)\na\n3\n"); + writeTrashFile("b", "1\nb(side)\n3\n"); + git.add().addFilepattern("a").addFilepattern("b").call(); + RevCommit secondCommit = git.commit().setMessage("side").call(); + + assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b"))); + checkoutBranch("refs/heads/master"); + assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b"))); + + writeTrashFile("a", "1\na\n3(main)\n"); + writeTrashFile("c/c/c", "1\nc(main)\n3\n"); + git.add().addFilepattern("a").addFilepattern("c/c/c").call(); + RevCommit thirdCommit = git.commit().setMessage("main").call(); + + MergeResult result = git.merge().include(secondCommit.getId()) + .setCommit(false) + .setStrategy(MergeStrategy.RESOLVE).call(); + assertEquals(MergeStatus.MERGED_NOT_COMMITTED, result.getMergeStatus()); + assertEquals(db.getRef(Constants.HEAD).getTarget().getObjectId(), + thirdCommit.getId()); + + assertEquals("1(side)\na\n3(main)\n", read(new File(db.getWorkTree(), + "a"))); + assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b"))); + assertEquals("1\nc(main)\n3\n", + read(new File(db.getWorkTree(), "c/c/c"))); + + assertEquals(null, result.getConflicts()); + + assertEquals(2, result.getMergedCommits().length); + assertEquals(thirdCommit, result.getMergedCommits()[0]); + assertEquals(secondCommit, result.getMergedCommits()[1]); + assertNull(result.getNewHead()); + assertEquals(RepositoryState.MERGING_RESOLVED, db.getRepositoryState()); + } + @Test public void testSuccessfulContentMergeAndDirtyworkingTree() throws Exception { @@ -1345,6 +1442,7 @@ public class MergeCommandTest extends RepositoryTestCase { assertEquals(MergeStatus.FAST_FORWARD, result.getMergeStatus()); } + @Test public void testNoFastForward() throws Exception { Git git = new Git(db); @@ -1362,6 +1460,33 @@ public class MergeCommandTest extends RepositoryTestCase { assertEquals(MergeStatus.MERGED, result.getMergeStatus()); } + @Test + public void testNoFastForwardNoCommit() throws Exception { + // given + Git git = new Git(db); + RevCommit initialCommit = git.commit().setMessage("initial commit") + .call(); + createBranch(initialCommit, "refs/heads/branch1"); + RevCommit secondCommit = git.commit().setMessage("second commit") + .call(); + checkoutBranch("refs/heads/branch1"); + + // when + MergeCommand merge = git.merge(); + merge.setFastForward(FastForwardMode.NO_FF); + merge.include(db.getRef(Constants.MASTER)); + merge.setCommit(false); + MergeResult result = merge.call(); + + // then + assertEquals(MergeStatus.MERGED_NOT_COMMITTED, result.getMergeStatus()); + assertEquals(2, result.getMergedCommits().length); + assertEquals(initialCommit, result.getMergedCommits()[0]); + assertEquals(secondCommit, result.getMergedCommits()[1]); + assertNull(result.getNewHead()); + assertEquals(RepositoryState.MERGING_RESOLVED, db.getRepositoryState()); + } + @Test public void testFastForwardOnlyNotPossible() throws Exception { Git git = new Git(db); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java index 6c6aa7b5c5..8f6e9cbb5d 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java @@ -195,6 +195,8 @@ public class MergeCommand extends GitCommand { } } + private boolean commit = true; + /** * @param repo */ @@ -327,7 +329,7 @@ public class MergeCommand extends GitCommand { if (merger instanceof ResolveMerger) { ResolveMerger resolveMerger = (ResolveMerger) merger; resolveMerger.setCommitNames(new String[] { - "BASE", "HEAD", ref.getName() }); //$NON-NLS-1$ + "BASE", "HEAD", ref.getName() }); //$NON-NLS-1$ //$NON-NLS-2$ resolveMerger.setWorkingTreeIterator(new FileTreeIterator(repo)); noProblems = merger.merge(headCommit, srcCommit); lowLevelResults = resolveMerger @@ -350,18 +352,26 @@ public class MergeCommand extends GitCommand { dco.checkout(); String msg = null; - RevCommit newHead = null; + ObjectId newHeadId = null; MergeStatus mergeStatus = null; - if (!squash) { - newHead = new Git(getRepository()).commit() - .setReflogComment(refLogMessage.toString()).call(); + if (!commit && squash) { + mergeStatus = MergeStatus.MERGED_SQUASHED_NOT_COMMITTED; + } + if (!commit && !squash) { + mergeStatus = MergeStatus.MERGED_NOT_COMMITTED; + } + if (commit && !squash) { + newHeadId = new Git(getRepository()).commit() + .setReflogComment(refLogMessage.toString()) + .call().getId(); mergeStatus = MergeStatus.MERGED; - } else { + } + if (commit && squash) { msg = JGitText.get().squashCommitNotUpdatingHEAD; - newHead = headCommit; + newHeadId = headCommit.getId(); mergeStatus = MergeStatus.MERGED_SQUASHED; } - return new MergeResult(newHead.getId(), null, + return new MergeResult(newHeadId, null, new ObjectId[] { headCommit.getId(), srcCommit.getId() }, mergeStatus, mergeStrategy, null, msg); @@ -521,4 +531,23 @@ public class MergeCommand extends GitCommand { this.fastForwardMode = fastForwardMode; return this; } + + /** + * Controls whether the merge command should automatically commit after a + * successful merge + * + * @param commit + * true if this command should commit (this is the + * default behavior). false if this command should + * not commit. In case the merge was successful but this flag was + * set to false a {@link MergeResult} with type + * {@link MergeResult} with status + * {@link MergeStatus#MERGED_NOT_COMMITTED} is returned + * @return {@code this} + * @since 3.0 + */ + public MergeCommand setCommit(boolean commit) { + this.commit = commit; + return this; + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeResult.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeResult.java index 82272168aa..c34ba6b2d1 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeResult.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeResult.java @@ -141,6 +141,20 @@ public class MergeResult { return true; } }, + /** + * @since 3.0 + */ + MERGED_SQUASHED_NOT_COMMITTED { + @Override + public String toString() { + return "Merged-squashed-not-committed"; + } + + @Override + public boolean isSuccessful() { + return true; + } + }, /** */ CONFLICTING { @Override @@ -167,6 +181,19 @@ public class MergeResult { return false; } }, + /** + * @since 3.0 + **/ + MERGED_NOT_COMMITTED { + public String toString() { + return "MergedNotCommited"; + } + + @Override + public boolean isSuccessful() { + return true; + } + }, /** */ NOT_SUPPORTED { @Override -- cgit v1.2.3