From fd62a456499a57e5ae09c490b8bf2c72ff55154a Mon Sep 17 00:00:00 2001 From: Robin Rosenberg Date: Sun, 15 Dec 2013 16:57:01 +0100 Subject: [PATCH] Fix merge/cherry-picking in CRLF mode This fixes a case where we have CRLF in the repo but LF in the worktree and are in autocrlf mode. Change-Id: I0388270c1cf0fd22dfd513bcaa404eb97268d39d Signed-off-by: Matthias Sohn --- .../eclipse/jgit/merge/ResolveMergerTest.java | 32 +++++++++++++++++++ .../org/eclipse/jgit/merge/ResolveMerger.java | 23 ++++++++----- 2 files changed, 47 insertions(+), 8 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 54de8cfb4..dd06168c3 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 @@ -53,6 +53,7 @@ import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.MergeResult; import org.eclipse.jgit.api.MergeResult.MergeStatus; import org.eclipse.jgit.api.errors.CheckoutConflictException; +import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.JGitInternalException; import org.eclipse.jgit.dircache.DirCache; import org.eclipse.jgit.errors.NoMergeBaseException; @@ -264,6 +265,37 @@ public class ResolveMergerTest extends RepositoryTestCase { indexState(CONTENT)); } + @Theory + public void mergeWithCrlfInWT(MergeStrategy strategy) throws IOException, + GitAPIException { + Git git = Git.wrap(db); + db.getConfig().setString("core", null, "autocrlf", "false"); + db.getConfig().save(); + writeTrashFile("crlf.txt", "some\r\ndata\r\n"); + git.add().addFilepattern("crlf.txt").call(); + git.commit().setMessage("base").call(); + + git.branchCreate().setName("brancha").call(); + + writeTrashFile("crlf.txt", "some\r\nmore\r\ndata\r\n"); + git.add().addFilepattern("crlf.txt").call(); + git.commit().setMessage("on master").call(); + + git.checkout().setName("brancha").call(); + writeTrashFile("crlf.txt", "some\r\ndata\r\ntoo\r\n"); + git.add().addFilepattern("crlf.txt").call(); + git.commit().setMessage("on brancha").call(); + + db.getConfig().setString("core", null, "autocrlf", "input"); + db.getConfig().save(); + + MergeResult mergeResult = git.merge().setStrategy(strategy) + .include(db.resolve("master")) + .call(); + assertEquals(MergeResult.MergeStatus.MERGED, + mergeResult.getMergeStatus()); + } + /** * 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/merge/ResolveMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java index 414746dc4..a891c8591 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java @@ -439,7 +439,7 @@ public class ResolveMerger extends ThreeWayMerger { else { // the preferred version THEIRS has a different mode // than ours. Check it out! - if (isWorktreeDirty(work)) + if (isWorktreeDirty(work, ourDce)) return false; // we know about length and lastMod only after we have written the new content. // This will happen later. Set these values to 0 for know. @@ -477,7 +477,7 @@ public class ResolveMerger extends ThreeWayMerger { // THEIRS. THEIRS is chosen. // Check worktree before checking out THEIRS - if (isWorktreeDirty(work)) + if (isWorktreeDirty(work, ourDce)) return false; if (nonTree(modeT)) { // we know about length and lastMod only after we have written @@ -535,7 +535,7 @@ public class ResolveMerger extends ThreeWayMerger { if (nonTree(modeO) && nonTree(modeT)) { // Check worktree before modifying files - if (isWorktreeDirty(work)) + if (isWorktreeDirty(work, ourDce)) return false; // Don't attempt to resolve submodule link conflicts @@ -566,7 +566,7 @@ public class ResolveMerger extends ThreeWayMerger { // OURS was deleted checkout THEIRS if (modeO == 0) { // Check worktree before checking out THEIRS - if (isWorktreeDirty(work)) + if (isWorktreeDirty(work, ourDce)) return false; if (nonTree(modeT)) { if (e != null) @@ -625,7 +625,8 @@ public class ResolveMerger extends ThreeWayMerger { return isDirty; } - private boolean isWorktreeDirty(WorkingTreeIterator work) { + private boolean isWorktreeDirty(WorkingTreeIterator work, + DirCacheEntry ourDce) throws IOException { if (work == null) return false; @@ -633,9 +634,15 @@ public class ResolveMerger extends ThreeWayMerger { final int modeO = tw.getRawMode(T_OURS); // Worktree entry has to match ours to be considered clean - boolean isDirty = work.isModeDifferent(modeO); - if (!isDirty && nonTree(modeF)) - isDirty = !tw.idEqual(T_FILE, T_OURS); + boolean isDirty; + if (ourDce != null) + isDirty = work.isModified(ourDce, true, reader); + else { + 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)