From 3cd089f04cf1122e6a9d0a6f842ddd0b46a7a9bd Mon Sep 17 00:00:00 2001 From: Robin Rosenberg Date: Mon, 18 Feb 2013 23:59:20 +0100 Subject: [PATCH] A folder does not constitute a dirty work tree This fixes two cases: - A folder without tracked content exist both in the workdir and merged commit, as long as there names within that folder does not conflict. - An empty folder structure exists with the same name as a file in the merged commit. Bug: 402834 Change-Id: I4c5b9f11313dd1665fcbdae2d0755fdb64deb3ef --- .../eclipse/jgit/merge/ResolveMergerTest.java | 77 +++++++++++++++++++ .../jgit/dircache/DirCacheCheckout.java | 3 +- .../org/eclipse/jgit/merge/ResolveMerger.java | 5 +- 3 files changed, 83 insertions(+), 2 deletions(-) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/ResolveMergerTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/ResolveMergerTest.java index d8ef2dd6b..72762437d 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/ResolveMergerTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/ResolveMergerTest.java @@ -188,6 +188,83 @@ public void checkMergeMergeableTreesWithoutIndex(MergeStrategy strategy) indexState(CONTENT)); } + /** + * An existing directory without tracked content should not prevent merging + * a tree where that directory exists. + * + * @param strategy + * @throws Exception + */ + @Theory + public void checkUntrackedFolderIsNotAConflict( + MergeStrategy strategy) throws Exception { + Git git = Git.wrap(db); + + writeTrashFile("d/1", "1"); + git.add().addFilepattern("d/1").call(); + RevCommit first = git.commit().setMessage("added d/1").call(); + + writeTrashFile("e/1", "4"); + git.add().addFilepattern("e/1").call(); + RevCommit masterCommit = git.commit().setMessage("added e/1").call(); + + git.checkout().setCreateBranch(true).setStartPoint(first) + .setName("side").call(); + writeTrashFile("f/1", "5"); + git.add().addFilepattern("f/1").call(); + git.commit().setAll(true).setMessage("added f/1") + .call(); + + // Untracked directory e shall not conflict with merged e/1 + writeTrashFile("e/2", "d two"); + + MergeResult mergeRes = git.merge().setStrategy(strategy) + .include(masterCommit).call(); + assertEquals(MergeStatus.MERGED, mergeRes.getMergeStatus()); + assertEquals( + "[d/1, mode:100644, content:1][e/1, mode:100644, content:4][f/1, mode:100644, content:5]", + indexState(CONTENT)); + } + + /** + * An existing directory without tracked content should not prevent merging + * a file with that name. + * + * @param strategy + * @throws Exception + */ + @Theory + public void checkUntrackedEmpytFolderIsNotAConflictWithFile( + MergeStrategy strategy) + throws Exception { + Git git = Git.wrap(db); + + writeTrashFile("d/1", "1"); + git.add().addFilepattern("d/1").call(); + RevCommit first = git.commit().setMessage("added d/1").call(); + + writeTrashFile("e", "4"); + git.add().addFilepattern("e").call(); + RevCommit masterCommit = git.commit().setMessage("added e").call(); + + git.checkout().setCreateBranch(true).setStartPoint(first) + .setName("side").call(); + writeTrashFile("f/1", "5"); + git.add().addFilepattern("f/1").call(); + git.commit().setAll(true).setMessage("added f/1").call(); + + // Untracked empty directory hierarcy e/1 shall not conflict with merged + // e/1 + FileUtils.mkdirs(new File(trash, "e/1"), true); + + MergeResult mergeRes = git.merge().setStrategy(strategy) + .include(masterCommit).call(); + assertEquals(MergeStatus.MERGED, mergeRes.getMergeStatus()); + assertEquals( + "[d/1, mode:100644, content:1][e, mode:100644, content:4][f/1, mode:100644, content:5]", + indexState(CONTENT)); + } + /** * Merging two equal subtrees when the index does not contain any file in * that subtree should lead to a merged state. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java index 292206e53..dd9023fc7 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java @@ -1129,7 +1129,8 @@ public static void checkoutEntry(final Repository repo, File f, if (!tmpFile.renameTo(f)) { // tried to rename which failed. Let' delete the target file and try // again - FileUtils.delete(f); + FileUtils.delete(f, FileUtils.EMPTY_DIRECTORIES_ONLY + | FileUtils.RECURSIVE); if (!tmpFile.renameTo(f)) { throw new IOException(MessageFormat.format( JGitText.get().couldNotWriteFile, tmpFile.getPath(), 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 bea211933..213a1d4da 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java @@ -621,7 +621,10 @@ private boolean isWorktreeDirty(WorkingTreeIterator work) { boolean isDirty = work.isModeDifferent(modeO); if (!isDirty && nonTree(modeF)) isDirty = !tw.idEqual(T_FILE, T_OURS); - + // Ignore existing empty directories + if (isDirty && modeF == FileMode.TYPE_TREE + && modeO == FileMode.TYPE_MISSING) + isDirty = false; if (isDirty) failingPaths.put(tw.getPathString(), MergeFailureReason.DIRTY_WORKTREE);