summaryrefslogtreecommitdiffstatsabout
diff options
context:
space:
mode:
authorPhilipp Thun2011-03-17 05:48:44 (EDT)
committer Christian Halstrick2011-03-18 12:04:50 (EDT)
commitbf05108d0b1aa7253659237d6848abc72c5e185e (patch)
tree605ee359b2e475b05f649dc2a28cad549fd791df
parent28ffed23072e0b1e8697adc53448c2c71f0d1306 (diff)
downloadjgit-bf05108d0b1aa7253659237d6848abc72c5e185e.zip
jgit-bf05108d0b1aa7253659237d6848abc72c5e185e.tar.gz
jgit-bf05108d0b1aa7253659237d6848abc72c5e185e.tar.bz2
Abort merge when file to be checked out is dirtyrefs/changes/33/2733/3
In case a file needs to be checked out (from THEIRS) during a merge operation, it has to be checked if the worktree version of this file is dirty. If this is true, merge shall fail. Change-Id: I17c24845584700aad953c3d4f2bea77a0d665ec4 Signed-off-by: Philipp Thun <philipp.thun@sap.com>
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java158
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java4
2 files changed, 162 insertions, 0 deletions
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 987e647..2761989 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
@@ -638,6 +638,164 @@ public class MergeCommandTest extends RepositoryTestCase {
assertEquals(RepositoryState.MERGING, db.getRepositoryState());
}
+ @Test
+ public void testSuccessfulMergeFailsDueToDirtyIndex() throws Exception {
+ Git git = new Git(db);
+
+ File fileA = writeTrashFile("a", "a");
+ RevCommit initialCommit = addAllAndCommit(git);
+
+ // switch branch
+ createBranch(initialCommit, "refs/heads/side");
+ checkoutBranch("refs/heads/side");
+ // modify file a
+ write(fileA, "a(side)");
+ writeTrashFile("b", "b");
+ RevCommit sideCommit = addAllAndCommit(git);
+
+ // switch branch
+ checkoutBranch("refs/heads/master");
+ writeTrashFile("c", "c");
+ addAllAndCommit(git);
+
+ // modify and add file a
+ write(fileA, "a(modified)");
+ git.add().addFilepattern("a").call();
+ // do not commit
+
+ // get current index state
+ String indexState = indexState(CONTENT);
+
+ // merge
+ MergeResult result = git.merge().include(sideCommit.getId())
+ .setStrategy(MergeStrategy.RESOLVE).call();
+
+ checkMergeFailedResult(result, indexState, fileA);
+ }
+
+ @Test
+ public void testConflictingMergeFailsDueToDirtyIndex() throws Exception {
+ Git git = new Git(db);
+
+ File fileA = writeTrashFile("a", "a");
+ RevCommit initialCommit = addAllAndCommit(git);
+
+ // switch branch
+ createBranch(initialCommit, "refs/heads/side");
+ checkoutBranch("refs/heads/side");
+ // modify file a
+ write(fileA, "a(side)");
+ writeTrashFile("b", "b");
+ RevCommit sideCommit = addAllAndCommit(git);
+
+ // switch branch
+ checkoutBranch("refs/heads/master");
+ // modify file a - this will cause a conflict during merge
+ write(fileA, "a(master)");
+ writeTrashFile("c", "c");
+ addAllAndCommit(git);
+
+ // modify and add file a
+ write(fileA, "a(modified)");
+ git.add().addFilepattern("a").call();
+ // do not commit
+
+ // get current index state
+ String indexState = indexState(CONTENT);
+
+ // merge
+ MergeResult result = git.merge().include(sideCommit.getId())
+ .setStrategy(MergeStrategy.RESOLVE).call();
+
+ checkMergeFailedResult(result, indexState, fileA);
+ }
+
+ @Test
+ public void testSuccessfulMergeFailsDueToDirtyWorktree() throws Exception {
+ Git git = new Git(db);
+
+ File fileA = writeTrashFile("a", "a");
+ RevCommit initialCommit = addAllAndCommit(git);
+
+ // switch branch
+ createBranch(initialCommit, "refs/heads/side");
+ checkoutBranch("refs/heads/side");
+ // modify file a
+ write(fileA, "a(side)");
+ writeTrashFile("b", "b");
+ RevCommit sideCommit = addAllAndCommit(git);
+
+ // switch branch
+ checkoutBranch("refs/heads/master");
+ writeTrashFile("c", "c");
+ addAllAndCommit(git);
+
+ // modify file a
+ write(fileA, "a(modified)");
+ // do not add and commit
+
+ // get current index state
+ String indexState = indexState(CONTENT);
+
+ // merge
+ MergeResult result = git.merge().include(sideCommit.getId())
+ .setStrategy(MergeStrategy.RESOLVE).call();
+
+ checkMergeFailedResult(result, indexState, fileA);
+ }
+
+ @Test
+ public void testConflictingMergeFailsDueToDirtyWorktree() throws Exception {
+ Git git = new Git(db);
+
+ File fileA = writeTrashFile("a", "a");
+ RevCommit initialCommit = addAllAndCommit(git);
+
+ // switch branch
+ createBranch(initialCommit, "refs/heads/side");
+ checkoutBranch("refs/heads/side");
+ // modify file a
+ write(fileA, "a(side)");
+ writeTrashFile("b", "b");
+ RevCommit sideCommit = addAllAndCommit(git);
+
+ // switch branch
+ checkoutBranch("refs/heads/master");
+ // modify file a - this will cause a conflict during merge
+ write(fileA, "a(master)");
+ writeTrashFile("c", "c");
+ addAllAndCommit(git);
+
+ // modify file a
+ write(fileA, "a(modified)");
+ // do not add and commit
+
+ // get current index state
+ String indexState = indexState(CONTENT);
+
+ // merge
+ MergeResult result = git.merge().include(sideCommit.getId())
+ .setStrategy(MergeStrategy.RESOLVE).call();
+
+ checkMergeFailedResult(result, indexState, fileA);
+ }
+
+ private RevCommit addAllAndCommit(final Git git) throws Exception {
+ git.add().addFilepattern(".").call();
+ return git.commit().setMessage("message").call();
+ }
+
+ private void checkMergeFailedResult(final MergeResult result,
+ final String indexState, final File fileA) throws Exception {
+ assertEquals(MergeStatus.FAILED, result.getMergeStatus());
+ assertEquals("a(modified)", read(fileA));
+ assertFalse(new File(db.getWorkTree(), "b").exists());
+ assertEquals("c", read(new File(db.getWorkTree(), "c")));
+ assertEquals(indexState, indexState(CONTENT));
+ assertEquals(null, result.getConflicts());
+ assertEquals(RepositoryState.SAFE, db.getRepositoryState());
+ }
+
private void createBranch(ObjectId objectId, String branchName) throws IOException {
RefUpdate updateRef = db.updateRef(branchName);
updateRef.setNewObjectId(objectId);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java
index a055131..5e99fc0 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java
@@ -393,6 +393,10 @@ public class ResolveMerger extends ThreeWayMerger {
if (modeB == modeO && tw.idEqual(T_BASE, T_OURS)) {
// OURS was not changed compared to BASE. All changes must be in
// THEIRS. THEIRS is chosen.
+
+ // Check worktree before checking out THEIRS
+ if (isWorktreeDirty())
+ return false;
if (nonTree(modeT)) {
DirCacheEntry e = add(tw.getRawPath(), theirs,
DirCacheEntry.STAGE_0);