]> source.dussan.org Git - jgit.git/commitdiff
Honor CRLF settings when writing merge results 63/116563/4
authorThomas Wolf <thomas.wolf@paranor.ch>
Thu, 1 Feb 2018 20:58:23 +0000 (21:58 +0100)
committerMatthias Sohn <matthias.sohn@sap.com>
Thu, 1 Feb 2018 23:45:32 +0000 (00:45 +0100)
Merges are performed using the raw text as stored in the git
repository. When we write the merge result, we must apply the
correct CRLF settings. Otherwise the line endings in the result
will be wrong.

Bug: 499615
Change-Id: I37a9b987e9404c97645d2720cd1c7c04c076a96b
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/RepositoryTestCase.java
org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/ResolveMergerTest.java
org.eclipse.jgit/.settings/.api_filters [new file with mode: 0644]
org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java

index 044f08072af366b63ff5b1d3092470094d88da5f..8f44620b802d4aa8e2f378f99ef054c9d0da5add 100644 (file)
@@ -197,14 +197,14 @@ public abstract class RepositoryTestCase extends LocalDiskRepositoryTestCase {
         */
        protected static void checkFile(File f, final String checkData)
                        throws IOException {
-               Reader r = new InputStreamReader(new FileInputStream(f), "UTF-8");
-               try {
-                       char[] data = new char[checkData.length()];
-                       if (checkData.length() != r.read(data))
-                               throw new IOException("Internal error reading file data from "+f);
-                       assertEquals(checkData, new String(data));
-               } finally {
-                       r.close();
+               try (Reader r = new InputStreamReader(new FileInputStream(f),
+                               "UTF-8")) {
+                       if (checkData.length() > 0) {
+                               char[] data = new char[checkData.length()];
+                               assertEquals(data.length, r.read(data));
+                               assertEquals(checkData, new String(data));
+                       }
+                       assertEquals(-1, r.read());
                }
        }
 
index 3272d598bc6513243ab1c245612901960f214ee7..a88efd17555fc75f560d25b840b8c7f1b248bdc1 100644 (file)
@@ -387,6 +387,35 @@ public class ResolveMergerTest extends RepositoryTestCase {
                                mergeResult.getMergeStatus());
        }
 
+       @Theory
+       public void mergeWithCrlfAutoCrlfTrue(MergeStrategy strategy)
+                       throws IOException, GitAPIException {
+               Git git = Git.wrap(db);
+               db.getConfig().setString("core", null, "autocrlf", "true");
+               db.getConfig().save();
+               writeTrashFile("crlf.txt", "a crlf file\r\n");
+               git.add().addFilepattern("crlf.txt").call();
+               git.commit().setMessage("base").call();
+
+               git.branchCreate().setName("brancha").call();
+
+               writeTrashFile("crlf.txt", "a crlf file\r\na second line\r\n");
+               git.add().addFilepattern("crlf.txt").call();
+               git.commit().setMessage("on master").call();
+
+               git.checkout().setName("brancha").call();
+               File testFile = writeTrashFile("crlf.txt",
+                               "a first line\r\na crlf file\r\n");
+               git.add().addFilepattern("crlf.txt").call();
+               git.commit().setMessage("on brancha").call();
+
+               MergeResult mergeResult = git.merge().setStrategy(strategy)
+                               .include(db.resolve("master")).call();
+               assertEquals(MergeResult.MergeStatus.MERGED,
+                               mergeResult.getMergeStatus());
+               checkFile(testFile, "a first line\r\na crlf file\r\na second line\r\n");
+       }
+
        /**
         * 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/.settings/.api_filters b/org.eclipse.jgit/.settings/.api_filters
new file mode 100644 (file)
index 0000000..293c60b
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<component id="org.eclipse.jgit" version="2">
+    <resource path="src/org/eclipse/jgit/merge/ResolveMerger.java" type="org.eclipse.jgit.merge.ResolveMerger">
+        <filter id="336658481">
+            <message_arguments>
+                <message_argument value="org.eclipse.jgit.merge.ResolveMerger"/>
+                <message_argument value="workingTreeOptions"/>
+            </message_arguments>
+        </filter>
+    </resource>
+</component>
index 5646529ddc0005f8fc8747c0b273a802f551bb44..b40c192783acc3b99e655768771a30b53cb84171 100644 (file)
@@ -87,6 +87,7 @@ import org.eclipse.jgit.errors.MissingObjectException;
 import org.eclipse.jgit.errors.NoWorkTreeException;
 import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.lib.ConfigConstants;
+import org.eclipse.jgit.lib.CoreConfig.EolStreamType;
 import org.eclipse.jgit.lib.FileMode;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectInserter;
@@ -99,10 +100,13 @@ import org.eclipse.jgit.treewalk.AbstractTreeIterator;
 import org.eclipse.jgit.treewalk.CanonicalTreeParser;
 import org.eclipse.jgit.treewalk.NameConflictTreeWalk;
 import org.eclipse.jgit.treewalk.TreeWalk;
+import org.eclipse.jgit.treewalk.TreeWalk.OperationType;
 import org.eclipse.jgit.treewalk.WorkingTreeIterator;
+import org.eclipse.jgit.treewalk.WorkingTreeOptions;
 import org.eclipse.jgit.treewalk.filter.TreeFilter;
 import org.eclipse.jgit.util.FS;
 import org.eclipse.jgit.util.TemporaryBuffer;
+import org.eclipse.jgit.util.io.EolStreamTypeUtil;
 
 /**
  * A three-way merger performing a content-merge if necessary
@@ -277,8 +281,16 @@ public class ResolveMerger extends ThreeWayMerger {
        protected MergeAlgorithm mergeAlgorithm;
 
        /**
-        * The size limit (bytes) which controls a file to be stored in {@code Heap} or
-        * {@code LocalFile} during the merge.
+        * The {@link WorkingTreeOptions} are needed to determine line endings for
+        * merged files.
+        *
+        * @since 4.11
+        */
+       protected WorkingTreeOptions workingTreeOptions;
+
+       /**
+        * The size limit (bytes) which controls a file to be stored in {@code Heap}
+        * or {@code LocalFile} during the merge.
         */
        private int inCoreLimit;
 
@@ -319,6 +331,7 @@ public class ResolveMerger extends ThreeWayMerger {
                        dircache = DirCache.newInCore();
                } else {
                        implicitDirCache = true;
+                       workingTreeOptions = local.getConfig().get(WorkingTreeOptions.KEY);
                }
        }
 
@@ -916,10 +929,15 @@ public class ResolveMerger extends ThreeWayMerger {
                FS fs = nonNullRepo().getFS();
                File of = new File(workTree, tw.getPathString());
                File parentFolder = of.getParentFile();
-               if (!fs.exists(parentFolder))
+               if (!fs.exists(parentFolder)) {
                        parentFolder.mkdirs();
-               try (OutputStream os = new BufferedOutputStream(
-                               new FileOutputStream(of))) {
+               }
+               EolStreamType streamType = EolStreamTypeUtil.detectStreamType(
+                               OperationType.CHECKOUT_OP, workingTreeOptions,
+                               tw.getAttributes());
+               try (OutputStream os = EolStreamTypeUtil.wrapOutputStream(
+                               new BufferedOutputStream(new FileOutputStream(of)),
+                               streamType)) {
                        new MergeFormatter().formatMerge(os, result,
                                        Arrays.asList(commitNames), CHARACTER_ENCODING);
                }