Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Wolf2018-02-12 03:40:41 -0500
committerMatthias Sohn2018-05-05 19:19:18 -0400
commit6209c97acc74faeae0f344af0ecf9e2922e63dbd (patch)
treeac9b535f43558702d17e2b7ab05ae25b25cca16f /org.eclipse.egit.core.test/src
parent788e4174e4d4e04707c3de8fcdead4a00ad35e89 (diff)
downloadegit-6209c97acc74faeae0f344af0ecf9e2922e63dbd.tar.gz
egit-6209c97acc74faeae0f344af0ecf9e2922e63dbd.tar.xz
egit-6209c97acc74faeae0f344af0ecf9e2922e63dbd.zip
Respect gitattributes in the compare editor
Apply smudge/clean filters. Store the filters to be applied when we create the internal GitBlobStorage and apply them when the stream is opened. Unfortunately this requires quite a few interface changes to pass through CheckoutMetadata. Adds tests for the new behavior, including index edits. Bug: 520693 Change-Id: If7696501f3e1b8f6d99518915b7292e268d656bd Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
Diffstat (limited to 'org.eclipse.egit.core.test/src')
-rw-r--r--org.eclipse.egit.core.test/src/org/eclipse/egit/core/internal/storage/CommitFileRevisionTest.java333
-rw-r--r--org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantComparatorTest.java22
2 files changed, 344 insertions, 11 deletions
diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/internal/storage/CommitFileRevisionTest.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/internal/storage/CommitFileRevisionTest.java
new file mode 100644
index 000000000..2d876a9b1
--- /dev/null
+++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/internal/storage/CommitFileRevisionTest.java
@@ -0,0 +1,333 @@
+/*******************************************************************************
+ * Copyright (C) 2017, Thomas Wolf <thomas.wolf@paranor.ch>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.core.internal.storage;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.egit.core.test.GitTestCase;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.ResetCommand.ResetType;
+import org.eclipse.jgit.attributes.FilterCommand;
+import org.eclipse.jgit.attributes.FilterCommandFactory;
+import org.eclipse.jgit.attributes.FilterCommandRegistry;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.StoredConfig;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
+import org.eclipse.jgit.util.IO;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests for reading blobs from a commit with .gitattributes support.
+ */
+public class CommitFileRevisionTest extends GitTestCase {
+
+ Repository repository;
+
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ repository = FileRepositoryBuilder.create(gitDir);
+ repository.create();
+ }
+
+ @Override
+ @After
+ public void tearDown() throws Exception {
+ repository.close();
+ super.tearDown();
+ }
+
+ private java.nio.file.Path createFile(IProject base, String name,
+ String content) throws IOException {
+ java.nio.file.Path path = base.getLocation().toFile().toPath()
+ .resolve(name);
+ Files.write(path, content.getBytes(StandardCharsets.UTF_8));
+ return path;
+ }
+
+ private RevCommit setupFilter(Repository repo, IProject base,
+ boolean commit) throws Exception {
+ createFile(base, ".gitattributes", "*.txt filter=test");
+ String builtinCommandName = "egit://builtin/test/smudge";
+ FilterCommandRegistry.register(builtinCommandName,
+ new TestCommandFactory('a', 'x'));
+ StoredConfig config = repo.getConfig();
+ config.setString("filter", "test", "smudge", builtinCommandName);
+ config.save();
+ if (commit) {
+ try (Git git = new Git(repo)) {
+ git.add().addFilepattern(".").call();
+ return git.commit().setMessage("Add .gitattributes").call();
+ }
+ }
+ return null;
+ }
+
+ @Test
+ public void testWithAttributesCheckedIn() throws Exception {
+ java.nio.file.Path filePath = createFile(project.getProject(),
+ "attr.txt", "a");
+ try (Git git = new Git(repository)) {
+ git.add().addFilepattern(".").call();
+ git.commit().setMessage("Initial commit").call();
+ // Verify that we do have "a" in the repo: modify the file, do a
+ // hard reset, verify the contents to be "a" again
+ createFile(project.getProject(), "attr.txt", "aa");
+ git.reset().setMode(ResetType.HARD).call();
+ List<String> content = Files.readAllLines(filePath,
+ StandardCharsets.UTF_8);
+ assertEquals(1, content.size());
+ assertEquals("a", content.get(0));
+ // Now create a smudge filter that will replace all a's by x's, and
+ // commit the .gitattributes file.
+ RevCommit head = setupFilter(repository, project.getProject(),
+ true);
+ // Modify the file again and do a hard reset. We should end up with
+ // a file containing "x".
+ createFile(project.getProject(), "attr.txt", "aa");
+ git.reset().setMode(ResetType.HARD).call();
+ content = Files.readAllLines(filePath, StandardCharsets.UTF_8);
+ assertEquals(1, content.size());
+ assertEquals("x", content.get(0));
+ // All right. Now get a CommitFileRevision and check its contents.
+ String relativePath = repository.getWorkTree().toPath()
+ .relativize(filePath).toString();
+ CommitFileRevision fileRevision = new CommitFileRevision(repository,
+ head, relativePath);
+ ByteBuffer rawContent = null;
+ try (InputStream blobStream = fileRevision
+ .getStorage(new NullProgressMonitor()).getContents()) {
+ rawContent = IO.readWholeStream(blobStream, 1);
+ }
+ assertNotNull(rawContent);
+ String blobContent = new String(rawContent.array(), 0,
+ rawContent.limit(), StandardCharsets.UTF_8);
+ assertEquals("x", blobContent);
+ } finally {
+ FilterCommandRegistry.unregister("egit://builtin/test/smudge");
+ }
+ }
+
+ @Test
+ public void testWithAttributesNotCheckedIn() throws Exception {
+ java.nio.file.Path filePath = createFile(project.getProject(),
+ "attr.txt", "a");
+ try (Git git = new Git(repository)) {
+ git.add().addFilepattern(".").call();
+ RevCommit head = git.commit().setMessage("Initial commit").call();
+ // Verify that we do have "a" in the repo: modify the file, do a
+ // hard reset, verify the contents to be "a" again
+ createFile(project.getProject(), "attr.txt", "aa");
+ git.reset().setMode(ResetType.HARD).call();
+ List<String> content = Files.readAllLines(filePath,
+ StandardCharsets.UTF_8);
+ assertEquals(1, content.size());
+ assertEquals("a", content.get(0));
+ // Now create a smudge filter that will replace all a's by x's.
+ setupFilter(repository, project.getProject(), false);
+ // Modify the file again and do a hard reset. Interestingly we end
+ // up with a file containing 'x': the checkout does apply the
+ // not-yet-committed .gitattributes. I do not know whether that is
+ // correct.
+ createFile(project.getProject(), "attr.txt", "aa");
+ git.reset().setMode(ResetType.HARD).call();
+ content = Files.readAllLines(filePath, StandardCharsets.UTF_8);
+ assertEquals(1, content.size());
+ assertEquals("x", content.get(0));
+ // All right. Now get a CommitFileRevision and check its contents.
+ String relativePath = repository.getWorkTree().toPath()
+ .relativize(filePath).toString();
+ CommitFileRevision fileRevision = new CommitFileRevision(repository,
+ head, relativePath);
+ ByteBuffer rawContent = null;
+ try (InputStream blobStream = fileRevision
+ .getStorage(new NullProgressMonitor()).getContents()) {
+ rawContent = IO.readWholeStream(blobStream, 1);
+ }
+ assertNotNull(rawContent);
+ String blobContent = new String(rawContent.array(), 0,
+ rawContent.limit(), StandardCharsets.UTF_8);
+ // Prize question: what do we expect here? We explicitly say we
+ // want to look at an older version. (OK, in this test it happens
+ // to be HEAD, but that's immaterial.) I believe the correct
+ // behavior is to apply only the attributes as they existed in that
+ // commit, i.e., to disregard the .gitattributes in the file system.
+ // Note, however, that this means that we get a different behavior
+ // than if we checked out the commit. Also note that global/info
+ // attributes get applied in any case -- that behavior is
+ // unavoidable and appears to be wanted by the .gitattributes spec.
+ assertEquals("a", blobContent);
+ } finally {
+ FilterCommandRegistry.unregister("egit://builtin/test/smudge");
+ }
+ }
+
+ @Test
+ public void testWithAttributesNotCheckedInButWithGlobalAttributes()
+ throws Exception {
+ java.nio.file.Path filePath = createFile(project.getProject(),
+ "attr.txt", "a");
+ try (Git git = new Git(repository)) {
+ git.add().addFilepattern(".").call();
+ RevCommit head = git.commit().setMessage("Initial commit").call();
+ // Verify that we do have "a" in the repo: modify the file, do a
+ // hard reset, verify the contents to be "a" again
+ createFile(project.getProject(), "attr.txt", "aa");
+ git.reset().setMode(ResetType.HARD).call();
+ List<String> content = Files.readAllLines(filePath,
+ StandardCharsets.UTF_8);
+ assertEquals(1, content.size());
+ assertEquals("a", content.get(0));
+ // Now create a smudge filter that will replace all a's by x's.
+ setupFilter(repository, project.getProject(), false);
+ // Set up the global attributes. For simplicity, we create the file
+ // inside the work tree.
+ java.nio.file.Path globalAttributes = createFile(
+ project.getProject(), "globalattrs", "*.txt filter=test2");
+ FilterCommandRegistry.register("egit://builtin/test/smudge2",
+ new TestCommandFactory('a', 'y'));
+ StoredConfig config = repository.getConfig();
+ config.setString("core", null, "attributesFile",
+ globalAttributes.toString());
+ config.setString("filter", "test2", "smudge",
+ "egit://builtin/test/smudge2");
+ config.save();
+ // Modify the file again and do a hard reset. File contains 'x'.
+ createFile(project.getProject(), "attr.txt", "aa");
+ git.reset().setMode(ResetType.HARD).call();
+ content = Files.readAllLines(filePath, StandardCharsets.UTF_8);
+ assertEquals(1, content.size());
+ assertEquals("x", content.get(0));
+ // All right. Now get a CommitFileRevision and check its contents.
+ String relativePath = repository.getWorkTree().toPath()
+ .relativize(filePath).toString();
+ CommitFileRevision fileRevision = new CommitFileRevision(repository,
+ head, relativePath);
+ ByteBuffer rawContent = null;
+ try (InputStream blobStream = fileRevision
+ .getStorage(new NullProgressMonitor()).getContents()) {
+ rawContent = IO.readWholeStream(blobStream, 1);
+ }
+ assertNotNull(rawContent);
+ String blobContent = new String(rawContent.array(), 0,
+ rawContent.limit(), StandardCharsets.UTF_8);
+ // This should have ignored the not-yet-committed .gitignore and
+ // applied the global smudge2 command.
+ assertEquals("y", blobContent);
+ } finally {
+ FilterCommandRegistry.unregister("egit://builtin/test/smudge");
+ FilterCommandRegistry.unregister("egit://builtin/test/smudge2");
+ }
+ }
+
+ @Test
+ public void testWithAttributesCheckedInAndWithGlobalAttributes()
+ throws Exception {
+ java.nio.file.Path filePath = createFile(project.getProject(),
+ "attr.txt", "a");
+ try (Git git = new Git(repository)) {
+ git.add().addFilepattern(".").call();
+ git.commit().setMessage("Initial commit").call();
+ // Verify that we do have "a" in the repo: modify the file, do a
+ // hard reset, verify the contents to be "a" again
+ createFile(project.getProject(), "attr.txt", "aa");
+ git.reset().setMode(ResetType.HARD).call();
+ List<String> content = Files.readAllLines(filePath,
+ StandardCharsets.UTF_8);
+ assertEquals(1, content.size());
+ assertEquals("a", content.get(0));
+ // Now create a smudge filter that will replace all a's by x's.
+ RevCommit head = setupFilter(repository, project.getProject(),
+ true);
+ // Set up the global attributes. For simplicity, we create the file
+ // inside the work tree.
+ java.nio.file.Path globalAttributes = createFile(
+ project.getProject(), "globalattrs", "*.txt filter=test2");
+ FilterCommandRegistry.register("egit://builtin/test/smudge2",
+ new TestCommandFactory('a', 'y'));
+ StoredConfig config = repository.getConfig();
+ config.setString("core", null, "attributesFile",
+ globalAttributes.toString());
+ config.setString("filter", "test2", "smudge",
+ "egit://builtin/test/smudge2");
+ config.save();
+ // Modify the file again and do a hard reset. File contains 'x'.
+ createFile(project.getProject(), "attr.txt", "aa");
+ git.reset().setMode(ResetType.HARD).call();
+ content = Files.readAllLines(filePath, StandardCharsets.UTF_8);
+ assertEquals(1, content.size());
+ assertEquals("x", content.get(0));
+ // All right. Now get a CommitFileRevision and check its contents.
+ String relativePath = repository.getWorkTree().toPath()
+ .relativize(filePath).toString();
+ CommitFileRevision fileRevision = new CommitFileRevision(repository,
+ head, relativePath);
+ ByteBuffer rawContent = null;
+ try (InputStream blobStream = fileRevision
+ .getStorage(new NullProgressMonitor()).getContents()) {
+ rawContent = IO.readWholeStream(blobStream, 1);
+ }
+ assertNotNull(rawContent);
+ String blobContent = new String(rawContent.array(), 0,
+ rawContent.limit(), StandardCharsets.UTF_8);
+ assertEquals("x", blobContent);
+ } finally {
+ FilterCommandRegistry.unregister("egit://builtin/test/smudge");
+ FilterCommandRegistry.unregister("egit://builtin/test/smudge2");
+ }
+ }
+
+ private static class TestCommandFactory implements FilterCommandFactory {
+ private final int toReplace;
+
+ private final int replacement;
+
+ public TestCommandFactory(int toReplace, int replacement) {
+ this.toReplace = toReplace;
+ this.replacement = replacement;
+ }
+
+ @Override
+ public FilterCommand create(Repository repo, InputStream in,
+ final OutputStream out) {
+ FilterCommand cmd = new FilterCommand(in, out) {
+
+ @Override
+ public int run() throws IOException {
+ int b = in.read();
+ if (b == -1) {
+ return b;
+ } else if (b == toReplace) {
+ out.write(replacement);
+ } else {
+ out.write(b);
+ }
+ return 1;
+ }
+ };
+ return cmd;
+ }
+ }
+
+}
diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantComparatorTest.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantComparatorTest.java
index 088e07af8..4e2811d64 100644
--- a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantComparatorTest.java
+++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantComparatorTest.java
@@ -8,9 +8,9 @@
*******************************************************************************/
package org.eclipse.egit.core.synchronize;
+import static org.eclipse.jgit.lib.Constants.HEAD;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.eclipse.jgit.lib.Constants.HEAD;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -465,9 +465,9 @@ public class GitResourceVariantComparatorTest extends GitTestCase {
String path = Repository.stripWorkDir(repo.getWorkTree(), file);
GitRemoteFile base = new GitRemoteFile(repo, baseCommit,
- baseCommit.getTree(), path);
+ baseCommit.getTree(), path, null);
GitRemoteFile remote = new GitRemoteFile(repo, baseCommit,
- remoteCommit.getTree(), path);
+ remoteCommit.getTree(), path, null);
// then
assertFalse(grvc.compare(base, remote));
@@ -496,9 +496,9 @@ public class GitResourceVariantComparatorTest extends GitTestCase {
String path = Repository.stripWorkDir(repo.getWorkTree(), file);
GitRemoteFile base = new GitRemoteFile(repo, baseCommit,
- baseCommit.getTree(), path);
+ baseCommit.getTree(), path, null);
GitRemoteFile remote = new GitRemoteFile(repo, remoteCommit,
- remoteCommit.getTree(), path);
+ remoteCommit.getTree(), path, null);
// then
assertFalse(grvc.compare(base, remote));
@@ -526,7 +526,7 @@ public class GitResourceVariantComparatorTest extends GitTestCase {
String folderPath = Repository.stripWorkDir(repo.getWorkTree(),
new File(file.getParent()));
GitRemoteFile base = new GitRemoteFile(repo, commit, commit.getTree(),
- filePath);
+ filePath, null);
GitRemoteFolder remote = new GitRemoteFolder(repo, null, commit,
commit.getTree(), folderPath);
@@ -559,7 +559,7 @@ public class GitResourceVariantComparatorTest extends GitTestCase {
GitRemoteFolder base = new GitRemoteFolder(repo, null, commit,
commit.getTree(), folderPath);
GitRemoteFile remote = new GitRemoteFile(repo, commit,
- commit.getTree(), filePath);
+ commit.getTree(), filePath, null);
// then
assertFalse(grvc.compare(base, remote));
@@ -659,10 +659,10 @@ public class GitResourceVariantComparatorTest extends GitTestCase {
String path = Repository.stripWorkDir(repo.getWorkTree(), file);
GitRemoteFile base = new GitRemoteFile(repo, baseCommit,
- baseCommit.getTree(), path);
+ baseCommit.getTree(), path, null);
GitRemoteFile remote = new GitRemoteFile(repo, remoteCommit,
- remoteCommit.getTree(), path);
+ remoteCommit.getTree(), path, null);
// then
assertFalse(grvc.compare(base, remote));
@@ -687,10 +687,10 @@ public class GitResourceVariantComparatorTest extends GitTestCase {
String path = Repository.stripWorkDir(repo.getWorkTree(), file);
GitRemoteFile base = new GitRemoteFile(repo, commit, commit.getTree(),
- path);
+ path, null);
GitRemoteFile remote = new GitRemoteFile(repo, commit,
- commit.getTree(), path);
+ commit.getTree(), path, null);
// then
assertTrue(grvc.compare(base, remote));

Back to the top