diff options
author | Matthias Sohn | 2018-05-12 09:55:41 -0400 |
---|---|---|
committer | Gerrit Code Review @ Eclipse.org | 2018-05-12 09:55:41 -0400 |
commit | aeb507087b4d9416cd76ec5f1229984c6413f025 (patch) | |
tree | 3d08c7dad1852c59268849d5449336123bd69025 /org.eclipse.egit.core.test/src | |
parent | 8d542d09f4d21f333a513add7c50e8e53b9273b0 (diff) | |
parent | 6209c97acc74faeae0f344af0ecf9e2922e63dbd (diff) | |
download | egit-aeb507087b4d9416cd76ec5f1229984c6413f025.tar.gz egit-aeb507087b4d9416cd76ec5f1229984c6413f025.tar.xz egit-aeb507087b4d9416cd76ec5f1229984c6413f025.zip |
Merge "Respect gitattributes in the compare editor"
Diffstat (limited to 'org.eclipse.egit.core.test/src')
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)); |