read(new File(db.getWorkTree(), "c/c/c")));
}
+ public void testDeletionAndConflict() throws Exception {
+ Git git = new Git(db);
+
+ writeTrashFile("a", "1\na\n3\n");
+ writeTrashFile("b", "1\nb\n3\n");
+ writeTrashFile("d", "1\nd\n3\n");
+ writeTrashFile("c/c/c", "1\nc\n3\n");
+ git.add().addFilepattern("a").addFilepattern("b")
+ .addFilepattern("c/c/c").addFilepattern("d").call();
+ RevCommit initialCommit = git.commit().setMessage("initial").call();
+
+ createBranch(initialCommit, "refs/heads/side");
+ checkoutBranch("refs/heads/side");
+
+ assertTrue(new File(db.getWorkTree(), "b").delete());
+ writeTrashFile("a", "1\na\n3(side)\n");
+ git.add().addFilepattern("b").setUpdate(true).call();
+ git.add().addFilepattern("a").setUpdate(true).call();
+ RevCommit secondCommit = git.commit().setMessage("side").call();
+
+ assertFalse(new File(db.getWorkTree(), "b").exists());
+ checkoutBranch("refs/heads/master");
+ assertTrue(new File(db.getWorkTree(), "b").exists());
+
+ 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();
+ git.commit().setMessage("main").call();
+
+ // We are merging a deletion into our branch
+ MergeResult result = git.merge().include(secondCommit.getId())
+ .setStrategy(MergeStrategy.RESOLVE).call();
+ assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
+
+ assertEquals(
+ "1\na\n<<<<<<< HEAD\n3(main)\n=======\n3(side)\n>>>>>>> 54ffed45d62d252715fc20e41da92d44c48fb0ff\n",
+ read(new File(db.getWorkTree(), "a")));
+ assertFalse(new File(db.getWorkTree(), "b").exists());
+ assertEquals("1\nc(main)\n3\n",
+ read(new File(db.getWorkTree(), "c/c/c")));
+ }
+
public void testMergeFailingWithDirtyWorkingTree() throws Exception {
Git git = new Git(db);
/** the merge failed because of a dirty index */
DIRTY_INDEX,
/** the merge failed because of a dirty workingtree */
- DIRTY_WORKTREE
+ DIRTY_WORKTREE,
+ /** the merge failed because of a file could not be deleted */
+ COULD_NOT_DELETE
}
private NameConflictTreeWalk tw;
private void checkout() throws NoWorkTreeException, IOException {
for (Map.Entry<String, DirCacheEntry> entry : toBeCheckedOut.entrySet()) {
File f = new File(db.getWorkTree(), entry.getKey());
- createDir(f.getParentFile());
- DirCacheCheckout.checkoutEntry(db,
- f,
- entry.getValue(), true);
+ if (entry.getValue() != null) {
+ createDir(f.getParentFile());
+ DirCacheCheckout.checkoutEntry(db,
+ f,
+ entry.getValue(), true);
+ } else {
+ if (!f.delete())
+ failingPathes.put(entry.getKey(),
+ MergeFailureReason.COULD_NOT_DELETE);
+ }
modifiedFiles.add(entry.getKey());
}
}
return true;
}
- if (nonTree(modeT) && modeB == modeO && tw.idEqual(T_BASE, T_OURS)) {
+ if (modeB == modeO && tw.idEqual(T_BASE, T_OURS)) {
// OURS was not changed compared to base. All changes must be in
// THEIRS. Choose THEIRS.
- DirCacheEntry e=add(tw.getRawPath(), theirs, DirCacheEntry.STAGE_0);
- if (e!=null)
- toBeCheckedOut.put(tw.getPathString(), e);
- return true;
+ if (nonTree(modeT)) {
+ DirCacheEntry e = add(tw.getRawPath(), theirs,
+ DirCacheEntry.STAGE_0);
+ if (e != null)
+ toBeCheckedOut.put(tw.getPathString(), e);
+ return true;
+ } else if (modeT == 0) {
+ // we want THEIRS ... but THEIRS contains the deletion of the
+ // file
+ toBeCheckedOut.put(tw.getPathString(), null);
+ return true;
+ }
}
if (tw.isSubtree()) {