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;
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;
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);
+ "' 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();
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<component id="org.eclipse.jgit.pgm" version="2">
<resource path="src/org/eclipse/jgit/pgm/CLIText.java" type="org.eclipse.jgit.pgm.CLIText">
+ <filter id="1143996420">
+ <message_arguments>
+ <message_argument value="mergeWentWellStoppedBeforeCommitting"/>
+ </message_arguments>
+ </filter>
<filter id="1143996420">
<message_arguments>
<message_argument value="noSuchRemoteRef"/>
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
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
/***/ public String mergeFailed;
/***/ public String mergeMadeBy;
/***/ public String mergedSquashed;
+ /***/ public String mergeWentWellStoppedBeforeCommitting;
/***/ public String metaVar_KEY;
/***/ public String metaVar_archiveFormat;
/***/ public String metaVar_arg;
@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)
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
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:
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);
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);
// 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 {
assertEquals(MergeStatus.FAST_FORWARD, result.getMergeStatus());
}
+
@Test
public void testNoFastForward() throws Exception {
Git git = new Git(db);
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);
}
}
+ private boolean commit = true;
+
/**
* @param repo
*/
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
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);
this.fastForwardMode = fastForwardMode;
return this;
}
+
+ /**
+ * Controls whether the merge command should automatically commit after a
+ * successful merge
+ *
+ * @param commit
+ * <code>true</code> if this command should commit (this is the
+ * default behavior). <code>false</code> if this command should
+ * not commit. In case the merge was successful but this flag was
+ * set to <code>false</code> 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;
+ }
}
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
return false;
}
},
+ /**
+ * @since 3.0
+ **/
+ MERGED_NOT_COMMITTED {
+ public String toString() {
+ return "MergedNotCommited";
+ }
+
+ @Override
+ public boolean isSuccessful() {
+ return true;
+ }
+ },
/** */
NOT_SUPPORTED {
@Override