aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonrad Kügler2014-01-12 07:39:18 (EST)
committerRobin Rosenberg2014-03-10 07:22:57 (EDT)
commitefd91ef8a7e9d97fab08a6b9a5e181c846b744cb (patch)
tree6163a9c3c552506a697bba433ed9c5edde789ec0
parent7e258e6468a2bbb357bfb06d4e844cf694325b10 (diff)
downloadjgit-efd91ef8a7e9d97fab08a6b9a5e181c846b744cb.zip
jgit-efd91ef8a7e9d97fab08a6b9a5e181c846b744cb.tar.gz
jgit-efd91ef8a7e9d97fab08a6b9a5e181c846b744cb.tar.bz2
Take core.autocrlf into account for blame annotationsrefs/changes/43/20543/4
Blaming with core.autocrlf set to 'true' - even for freshly checked out files - showed all lines as being locally modified. For autocrlf = true the line breaks of the local file will be converted to LF for blaming. This results in useful diffs and therefor in the desired blame annotations. For autocrlf = input no conversion takes place to cope with CRLF line breaks in the repository, in addition to the usual LF. For autocrlf = true CRLF line breaks in the repo can't be supported without additional effort. In that case the whole local file will be blamed as being locally modified. Change-Id: If020dcca54d16b2fb79210a070b8480aec82e58e Signed-off-by: Konrad Kügler <swamblumat-eclipsebugs@yahoo.de> Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/BlameCommandTest.java61
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/BlameCommand.java58
2 files changed, 117 insertions, 2 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/BlameCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/BlameCommandTest.java
index 7b2e85f..20e93f8 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/BlameCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/BlameCommandTest.java
@@ -45,9 +45,15 @@ package org.eclipse.jgit.api;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import java.io.File;
+
+import org.eclipse.jgit.api.ResetCommand.ResetType;
import org.eclipse.jgit.blame.BlameResult;
import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.lib.ConfigConstants;
+import org.eclipse.jgit.lib.CoreConfig.AutoCRLF;
import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.junit.Test;
/**
@@ -325,4 +331,59 @@ public class BlameCommandTest extends RepositoryTestCase {
assertEquals(commit3, lines.getSourceCommit(1));
assertEquals(commit3, lines.getSourceCommit(2));
}
+
+ @Test
+ public void testCoreAutoCrlf1() throws Exception {
+ testCoreAutoCrlf(AutoCRLF.INPUT, AutoCRLF.FALSE);
+ }
+
+ @Test
+ public void testCoreAutoCrlf2() throws Exception {
+ testCoreAutoCrlf(AutoCRLF.FALSE, AutoCRLF.FALSE);
+ }
+
+ @Test
+ public void testCoreAutoCrlf3() throws Exception {
+ testCoreAutoCrlf(AutoCRLF.INPUT, AutoCRLF.INPUT);
+ }
+
+ @Test
+ public void testCoreAutoCrlf4() throws Exception {
+ testCoreAutoCrlf(AutoCRLF.FALSE, AutoCRLF.INPUT);
+ }
+
+ @Test
+ public void testCoreAutoCrlf5() throws Exception {
+ testCoreAutoCrlf(AutoCRLF.INPUT, AutoCRLF.TRUE);
+ }
+
+ private void testCoreAutoCrlf(AutoCRLF modeForCommitting,
+ AutoCRLF modeForReset) throws Exception {
+ Git git = new Git(db);
+ FileBasedConfig config = db.getConfig();
+ config.setEnum(ConfigConstants.CONFIG_CORE_SECTION, null,
+ ConfigConstants.CONFIG_KEY_AUTOCRLF, modeForCommitting);
+ config.save();
+
+ String joinedCrlf = "a\r\nb\r\nc\r\n";
+ File trashFile = writeTrashFile("file.txt", joinedCrlf);
+ git.add().addFilepattern("file.txt").call();
+ RevCommit commit = git.commit().setMessage("create file").call();
+
+ // re-create file from the repo
+ trashFile.delete();
+ config.setEnum(ConfigConstants.CONFIG_CORE_SECTION, null,
+ ConfigConstants.CONFIG_KEY_AUTOCRLF, modeForReset);
+ config.save();
+ git.reset().setMode(ResetType.HARD).call();
+
+ BlameCommand command = new BlameCommand(db);
+ command.setFilePath("file.txt");
+ BlameResult lines = command.call();
+
+ assertEquals(3, lines.getResultContents().size());
+ assertEquals(commit, lines.getSourceCommit(0));
+ assertEquals(commit, lines.getSourceCommit(1));
+ assertEquals(commit, lines.getSourceCommit(2));
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/BlameCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/BlameCommand.java
index 2972614..f7ce835 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/BlameCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/BlameCommand.java
@@ -43,7 +43,10 @@
package org.eclipse.jgit.api;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
+import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -60,6 +63,10 @@ import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.CoreConfig.AutoCRLF;
+import org.eclipse.jgit.treewalk.WorkingTreeOptions;
+import org.eclipse.jgit.util.IO;
+import org.eclipse.jgit.util.io.EolCanonicalizingInputStream;
/**
* Blame command for building a {@link BlameResult} for a file path.
@@ -215,8 +222,10 @@ public class BlameCommand extends GitCommand<BlameResult> {
gen.push(null, dc.getEntry(entry).getObjectId());
File inTree = new File(repo.getWorkTree(), path);
- if (repo.getFS().isFile(inTree))
- gen.push(null, new RawText(inTree));
+ if (repo.getFS().isFile(inTree)) {
+ RawText rawText = getRawText(inTree);
+ gen.push(null, rawText);
+ }
}
}
return gen.computeBlameResult();
@@ -226,4 +235,49 @@ public class BlameCommand extends GitCommand<BlameResult> {
gen.release();
}
}
+
+ private RawText getRawText(File inTree) throws IOException,
+ FileNotFoundException {
+ RawText rawText;
+
+ WorkingTreeOptions workingTreeOptions = getRepository().getConfig()
+ .get(WorkingTreeOptions.KEY);
+ AutoCRLF autoCRLF = workingTreeOptions.getAutoCRLF();
+ switch (autoCRLF) {
+ case FALSE:
+ case INPUT:
+ // Git used the repo format on checkout, but other tools
+ // may change the format to CRLF. We ignore that here.
+ rawText = new RawText(inTree);
+ break;
+ case TRUE:
+ EolCanonicalizingInputStream in = new EolCanonicalizingInputStream(
+ new FileInputStream(inTree), true);
+ // Canonicalization should lead to same or shorter length
+ // (CRLF to LF), so the file size on disk is an upper size bound
+ rawText = new RawText(toByteArray(in, (int) inTree.length()));
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "Unknown autocrlf option " + autoCRLF); //$NON-NLS-1$
+ }
+ return rawText;
+ }
+
+ private static byte[] toByteArray(InputStream source, int upperSizeLimit)
+ throws IOException {
+ byte[] buffer = new byte[upperSizeLimit];
+ try {
+ int read = IO.readFully(source, buffer, 0);
+ if (read == upperSizeLimit)
+ return buffer;
+ else {
+ byte[] copy = new byte[read];
+ System.arraycopy(buffer, 0, copy, 0, read);
+ return copy;
+ }
+ } finally {
+ source.close();
+ }
+ }
}