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 <christian.halstrick@sap.com>
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
This commit is contained in:
Tomasz Zarna 2012-01-12 18:32:53 +01:00
parent 81b601de53
commit 5453585773
9 changed files with 241 additions and 12 deletions

View File

@ -49,7 +49,6 @@
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 @@
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 @@ protected void assertArrayOfLinesEquals(String[] expected, String[] actual) {
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);

View File

@ -101,6 +101,40 @@ public void testMerge() throws Exception {
+ "' 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();

View File

@ -1,6 +1,11 @@
<?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"/>

View File

@ -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

View File

@ -137,6 +137,7 @@ public static String formatLine(String line) {
/***/ public String mergeFailed;
/***/ public String mergeMadeBy;
/***/ public String mergedSquashed;
/***/ public String mergeWentWellStoppedBeforeCommitting;
/***/ public String metaVar_KEY;
/***/ public String metaVar_archiveFormat;
/***/ public String metaVar_arg;

View File

@ -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 @@ protected void run() throws Exception {
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 @@ protected void run() throws Exception {
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:

View File

@ -141,6 +141,28 @@ public void testFastForward() throws Exception {
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 void testMergeSuccessAllStrategies(MergeStrategy mergeStrategy)
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 void testSuccessfulContentMerge() throws Exception {
// 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 void testFastForwardOnly() throws Exception {
assertEquals(MergeStatus.FAST_FORWARD, result.getMergeStatus());
}
@Test
public void testNoFastForward() throws Exception {
Git git = new Git(db);
@ -1362,6 +1460,33 @@ public void testNoFastForward() throws Exception {
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);

View File

@ -195,6 +195,8 @@ public static FastForwardMode valueOf(FastForwardMode.Merge ffMode) {
}
}
private boolean commit = true;
/**
* @param repo
*/
@ -327,7 +329,7 @@ public MergeResult call() throws GitAPIException, NoHeadException,
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 MergeResult call() throws GitAPIException, NoHeadException,
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 MergeCommand setFastForward(FastForwardMode fastForwardMode) {
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;
}
}

View File

@ -141,6 +141,20 @@ public boolean isSuccessful() {
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 boolean isSuccessful() {
return false;
}
},
/**
* @since 3.0
**/
MERGED_NOT_COMMITTED {
public String toString() {
return "MergedNotCommited";
}
@Override
public boolean isSuccessful() {
return true;
}
},
/** */
NOT_SUPPORTED {
@Override