From 9ac415aa95bdeab77142879a7f9196deb4ebefbe Mon Sep 17 00:00:00 2001 From: Thomas Wolf Date: Fri, 2 Feb 2018 08:16:13 +0100 Subject: [PATCH] Fix index blob for merges with CRLF translations Commit fc7d407 corrected line endings for working tree files resulting from merges when CRLF translations are to be done. However, that also resulted in the file content being put as-is into the index, which is wrong. The index must contain the file content with reverse CRLF translations applied. With core.autocrlf=true, the working tree file should have CR-LF, but the index blob must still contain only LF. Fix this oversight and apply the inverse translation when updating the index, similar to what is done in AddCommand. Bug: 499615 Change-Id: I3a33931318bdb580b2390f3450f91ea8f258a6a4 Signed-off-by: Thomas Wolf --- .../eclipse/jgit/merge/ResolveMergerTest.java | 3 ++ .../org/eclipse/jgit/merge/ResolveMerger.java | 48 +++++++++++++++++-- 2 files changed, 46 insertions(+), 5 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 a88efd175..ab998ebfb 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 @@ -414,6 +414,9 @@ public class ResolveMergerTest extends RepositoryTestCase { assertEquals(MergeResult.MergeStatus.MERGED, mergeResult.getMergeStatus()); checkFile(testFile, "a first line\r\na crlf file\r\na second line\r\n"); + assertEquals( + "[crlf.txt, mode:100644, content:a first line\na crlf file\na second line\n]", + indexState(CONTENT)); } /** 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 b40c19278..837528e87 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java @@ -51,6 +51,7 @@ import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_ALGORITHM; import static org.eclipse.jgit.lib.Constants.CHARACTER_ENCODING; import static org.eclipse.jgit.lib.Constants.OBJ_BLOB; +import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; @@ -903,17 +904,54 @@ public class ResolveMerger extends ThreeWayMerger { long len = mergedFile.length(); dce.setLastModified(FS.DETECTED.lastModified(mergedFile)); dce.setLength((int) len); - InputStream is = new FileInputStream(mergedFile); - try { - dce.setObjectId(getObjectInserter().insert(OBJ_BLOB, len, is)); - } finally { - is.close(); + EolStreamType streamType = EolStreamTypeUtil.detectStreamType( + OperationType.CHECKIN_OP, workingTreeOptions, + tw.getAttributes()); + long blobLen = len == 0 ? 0 + : getEntryContentLength(mergedFile, streamType); + // TODO: we read the file twice because insert() needs the blob + // length up front. C.f. AddCommand. + try (InputStream is = EolStreamTypeUtil.wrapInputStream( + new FileInputStream(mergedFile), streamType)) { + dce.setObjectId( + getObjectInserter().insert(OBJ_BLOB, blobLen, is)); } } else dce.setObjectId(insertMergeResult(result)); builder.add(dce); } + /** + * Computes the length of the index blob for a given file. + * + * @param file + * on disk + * @param streamType + * specifying CRLF translation + * @return the number of bytes after CRLF translations have been done. + * @throws IOException + * if the file cannot be read + */ + private long getEntryContentLength(File file, EolStreamType streamType) + throws IOException { + if (streamType == EolStreamType.DIRECT) { + return file.length(); + } + long length = 0; + try (InputStream is = EolStreamTypeUtil.wrapInputStream( + new BufferedInputStream(new FileInputStream(file)), + streamType)) { + for (;;) { + long n = is.skip(1 << 20); + if (n <= 0) { + break; + } + length += n; + } + return length; + } + } + /** * Writes merged file content to the working tree. *