Merge "Respect .gitattributes diff overrides in diff operations"
diff --git a/java/com/google/gerrit/server/patch/gitfilediff/GitFileDiff.java b/java/com/google/gerrit/server/patch/gitfilediff/GitFileDiff.java
index 580aef5..23b0024 100644
--- a/java/com/google/gerrit/server/patch/gitfilediff/GitFileDiff.java
+++ b/java/com/google/gerrit/server/patch/gitfilediff/GitFileDiff.java
@@ -32,6 +32,7 @@
import com.google.gerrit.server.patch.filediff.Edit;
import com.google.protobuf.Descriptors.FieldDescriptor;
import java.util.Optional;
+import org.eclipse.jgit.attributes.Attribute;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.lib.AbbreviatedObjectId;
import org.eclipse.jgit.lib.FileMode;
@@ -66,8 +67,17 @@
* parameters.
*/
static GitFileDiff create(DiffEntry diffEntry, FileHeader fileHeader) {
+ Attribute diffAttr = diffEntry.getDiffAttribute();
+ // Treat the file as binary if .gitattributes explicitly unsets diffing (e.g. "-diff"
+ // or the "binary" macro which JGit expands to "-diff -merge -text").
+ boolean isBinary = diffAttr != null && diffAttr.getState() == Attribute.State.UNSET;
+
ImmutableList<Edit> edits =
- fileHeader.toEditList().stream().map(Edit::fromJGitEdit).collect(toImmutableList());
+ isBinary
+ ? ImmutableList.of()
+ : fileHeader.toEditList().stream().map(Edit::fromJGitEdit).collect(toImmutableList());
+
+ PatchType patchType = isBinary ? PatchType.BINARY : FileHeaderUtil.getPatchType(fileHeader);
return builder()
.edits(edits)
@@ -77,7 +87,7 @@
.oldPath(FileHeaderUtil.getOldPath(fileHeader))
.newPath(FileHeaderUtil.getNewPath(fileHeader))
.changeType(FileHeaderUtil.getChangeType(fileHeader))
- .patchType(Optional.of(FileHeaderUtil.getPatchType(fileHeader)))
+ .patchType(Optional.of(patchType))
.oldMode(Optional.of(mapFileMode(diffEntry.getOldMode())))
.newMode(Optional.of(mapFileMode(diffEntry.getNewMode())))
.build();
diff --git a/javatests/com/google/gerrit/server/patch/DiffOperationsTest.java b/javatests/com/google/gerrit/server/patch/DiffOperationsTest.java
index 7c8555e..1234262 100644
--- a/javatests/com/google/gerrit/server/patch/DiffOperationsTest.java
+++ b/javatests/com/google/gerrit/server/patch/DiffOperationsTest.java
@@ -20,6 +20,7 @@
import com.google.common.collect.ImmutableList;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Patch.ChangeType;
+import com.google.gerrit.entities.Patch.PatchType;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.server.git.GitRepositoryManager;
@@ -423,6 +424,66 @@
}
}
+ @Test
+ public void gitattributesDiffOverride() throws Exception {
+ String jsonFile = "file_2.json";
+ // 1. First, let's create a commit where the file is modified but there is no .gitattributes.
+ // It should be diffed as UNIFIED.
+ ObjectId oldCommitId1 =
+ createCommit(repo, null, ImmutableList.of(new FileEntity(jsonFile, "{}")));
+ ObjectId newCommitId1 =
+ createCommit(
+ repo, oldCommitId1, ImmutableList.of(new FileEntity(jsonFile, "{\"foo\": \"bar\"}")));
+ FileDiffOutput diffOutput1 =
+ diffOperations.getModifiedFileAgainstParent(
+ testProjectName, newCommitId1, 0, jsonFile, null);
+ assertThat(diffOutput1.patchType()).hasValue(PatchType.UNIFIED);
+ assertThat(diffOutput1.edits()).isNotEmpty();
+
+ // 2. Now let's create a commit where .gitattributes specifies "-diff" for the file.
+ // It should be treated as BINARY.
+ ObjectId oldCommitId2 =
+ createCommit(
+ repo,
+ null,
+ ImmutableList.of(
+ new FileEntity(".gitattributes", jsonFile + " -diff"),
+ new FileEntity(jsonFile, "{}")));
+ ObjectId newCommitId2 =
+ createCommit(
+ repo,
+ oldCommitId2,
+ ImmutableList.of(
+ new FileEntity(".gitattributes", jsonFile + " -diff"),
+ new FileEntity(jsonFile, "{\"foo\": \"bar\"}")));
+ FileDiffOutput diffOutput2 =
+ diffOperations.getModifiedFileAgainstParent(
+ testProjectName, newCommitId2, 0, jsonFile, null);
+ assertThat(diffOutput2.patchType()).hasValue(PatchType.BINARY);
+ assertThat(diffOutput2.edits()).isEmpty();
+
+ // 3. Let's also test with "binary" macro attribute.
+ ObjectId oldCommitId3 =
+ createCommit(
+ repo,
+ null,
+ ImmutableList.of(
+ new FileEntity(".gitattributes", jsonFile + " binary"),
+ new FileEntity(jsonFile, "{}")));
+ ObjectId newCommitId3 =
+ createCommit(
+ repo,
+ oldCommitId3,
+ ImmutableList.of(
+ new FileEntity(".gitattributes", jsonFile + " binary"),
+ new FileEntity(jsonFile, "{\"foo\": \"bar\"}")));
+ FileDiffOutput diffOutput3 =
+ diffOperations.getModifiedFileAgainstParent(
+ testProjectName, newCommitId3, 0, jsonFile, null);
+ assertThat(diffOutput3.patchType()).hasValue(PatchType.BINARY);
+ assertThat(diffOutput3.edits()).isEmpty();
+ }
+
static class FileEntity {
String name;
String content;