Browse Source

Honor CRLF settings when writing merge results

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>
stable-4.11
Thomas Wolf 7 years ago committed by Matthias Sohn
parent
commit
fc7d407d0b
  1. 16
      org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/RepositoryTestCase.java
  2. 29
      org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/ResolveMergerTest.java
  3. 11
      org.eclipse.jgit/.settings/.api_filters
  4. 28
      org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java

16
org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/RepositoryTestCase.java

@ -197,14 +197,14 @@ public abstract class RepositoryTestCase extends LocalDiskRepositoryTestCase {
*/ */
protected static void checkFile(File f, final String checkData) protected static void checkFile(File f, final String checkData)
throws IOException { throws IOException {
Reader r = new InputStreamReader(new FileInputStream(f), "UTF-8"); try (Reader r = new InputStreamReader(new FileInputStream(f),
try { "UTF-8")) {
char[] data = new char[checkData.length()]; if (checkData.length() > 0) {
if (checkData.length() != r.read(data)) char[] data = new char[checkData.length()];
throw new IOException("Internal error reading file data from "+f); assertEquals(data.length, r.read(data));
assertEquals(checkData, new String(data)); assertEquals(checkData, new String(data));
} finally { }
r.close(); assertEquals(-1, r.read());
} }
} }

29
org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/ResolveMergerTest.java

@ -387,6 +387,35 @@ public class ResolveMergerTest extends RepositoryTestCase {
mergeResult.getMergeStatus()); 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 * Merging two equal subtrees when the index does not contain any file in
* that subtree should lead to a merged state. * that subtree should lead to a merged state.

11
org.eclipse.jgit/.settings/.api_filters

@ -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>

28
org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java

@ -87,6 +87,7 @@ import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.NoWorkTreeException; import org.eclipse.jgit.errors.NoWorkTreeException;
import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.CoreConfig.EolStreamType;
import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter; 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.CanonicalTreeParser;
import org.eclipse.jgit.treewalk.NameConflictTreeWalk; import org.eclipse.jgit.treewalk.NameConflictTreeWalk;
import org.eclipse.jgit.treewalk.TreeWalk; import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.TreeWalk.OperationType;
import org.eclipse.jgit.treewalk.WorkingTreeIterator; import org.eclipse.jgit.treewalk.WorkingTreeIterator;
import org.eclipse.jgit.treewalk.WorkingTreeOptions;
import org.eclipse.jgit.treewalk.filter.TreeFilter; import org.eclipse.jgit.treewalk.filter.TreeFilter;
import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.TemporaryBuffer; import org.eclipse.jgit.util.TemporaryBuffer;
import org.eclipse.jgit.util.io.EolStreamTypeUtil;
/** /**
* A three-way merger performing a content-merge if necessary * A three-way merger performing a content-merge if necessary
@ -277,8 +281,16 @@ public class ResolveMerger extends ThreeWayMerger {
protected MergeAlgorithm mergeAlgorithm; protected MergeAlgorithm mergeAlgorithm;
/** /**
* The size limit (bytes) which controls a file to be stored in {@code Heap} or * The {@link WorkingTreeOptions} are needed to determine line endings for
* {@code LocalFile} during the merge. * 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; private int inCoreLimit;
@ -319,6 +331,7 @@ public class ResolveMerger extends ThreeWayMerger {
dircache = DirCache.newInCore(); dircache = DirCache.newInCore();
} else { } else {
implicitDirCache = true; implicitDirCache = true;
workingTreeOptions = local.getConfig().get(WorkingTreeOptions.KEY);
} }
} }
@ -916,10 +929,15 @@ public class ResolveMerger extends ThreeWayMerger {
FS fs = nonNullRepo().getFS(); FS fs = nonNullRepo().getFS();
File of = new File(workTree, tw.getPathString()); File of = new File(workTree, tw.getPathString());
File parentFolder = of.getParentFile(); File parentFolder = of.getParentFile();
if (!fs.exists(parentFolder)) if (!fs.exists(parentFolder)) {
parentFolder.mkdirs(); 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, new MergeFormatter().formatMerge(os, result,
Arrays.asList(commitNames), CHARACTER_ENCODING); Arrays.asList(commitNames), CHARACTER_ENCODING);
} }

Loading…
Cancel
Save