diff options
Diffstat (limited to 'org.eclipse.jgit.test')
23 files changed, 1452 insertions, 212 deletions
diff --git a/org.eclipse.jgit.test/BUILD b/org.eclipse.jgit.test/BUILD index e63c02c03c..5066808f6a 100644 --- a/org.eclipse.jgit.test/BUILD +++ b/org.eclipse.jgit.test/BUILD @@ -13,6 +13,7 @@ HELPERS = glob( ) + [PKG + c for c in [ "api/AbstractRemoteCommandTest.java", "diff/AbstractDiffTestCase.java", + "diff/AbstractRenameDetectionTestCase.java", "internal/diffmergetool/ExternalToolTestCase.java", "internal/revwalk/ObjectReachabilityTestCase.java", "internal/revwalk/ReachabilityCheckerTestCase.java", diff --git a/org.eclipse.jgit.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.test/META-INF/MANIFEST.MF index 381a71957f..97fe1be744 100644 --- a/org.eclipse.jgit.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.test/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Automatic-Module-Name: org.eclipse.jgit.test Bundle-SymbolicName: org.eclipse.jgit.test -Bundle-Version: 6.2.1.qualifier +Bundle-Version: 6.3.1.qualifier Bundle-Localization: plugin Bundle-Vendor: %Bundle-Vendor Bundle-RequiredExecutionEnvironment: JavaSE-11 @@ -16,61 +16,62 @@ Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)", org.apache.commons.compress.compressors.gzip;version="[1.15.0,2.0)", org.apache.commons.compress.compressors.xz;version="[1.15.0,2.0)", org.assertj.core.api;version="[3.14.0,4.0.0)", - org.eclipse.jgit.annotations;version="[6.2.1,6.3.0)", - org.eclipse.jgit.api;version="[6.2.1,6.3.0)", - org.eclipse.jgit.api.errors;version="[6.2.1,6.3.0)", - org.eclipse.jgit.archive;version="[6.2.1,6.3.0)", - org.eclipse.jgit.attributes;version="[6.2.1,6.3.0)", - org.eclipse.jgit.awtui;version="[6.2.1,6.3.0)", - org.eclipse.jgit.blame;version="[6.2.1,6.3.0)", - org.eclipse.jgit.diff;version="[6.2.1,6.3.0)", - org.eclipse.jgit.dircache;version="[6.2.1,6.3.0)", - org.eclipse.jgit.errors;version="[6.2.1,6.3.0)", - org.eclipse.jgit.events;version="[6.2.1,6.3.0)", - org.eclipse.jgit.fnmatch;version="[6.2.1,6.3.0)", - org.eclipse.jgit.gitrepo;version="[6.2.1,6.3.0)", - org.eclipse.jgit.hooks;version="[6.2.1,6.3.0)", - org.eclipse.jgit.ignore;version="[6.2.1,6.3.0)", - org.eclipse.jgit.ignore.internal;version="[6.2.1,6.3.0)", - org.eclipse.jgit.internal;version="[6.2.1,6.3.0)", - org.eclipse.jgit.internal.diffmergetool;version="[6.2.1,6.3.0)", - org.eclipse.jgit.internal.fsck;version="[6.2.1,6.3.0)", - org.eclipse.jgit.internal.revwalk;version="[6.2.1,6.3.0)", - org.eclipse.jgit.internal.storage.dfs;version="[6.2.1,6.3.0)", - org.eclipse.jgit.internal.storage.file;version="[6.2.1,6.3.0)", - org.eclipse.jgit.internal.storage.io;version="[6.2.1,6.3.0)", - org.eclipse.jgit.internal.storage.pack;version="[6.2.1,6.3.0)", - org.eclipse.jgit.internal.storage.reftable;version="[6.2.1,6.3.0)", - org.eclipse.jgit.internal.transport.connectivity;version="[6.2.1,6.3.0)", - org.eclipse.jgit.internal.transport.http;version="[6.2.1,6.3.0)", - org.eclipse.jgit.internal.transport.parser;version="[6.2.1,6.3.0)", - org.eclipse.jgit.internal.transport.ssh;version="[6.2.1,6.3.0)", - org.eclipse.jgit.junit;version="[6.2.1,6.3.0)", - org.eclipse.jgit.junit.time;version="[6.2.1,6.3.0)", - org.eclipse.jgit.lfs;version="[6.2.1,6.3.0)", - org.eclipse.jgit.lib;version="[6.2.1,6.3.0)", - org.eclipse.jgit.lib.internal;version="[6.2.1,6.3.0)", - org.eclipse.jgit.logging;version="[6.2.1,6.3.0)", - org.eclipse.jgit.merge;version="[6.2.1,6.3.0)", - org.eclipse.jgit.nls;version="[6.2.1,6.3.0)", - org.eclipse.jgit.notes;version="[6.2.1,6.3.0)", - org.eclipse.jgit.patch;version="[6.2.1,6.3.0)", - org.eclipse.jgit.pgm;version="[6.2.1,6.3.0)", - org.eclipse.jgit.pgm.internal;version="[6.2.1,6.3.0)", - org.eclipse.jgit.revplot;version="[6.2.1,6.3.0)", - org.eclipse.jgit.revwalk;version="[6.2.1,6.3.0)", - org.eclipse.jgit.revwalk.filter;version="[6.2.1,6.3.0)", - org.eclipse.jgit.storage.file;version="[6.2.1,6.3.0)", - org.eclipse.jgit.storage.pack;version="[6.2.1,6.3.0)", - org.eclipse.jgit.submodule;version="[6.2.1,6.3.0)", - org.eclipse.jgit.transport;version="[6.2.1,6.3.0)", - org.eclipse.jgit.transport.http;version="[6.2.1,6.3.0)", - org.eclipse.jgit.transport.resolver;version="[6.2.1,6.3.0)", - org.eclipse.jgit.treewalk;version="[6.2.1,6.3.0)", - org.eclipse.jgit.treewalk.filter;version="[6.2.1,6.3.0)", - org.eclipse.jgit.util;version="[6.2.1,6.3.0)", - org.eclipse.jgit.util.io;version="[6.2.1,6.3.0)", - org.eclipse.jgit.util.sha1;version="[6.2.1,6.3.0)", + org.eclipse.jgit.annotations;version="[6.3.1,6.4.0)", + org.eclipse.jgit.api;version="[6.3.1,6.4.0)", + org.eclipse.jgit.api.errors;version="[6.3.1,6.4.0)", + org.eclipse.jgit.archive;version="[6.3.1,6.4.0)", + org.eclipse.jgit.attributes;version="[6.3.1,6.4.0)", + org.eclipse.jgit.awtui;version="[6.3.1,6.4.0)", + org.eclipse.jgit.blame;version="[6.3.1,6.4.0)", + org.eclipse.jgit.diff;version="[6.3.1,6.4.0)", + org.eclipse.jgit.dircache;version="[6.3.1,6.4.0)", + org.eclipse.jgit.errors;version="[6.3.1,6.4.0)", + org.eclipse.jgit.events;version="[6.3.1,6.4.0)", + org.eclipse.jgit.fnmatch;version="[6.3.1,6.4.0)", + org.eclipse.jgit.gitrepo;version="[6.3.1,6.4.0)", + org.eclipse.jgit.hooks;version="[6.3.1,6.4.0)", + org.eclipse.jgit.ignore;version="[6.3.1,6.4.0)", + org.eclipse.jgit.ignore.internal;version="[6.3.1,6.4.0)", + org.eclipse.jgit.internal;version="[6.3.1,6.4.0)", + org.eclipse.jgit.internal.diff;version="[6.3.1,6.4.0)", + org.eclipse.jgit.internal.diffmergetool;version="[6.3.1,6.4.0)", + org.eclipse.jgit.internal.fsck;version="[6.3.1,6.4.0)", + org.eclipse.jgit.internal.revwalk;version="[6.3.1,6.4.0)", + org.eclipse.jgit.internal.storage.dfs;version="[6.3.1,6.4.0)", + org.eclipse.jgit.internal.storage.file;version="[6.3.1,6.4.0)", + org.eclipse.jgit.internal.storage.io;version="[6.3.1,6.4.0)", + org.eclipse.jgit.internal.storage.pack;version="[6.3.1,6.4.0)", + org.eclipse.jgit.internal.storage.reftable;version="[6.3.1,6.4.0)", + org.eclipse.jgit.internal.transport.connectivity;version="[6.3.1,6.4.0)", + org.eclipse.jgit.internal.transport.http;version="[6.3.1,6.4.0)", + org.eclipse.jgit.internal.transport.parser;version="[6.3.1,6.4.0)", + org.eclipse.jgit.internal.transport.ssh;version="[6.3.1,6.4.0)", + org.eclipse.jgit.junit;version="[6.3.1,6.4.0)", + org.eclipse.jgit.junit.time;version="[6.3.1,6.4.0)", + org.eclipse.jgit.lfs;version="[6.3.1,6.4.0)", + org.eclipse.jgit.lib;version="[6.3.1,6.4.0)", + org.eclipse.jgit.lib.internal;version="[6.3.1,6.4.0)", + org.eclipse.jgit.logging;version="[6.3.1,6.4.0)", + org.eclipse.jgit.merge;version="[6.3.1,6.4.0)", + org.eclipse.jgit.nls;version="[6.3.1,6.4.0)", + org.eclipse.jgit.notes;version="[6.3.1,6.4.0)", + org.eclipse.jgit.patch;version="[6.3.1,6.4.0)", + org.eclipse.jgit.pgm;version="[6.3.1,6.4.0)", + org.eclipse.jgit.pgm.internal;version="[6.3.1,6.4.0)", + org.eclipse.jgit.revplot;version="[6.3.1,6.4.0)", + org.eclipse.jgit.revwalk;version="[6.3.1,6.4.0)", + org.eclipse.jgit.revwalk.filter;version="[6.3.1,6.4.0)", + org.eclipse.jgit.storage.file;version="[6.3.1,6.4.0)", + org.eclipse.jgit.storage.pack;version="[6.3.1,6.4.0)", + org.eclipse.jgit.submodule;version="[6.3.1,6.4.0)", + org.eclipse.jgit.transport;version="[6.3.1,6.4.0)", + org.eclipse.jgit.transport.http;version="[6.3.1,6.4.0)", + org.eclipse.jgit.transport.resolver;version="[6.3.1,6.4.0)", + org.eclipse.jgit.treewalk;version="[6.3.1,6.4.0)", + org.eclipse.jgit.treewalk.filter;version="[6.3.1,6.4.0)", + org.eclipse.jgit.util;version="[6.3.1,6.4.0)", + org.eclipse.jgit.util.io;version="[6.3.1,6.4.0)", + org.eclipse.jgit.util.sha1;version="[6.3.1,6.4.0)", org.hamcrest;version="[1.1.0,3.0.0)", org.hamcrest.collection;version="[1.1.0,3.0.0)", org.junit;version="[4.13,5.0.0)", @@ -85,4 +86,4 @@ Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)", org.mockito.stubbing;version="[2.23.0,3.0.0)", org.objenesis;version="[2.6.0,3.0.0)", org.slf4j;version="[1.7.0,2.0.0)", - org.tukaani.xz;version="[1.6.0,2.0)" + org.tukaani.xz diff --git a/org.eclipse.jgit.test/pom.xml b/org.eclipse.jgit.test/pom.xml index efba3e0ed9..3eb762f0c2 100644 --- a/org.eclipse.jgit.test/pom.xml +++ b/org.eclipse.jgit.test/pom.xml @@ -19,7 +19,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>6.2.1-SNAPSHOT</version> + <version>6.3.1-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.test</artifactId> @@ -42,19 +42,19 @@ <!-- Optional security provider for encryption tests. --> <dependency> <groupId>org.bouncycastle</groupId> - <artifactId>bcprov-jdk15on</artifactId> + <artifactId>bcprov-jdk18on</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.bouncycastle</groupId> - <artifactId>bcpg-jdk15on</artifactId> + <artifactId>bcpg-jdk18on</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.bouncycastle</groupId> - <artifactId>bcpkix-jdk15on</artifactId> + <artifactId>bcpkix-jdk18on</artifactId> <scope>test</scope> </dependency> diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java index 5dfdfcfe6b..57661a7eca 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java @@ -15,13 +15,16 @@ import static org.eclipse.jgit.util.FileUtils.RECURSIVE; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.junit.Assume.assumeTrue; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.PrintWriter; +import java.nio.file.Files; import java.util.Set; +import org.eclipse.jgit.api.ResetCommand.ResetType; import org.eclipse.jgit.api.errors.FilterFailedException; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.NoFilepatternException; @@ -34,6 +37,7 @@ import org.eclipse.jgit.junit.RepositoryTestCase; import org.eclipse.jgit.lfs.BuiltinLFS; import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.CoreConfig.SymLinks; import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectInserter; @@ -100,6 +104,43 @@ public class AddCommandTest extends RepositoryTestCase { } @Test + public void testAddLink() throws IOException, GitAPIException { + assumeTrue(db.getFS().supportsSymlinks()); + try (Git git = new Git(db)) { + writeTrashFile("a.txt", "a"); + File link = new File(db.getWorkTree(), "link"); + db.getFS().createSymLink(link, "a.txt"); + git.add().addFilepattern(".").call(); + assertEquals( + "[a.txt, mode:100644, content:a][link, mode:120000, content:a.txt]", + indexState(CONTENT)); + git.commit().setMessage("link").call(); + StoredConfig config = db.getConfig(); + config.setEnum(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_SYMLINKS, SymLinks.FALSE); + config.save(); + Files.delete(link.toPath()); + git.reset().setMode(ResetType.HARD).call(); + assertTrue(Files.isRegularFile(link.toPath())); + assertEquals( + "[a.txt, mode:100644, content:a][link, mode:120000, content:a.txt]", + indexState(CONTENT)); + writeTrashFile("link", "b.txt"); + git.add().addFilepattern("link").call(); + assertEquals( + "[a.txt, mode:100644, content:a][link, mode:120000, content:b.txt]", + indexState(CONTENT)); + config.setEnum(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_SYMLINKS, SymLinks.TRUE); + config.save(); + git.add().addFilepattern("link").call(); + assertEquals( + "[a.txt, mode:100644, content:a][link, mode:100644, content:b.txt]", + indexState(CONTENT)); + } + } + + @Test public void testCleanFilter() throws IOException, GitAPIException { writeTrashFile(".gitattributes", "*.txt filter=tstFilter"); writeTrashFile("src/a.tmp", "foo"); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ApplyCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ApplyCommandTest.java index 584d149631..40764b739b 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ApplyCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ApplyCommandTest.java @@ -525,9 +525,9 @@ public class ApplyCommandTest extends RepositoryTestCase { @Test public void testRenameNoHunks() throws Exception { ApplyResult result = init("RenameNoHunks", true, true); - assertEquals(1, result.getUpdatedFiles().size()); - assertEquals(new File(db.getWorkTree(), "RenameNoHunks"), result.getUpdatedFiles() - .get(0)); + assertEquals(2, result.getUpdatedFiles().size()); + assertTrue(result.getUpdatedFiles().contains(new File(db.getWorkTree(), "RenameNoHunks"))); + assertTrue(result.getUpdatedFiles().contains(new File(db.getWorkTree(), "nested/subdir/Renamed"))); checkFile(new File(db.getWorkTree(), "nested/subdir/Renamed"), b.getString(0, b.size(), false)); } @@ -535,9 +535,9 @@ public class ApplyCommandTest extends RepositoryTestCase { @Test public void testRenameWithHunks() throws Exception { ApplyResult result = init("RenameWithHunks", true, true); - assertEquals(1, result.getUpdatedFiles().size()); - assertEquals(new File(db.getWorkTree(), "RenameWithHunks"), result.getUpdatedFiles() - .get(0)); + assertEquals(2, result.getUpdatedFiles().size()); + assertTrue(result.getUpdatedFiles().contains(new File(db.getWorkTree(), "RenameWithHunks"))); + assertTrue(result.getUpdatedFiles().contains(new File(db.getWorkTree(), "nested/subdir/Renamed"))); checkFile(new File(db.getWorkTree(), "nested/subdir/Renamed"), b.getString(0, b.size(), false)); } @@ -546,7 +546,7 @@ public class ApplyCommandTest extends RepositoryTestCase { public void testCopyWithHunks() throws Exception { ApplyResult result = init("CopyWithHunks", true, true); assertEquals(1, result.getUpdatedFiles().size()); - assertEquals(new File(db.getWorkTree(), "CopyWithHunks"), result.getUpdatedFiles() + assertEquals(new File(db.getWorkTree(), "CopyResult"), result.getUpdatedFiles() .get(0)); checkFile(new File(db.getWorkTree(), "CopyResult"), b.getString(0, b.size(), false)); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CleanCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CleanCommandTest.java index f8078890b7..204c89db9b 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CleanCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CleanCommandTest.java @@ -301,4 +301,25 @@ public class CleanCommandTest extends RepositoryTestCase { writeTrashFile("this_is/not_ok/more/subdirs/file.txt", "2"); git.clean().setCleanDirectories(true).setIgnore(false).call(); } + + @Test + public void testPrefix() throws Exception { + File a = writeTrashFile("a.txt", "a"); + File b = writeTrashFile("a/a.txt", "sub a"); + File dir = b.getParentFile(); + git.clean().call(); + assertFalse(a.exists()); + assertTrue(dir.exists()); + assertTrue(b.exists()); + } + + @Test + public void testPrefixWithDir() throws Exception { + File a = writeTrashFile("a.txt", "a"); + File b = writeTrashFile("a/a.txt", "sub a"); + File dir = b.getParentFile(); + git.clean().setCleanDirectories(true).call(); + assertFalse(a.exists()); + assertFalse(dir.exists()); + } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java index c928d2ad22..6053c8c568 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011, 2013 Chris Aniszczyk <caniszczyk@gmail.com> and others + * Copyright (C) 2011, 2022 Chris Aniszczyk <caniszczyk@gmail.com> and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at @@ -19,10 +19,14 @@ import static org.junit.Assert.fail; import java.io.File; import java.io.IOException; import java.net.URISyntaxException; +import java.time.Instant; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import java.util.stream.Stream; +import java.util.stream.StreamSupport; import org.eclipse.jgit.api.ListBranchCommand.ListMode; import org.eclipse.jgit.api.errors.GitAPIException; @@ -40,6 +44,7 @@ import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.StoredConfig; import org.eclipse.jgit.revwalk.RevBlob; import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevObject; import org.eclipse.jgit.submodule.SubmoduleStatus; import org.eclipse.jgit.submodule.SubmoduleStatusType; import org.eclipse.jgit.submodule.SubmoduleWalk; @@ -895,6 +900,234 @@ public class CloneCommandTest extends RepositoryTestCase { assertEquals("refs/heads/test-copy", git2.getRepository().getFullBranch()); } + @Test + public void testCloneRepositoryWithDepth() throws IOException, JGitInternalException, GitAPIException { + File directory = createTempDirectory("testCloneRepositoryWithDepth"); + CloneCommand command = Git.cloneRepository(); + command.setDirectory(directory); + command.setURI(fileUri()); + command.setDepth(1); + command.setBranchesToClone(Set.of("refs/heads/test")); + Git git2 = command.call(); + addRepoToClose(git2.getRepository()); + + List<RevCommit> log = StreamSupport.stream(git2.log().all().call().spliterator(), false) + .collect(Collectors.toList()); + assertEquals(1, log.size()); + RevCommit commit = log.get(0); + assertEquals(Set.of(commit.getId()), + git2.getRepository().getObjectDatabase().getShallowCommits()); + assertEquals("Second commit", commit.getFullMessage()); + assertEquals(0, commit.getParentCount()); + } + + @Test + public void testCloneRepositoryWithDepthAndAllBranches() throws IOException, JGitInternalException, GitAPIException { + File directory = createTempDirectory("testCloneRepositoryWithDepthAndAllBranches"); + CloneCommand command = Git.cloneRepository(); + command.setDirectory(directory); + command.setURI(fileUri()); + command.setDepth(1); + command.setCloneAllBranches(true); + Git git2 = command.call(); + addRepoToClose(git2.getRepository()); + + List<RevCommit> log = StreamSupport.stream(git2.log().all().call().spliterator(), false) + .collect(Collectors.toList()); + assertEquals(2, log.size()); + assertEquals(log.stream().map(RevCommit::getId).collect(Collectors.toSet()), + git2.getRepository().getObjectDatabase().getShallowCommits()); + assertEquals(List.of("Second commit", "Initial commit"), + log.stream().map(RevCommit::getFullMessage).collect(Collectors.toList())); + for (RevCommit commit : log) { + assertEquals(0, commit.getParentCount()); + } + } + + @Test + public void testCloneRepositoryWithDepth2() throws Exception { + RevCommit parent = tr.git().log().call().iterator().next(); + RevCommit commit = tr.commit() + .parent(parent) + .message("Third commit") + .add("test.txt", "Hello world") + .create(); + tr.update("refs/heads/test", commit); + + File directory = createTempDirectory("testCloneRepositoryWithDepth2"); + CloneCommand command = Git.cloneRepository(); + command.setDirectory(directory); + command.setURI(fileUri()); + command.setDepth(2); + command.setBranchesToClone(Set.of("refs/heads/test")); + Git git2 = command.call(); + addRepoToClose(git2.getRepository()); + + List<RevCommit> log = StreamSupport + .stream(git2.log().all().call().spliterator(), false) + .collect(Collectors.toList()); + assertEquals(2, log.size()); + assertEquals(Set.of(parent.getId()), + git2.getRepository().getObjectDatabase().getShallowCommits()); + assertEquals(List.of("Third commit", "Second commit"), log.stream() + .map(RevCommit::getFullMessage).collect(Collectors.toList())); + assertEquals(List.of(Integer.valueOf(1), Integer.valueOf(0)), + log.stream().map(RevCommit::getParentCount) + .collect(Collectors.toList())); + } + + @Test + public void testCloneRepositoryWithDepthAndFetch() throws Exception { + File directory = createTempDirectory("testCloneRepositoryWithDepthAndFetch"); + CloneCommand command = Git.cloneRepository(); + command.setDirectory(directory); + command.setURI(fileUri()); + command.setDepth(1); + command.setBranchesToClone(Set.of("refs/heads/test")); + Git git2 = command.call(); + addRepoToClose(git2.getRepository()); + + RevCommit parent = tr.git().log().call().iterator().next(); + RevCommit commit = tr.commit() + .parent(parent) + .message("Third commit") + .add("test.txt", "Hello world") + .create(); + tr.update("refs/heads/test", commit); + + git2.fetch().call(); + + List<RevCommit> log = StreamSupport + .stream(git2.log().all().call().spliterator(), false) + .collect(Collectors.toList()); + assertEquals(2, log.size()); + assertEquals(Set.of(parent.getId()), + git2.getRepository().getObjectDatabase().getShallowCommits()); + assertEquals(List.of("Third commit", "Second commit"), log.stream() + .map(RevCommit::getFullMessage).collect(Collectors.toList())); + assertEquals(List.of(Integer.valueOf(1), Integer.valueOf(0)), + log.stream().map(RevCommit::getParentCount) + .collect(Collectors.toList())); + } + + @Test + public void testCloneRepositoryWithDepthAndFetchWithDepth() throws Exception { + File directory = createTempDirectory("testCloneRepositoryWithDepthAndFetchWithDepth"); + CloneCommand command = Git.cloneRepository(); + command.setDirectory(directory); + command.setURI(fileUri()); + command.setDepth(1); + command.setBranchesToClone(Set.of("refs/heads/test")); + Git git2 = command.call(); + addRepoToClose(git2.getRepository()); + + RevCommit parent = tr.git().log().call().iterator().next(); + RevCommit commit = tr.commit() + .parent(parent) + .message("Third commit") + .add("test.txt", "Hello world") + .create(); + tr.update("refs/heads/test", commit); + + git2.fetch().setDepth(1).call(); + + List<RevCommit> log = StreamSupport + .stream(git2.log().all().call().spliterator(), false) + .collect(Collectors.toList()); + assertEquals(2, log.size()); + assertEquals( + log.stream().map(RevObject::getId).collect(Collectors.toSet()), + git2.getRepository().getObjectDatabase().getShallowCommits()); + assertEquals(List.of("Third commit", "Second commit"), log.stream() + .map(RevCommit::getFullMessage).collect(Collectors.toList())); + assertEquals(List.of(Integer.valueOf(0), Integer.valueOf(0)), + log.stream().map(RevCommit::getParentCount) + .collect(Collectors.toList())); + } + + @Test + public void testCloneRepositoryWithDepthAndFetchUnshallow() throws Exception { + File directory = createTempDirectory("testCloneRepositoryWithDepthAndFetchUnshallow"); + CloneCommand command = Git.cloneRepository(); + command.setDirectory(directory); + command.setURI(fileUri()); + command.setDepth(1); + command.setBranchesToClone(Set.of("refs/heads/test")); + Git git2 = command.call(); + addRepoToClose(git2.getRepository()); + + git2.fetch().setUnshallow(true).call(); + + List<RevCommit> log = StreamSupport + .stream(git2.log().all().call().spliterator(), false) + .collect(Collectors.toList()); + assertEquals(2, log.size()); + assertEquals(Set.of(), + git2.getRepository().getObjectDatabase().getShallowCommits()); + assertEquals(List.of("Second commit", "Initial commit"), log.stream() + .map(RevCommit::getFullMessage).collect(Collectors.toList())); + assertEquals(List.of(Integer.valueOf(1), Integer.valueOf(0)), + log.stream().map(RevCommit::getParentCount) + .collect(Collectors.toList())); + } + + @Test + public void testCloneRepositoryWithShallowSince() throws Exception { + RevCommit commit = tr.commit() + .parent(tr.git().log().call().iterator().next()) + .message("Third commit").add("test.txt", "Hello world") + .create(); + tr.update("refs/heads/test", commit); + + File directory = createTempDirectory("testCloneRepositoryWithShallowSince"); + CloneCommand command = Git.cloneRepository(); + command.setDirectory(directory); + command.setURI(fileUri()); + command.setShallowSince(Instant.ofEpochSecond(commit.getCommitTime())); + command.setBranchesToClone(Set.of("refs/heads/test")); + Git git2 = command.call(); + addRepoToClose(git2.getRepository()); + + List<RevCommit> log = StreamSupport + .stream(git2.log().all().call().spliterator(), false) + .collect(Collectors.toList()); + assertEquals(1, log.size()); + assertEquals(Set.of(commit.getId()), + git2.getRepository().getObjectDatabase().getShallowCommits()); + assertEquals("Third commit", log.get(0).getFullMessage()); + assertEquals(0, log.get(0).getParentCount()); + } + + @Test + public void testCloneRepositoryWithShallowExclude() throws Exception { + RevCommit parent = tr.git().log().call().iterator().next(); + tr.update("refs/heads/test", + tr.commit() + .parent(parent) + .message("Third commit") + .add("test.txt", "Hello world") + .create()); + + File directory = createTempDirectory("testCloneRepositoryWithShallowExclude"); + CloneCommand command = Git.cloneRepository(); + command.setDirectory(directory); + command.setURI(fileUri()); + command.addShallowExclude(parent.getId()); + command.setBranchesToClone(Set.of("refs/heads/test")); + Git git2 = command.call(); + addRepoToClose(git2.getRepository()); + + List<RevCommit> log = StreamSupport + .stream(git2.log().all().call().spliterator(), false) + .collect(Collectors.toList()); + assertEquals(1, log.size()); + RevCommit commit = log.get(0); + assertEquals(Set.of(commit.getId()), + git2.getRepository().getObjectDatabase().getShallowCommits()); + assertEquals("Third commit", commit.getFullMessage()); + assertEquals(0, commit.getParentCount()); + } + private void assertTagOption(Repository repo, TagOpt expectedTagOption) throws URISyntaxException { RemoteConfig remoteConfig = new RemoteConfig( diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/AbstractRenameDetectionTestCase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/AbstractRenameDetectionTestCase.java new file mode 100644 index 0000000000..a8967f27ec --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/AbstractRenameDetectionTestCase.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2022, Google Inc. and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.eclipse.jgit.diff; + +import static org.junit.Assert.assertEquals; + +import org.eclipse.jgit.diff.DiffEntry.ChangeType; +import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.junit.TestRepository; +import org.eclipse.jgit.lib.AbbreviatedObjectId; +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.Repository; +import org.junit.Before; + +public abstract class AbstractRenameDetectionTestCase + extends RepositoryTestCase { + + protected static final String PATH_A = "src/A"; + + protected static final String PATH_B = "src/B"; + + protected static final String PATH_H = "src/H"; + + protected static final String PATH_Q = "src/Q"; + + protected TestRepository<Repository> testDb; + + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + testDb = new TestRepository<>(db); + } + + protected ObjectId blob(String content) throws Exception { + return testDb.blob(content).copy(); + } + + protected static void assertRename(DiffEntry o, DiffEntry n, int score, + DiffEntry rename) { + assertEquals(ChangeType.RENAME, rename.getChangeType()); + + assertEquals(o.getOldPath(), rename.getOldPath()); + assertEquals(n.getNewPath(), rename.getNewPath()); + + assertEquals(o.getOldMode(), rename.getOldMode()); + assertEquals(n.getNewMode(), rename.getNewMode()); + + assertEquals(o.getOldId(), rename.getOldId()); + assertEquals(n.getNewId(), rename.getNewId()); + + assertEquals(score, rename.getScore()); + } + + protected static void assertCopy(DiffEntry o, DiffEntry n, int score, + DiffEntry copy) { + assertEquals(ChangeType.COPY, copy.getChangeType()); + + assertEquals(o.getOldPath(), copy.getOldPath()); + assertEquals(n.getNewPath(), copy.getNewPath()); + + assertEquals(o.getOldMode(), copy.getOldMode()); + assertEquals(n.getNewMode(), copy.getNewMode()); + + assertEquals(o.getOldId(), copy.getOldId()); + assertEquals(n.getNewId(), copy.getNewId()); + + assertEquals(score, copy.getScore()); + } + + protected static void assertAdd(String newName, ObjectId newId, + FileMode newMode, DiffEntry add) { + assertEquals(DiffEntry.DEV_NULL, add.oldPath); + assertEquals(DiffEntry.A_ZERO, add.oldId); + assertEquals(FileMode.MISSING, add.oldMode); + assertEquals(ChangeType.ADD, add.changeType); + assertEquals(newName, add.newPath); + assertEquals(AbbreviatedObjectId.fromObjectId(newId), add.newId); + assertEquals(newMode, add.newMode); + } + + protected static void assertDelete(String oldName, ObjectId oldId, + FileMode oldMode, DiffEntry delete) { + assertEquals(DiffEntry.DEV_NULL, delete.newPath); + assertEquals(DiffEntry.A_ZERO, delete.newId); + assertEquals(FileMode.MISSING, delete.newMode); + assertEquals(ChangeType.DELETE, delete.changeType); + assertEquals(oldName, delete.oldPath); + assertEquals(AbbreviatedObjectId.fromObjectId(oldId), delete.oldId); + assertEquals(oldMode, delete.oldMode); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/FilteredRenameDetectorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/FilteredRenameDetectorTest.java new file mode 100644 index 0000000000..bfda36db76 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/FilteredRenameDetectorTest.java @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2022, Simeon Andreev and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.eclipse.jgit.diff; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; + +import java.util.Arrays; +import java.util.List; +import org.eclipse.jgit.internal.diff.FilteredRenameDetector; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.treewalk.filter.PathFilter; +import org.junit.Before; +import org.junit.Test; + +public class FilteredRenameDetectorTest extends AbstractRenameDetectionTestCase { + + private FilteredRenameDetector frd; + + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + frd = new FilteredRenameDetector(db); + } + + @Test + public void testExactRename() throws Exception { + ObjectId foo = blob("foo"); + ObjectId bar = blob("bar"); + + DiffEntry a = DiffEntry.add(PATH_A, foo); + DiffEntry b = DiffEntry.delete(PATH_Q, foo); + + DiffEntry c = DiffEntry.add(PATH_H, bar); + DiffEntry d = DiffEntry.delete(PATH_B, bar); + + List<DiffEntry> changes = Arrays.asList(a, b, c, d); + PathFilter filter = PathFilter.create(PATH_A); + List<DiffEntry> entries = frd.compute(changes, filter); + assertEquals("Unexpected entries in: " + entries, 1, entries.size()); + assertRename(b, a, 100, entries.get(0)); + } + + @Test + public void testExactRename_multipleFilters() throws Exception { + ObjectId foo = blob("foo"); + ObjectId bar = blob("bar"); + + DiffEntry a = DiffEntry.add(PATH_A, foo); + DiffEntry b = DiffEntry.delete(PATH_Q, foo); + + DiffEntry c = DiffEntry.add(PATH_H, bar); + DiffEntry d = DiffEntry.delete(PATH_B, bar); + + List<DiffEntry> changes = Arrays.asList(a, b, c, d); + List<PathFilter> filters = Arrays.asList(PathFilter.create(PATH_A), + PathFilter.create(PATH_H)); + List<DiffEntry> entries = frd.compute(changes, filters); + assertEquals("Unexpected entries in: " + entries, 2, entries.size()); + assertRename(b, a, 100, entries.get(0)); + assertRename(d, c, 100, entries.get(1)); + } + + @Test + public void testInexactRename() throws Exception { + ObjectId aId = blob("foo\nbar\nbaz\nblarg\n"); + ObjectId bId = blob("foo\nbar\nbaz\nblah\n"); + DiffEntry a = DiffEntry.add(PATH_A, aId); + DiffEntry b = DiffEntry.delete(PATH_Q, bId); + + ObjectId cId = blob("some\nsort\nof\ntext\n"); + ObjectId dId = blob("completely\nunrelated\ntext\n"); + DiffEntry c = DiffEntry.add(PATH_B, cId); + DiffEntry d = DiffEntry.delete(PATH_H, dId); + + List<DiffEntry> changes = Arrays.asList(a, b, c, d); + PathFilter filter = PathFilter.create(PATH_A); + List<DiffEntry> entries = frd.compute(changes, filter); + assertEquals("Unexpected entries: " + entries, 1, entries.size()); + assertRename(b, a, 66, entries.get(0)); + } + + @Test + public void testInexactRename_multipleFilters() throws Exception { + ObjectId aId = blob("foo\nbar\nbaz\nblarg\n"); + ObjectId bId = blob("foo\nbar\nbaz\nblah\n"); + DiffEntry a = DiffEntry.add(PATH_A, aId); + DiffEntry b = DiffEntry.delete(PATH_Q, bId); + + ObjectId cId = blob("some\nsort\nof\ntext\n"); + ObjectId dId = blob("completely\nunrelated\ntext\n"); + DiffEntry c = DiffEntry.add(PATH_B, cId); + DiffEntry d = DiffEntry.delete(PATH_H, dId); + + List<DiffEntry> changes = Arrays.asList(a, b, c, d); + List<PathFilter> filters = Arrays.asList(PathFilter.create(PATH_A), + PathFilter.create(PATH_H)); + List<DiffEntry> entries = frd.compute(changes, filters); + assertEquals("Unexpected entries: " + entries, 2, entries.size()); + assertRename(b, a, 66, entries.get(0)); + assertSame(d, entries.get(1)); + } + + @Test + public void testNoRenames() throws Exception { + ObjectId aId = blob(""); + ObjectId bId = blob("blah1"); + ObjectId cId = blob(""); + ObjectId dId = blob("blah2"); + + DiffEntry a = DiffEntry.add(PATH_A, aId); + DiffEntry b = DiffEntry.delete(PATH_Q, bId); + + DiffEntry c = DiffEntry.add(PATH_H, cId); + DiffEntry d = DiffEntry.delete(PATH_B, dId); + + List<DiffEntry> changes = Arrays.asList(a, b, c, d); + PathFilter filter = PathFilter.create(PATH_A); + List<DiffEntry> entries = frd.compute(changes, filter); + assertEquals("Unexpected entries in: " + entries, 1, entries.size()); + assertSame(a, entries.get(0)); + } + + @Test + public void testNoRenames_multipleFilters() throws Exception { + ObjectId aId = blob(""); + ObjectId bId = blob("blah1"); + ObjectId cId = blob(""); + ObjectId dId = blob("blah2"); + + DiffEntry a = DiffEntry.add(PATH_A, aId); + DiffEntry b = DiffEntry.delete(PATH_Q, bId); + + DiffEntry c = DiffEntry.add(PATH_H, cId); + DiffEntry d = DiffEntry.delete(PATH_B, dId); + + List<DiffEntry> changes = Arrays.asList(a, b, c, d); + List<PathFilter> filters = Arrays.asList(PathFilter.create(PATH_A), + PathFilter.create(PATH_H)); + List<DiffEntry> entries = frd.compute(changes, filters); + assertEquals("Unexpected entries in: " + entries, 2, entries.size()); + assertSame(a, entries.get(0)); + assertSame(c, entries.get(1)); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/RenameDetectorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/RenameDetectorTest.java index 5edb60ce37..ad560e3b8a 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/RenameDetectorTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/RenameDetectorTest.java @@ -18,31 +18,20 @@ import static org.junit.Assert.fail; import java.util.Arrays; import java.util.List; -import org.eclipse.jgit.diff.DiffEntry.ChangeType; -import org.eclipse.jgit.junit.RepositoryTestCase; -import org.eclipse.jgit.junit.TestRepository; import org.eclipse.jgit.lib.AbbreviatedObjectId; import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.ObjectId; -import org.eclipse.jgit.lib.Repository; import org.junit.Before; import org.junit.Test; -public class RenameDetectorTest extends RepositoryTestCase { - private static final String PATH_A = "src/A"; - private static final String PATH_B = "src/B"; - private static final String PATH_H = "src/H"; - private static final String PATH_Q = "src/Q"; +public class RenameDetectorTest extends AbstractRenameDetectionTestCase { private RenameDetector rd; - private TestRepository<Repository> testDb; - @Override @Before public void setUp() throws Exception { super.setUp(); - testDb = new TestRepository<>(db); rd = new RenameDetector(db); } @@ -675,62 +664,4 @@ public class RenameDetectorTest extends RepositoryTestCase { assertSame(c, entries.get(2)); assertSame(d, entries.get(3)); } - - private ObjectId blob(String content) throws Exception { - return testDb.blob(content).copy(); - } - - private static void assertRename(DiffEntry o, DiffEntry n, int score, - DiffEntry rename) { - assertEquals(ChangeType.RENAME, rename.getChangeType()); - - assertEquals(o.getOldPath(), rename.getOldPath()); - assertEquals(n.getNewPath(), rename.getNewPath()); - - assertEquals(o.getOldMode(), rename.getOldMode()); - assertEquals(n.getNewMode(), rename.getNewMode()); - - assertEquals(o.getOldId(), rename.getOldId()); - assertEquals(n.getNewId(), rename.getNewId()); - - assertEquals(score, rename.getScore()); - } - - private static void assertCopy(DiffEntry o, DiffEntry n, int score, - DiffEntry copy) { - assertEquals(ChangeType.COPY, copy.getChangeType()); - - assertEquals(o.getOldPath(), copy.getOldPath()); - assertEquals(n.getNewPath(), copy.getNewPath()); - - assertEquals(o.getOldMode(), copy.getOldMode()); - assertEquals(n.getNewMode(), copy.getNewMode()); - - assertEquals(o.getOldId(), copy.getOldId()); - assertEquals(n.getNewId(), copy.getNewId()); - - assertEquals(score, copy.getScore()); - } - - private static void assertAdd(String newName, ObjectId newId, - FileMode newMode, DiffEntry add) { - assertEquals(DiffEntry.DEV_NULL, add.oldPath); - assertEquals(DiffEntry.A_ZERO, add.oldId); - assertEquals(FileMode.MISSING, add.oldMode); - assertEquals(ChangeType.ADD, add.changeType); - assertEquals(newName, add.newPath); - assertEquals(AbbreviatedObjectId.fromObjectId(newId), add.newId); - assertEquals(newMode, add.newMode); - } - - private static void assertDelete(String oldName, ObjectId oldId, - FileMode oldMode, DiffEntry delete) { - assertEquals(DiffEntry.DEV_NULL, delete.newPath); - assertEquals(DiffEntry.A_ZERO, delete.newId); - assertEquals(FileMode.MISSING, delete.newMode); - assertEquals(ChangeType.DELETE, delete.changeType); - assertEquals(oldName, delete.oldPath); - assertEquals(AbbreviatedObjectId.fromObjectId(oldId), delete.oldId); - assertEquals(oldMode, delete.oldMode); - } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/RepoCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/RepoCommandTest.java index 3e6d13a67e..ca6f2e1053 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/RepoCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/RepoCommandTest.java @@ -13,6 +13,7 @@ import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; @@ -32,6 +33,7 @@ import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.InvalidRefNameException; import org.eclipse.jgit.api.errors.InvalidRemoteException; +import org.eclipse.jgit.gitrepo.RepoCommand.ManifestErrorException; import org.eclipse.jgit.gitrepo.RepoCommand.RemoteFile; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.junit.JGitTestUtil; @@ -1337,6 +1339,28 @@ public class RepoCommandTest extends RepositoryTestCase { } } + @Test + public void testInvalidPath() throws Exception { + Repository remoteDb = createBareRepository(); + Repository tempDb = createWorkRepository(); + + StringBuilder xmlContent = new StringBuilder(); + xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") + .append("<manifest>") + .append("<remote name=\"remote1\" fetch=\".\" />") + .append("<default revision=\"master\" remote=\"remote1\" />") + .append("<project path=\".\" ").append("name=\"") + .append(defaultUri).append("\" />").append("</manifest>"); + JGitTestUtil.writeTrashFile(tempDb, "manifest.xml", + xmlContent.toString()); + + RepoCommand command = new RepoCommand(remoteDb); + command.setPath( + tempDb.getWorkTree().getAbsolutePath() + "/manifest.xml") + .setURI(rootUri).setRecommendShallow(true); + assertThrows(ManifestErrorException.class, () -> command.call()); + } + private void resolveRelativeUris() { // Find the longest common prefix ends with "/" as rootUri. defaultUri = defaultDb.getDirectory().toURI().toString(); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/CGitIgnoreTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/CGitIgnoreTest.java index ae3f05111f..083e6cd005 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/CGitIgnoreTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/CGitIgnoreTest.java @@ -13,6 +13,7 @@ import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import java.io.BufferedInputStream; import java.io.BufferedReader; @@ -20,6 +21,7 @@ import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; +import java.nio.file.Files; import java.util.LinkedHashSet; import java.util.Set; @@ -354,4 +356,84 @@ public class CGitIgnoreTest extends RepositoryTestCase { writeTrashFile("src/.gitignore", "*\n!*.java\n!*/"); assertSameAsCGit(); } + + @Test + public void testMultipleEntriesIgnored() throws Exception { + createFiles("dir/a"); + writeTrashFile(".gitignore", "!dir/a\ndir/a"); + assertSameAsCGit(); + } + + @Test + public void testMultipleEntriesNotIgnored() throws Exception { + createFiles("dir/a"); + writeTrashFile(".gitignore", "dir/a\n!dir/a"); + assertSameAsCGit("dir/a"); + } + + @Test + public void testInfoExcludes() throws Exception { + createFiles("dir/a", "dir/b"); + File gitDir = db.getDirectory(); + File info = new File(gitDir, "info"); + assertTrue(info.mkdirs()); + File infoExclude = new File(info, "exclude"); + Files.writeString(infoExclude.toPath(), "dir/a"); + assertSameAsCGit("dir/b"); + } + + @Test + public void testInfoExcludesPrecedence() throws Exception { + createFiles("dir/a", "dir/b"); + writeTrashFile(".gitignore", "!dir/a"); + File gitDir = db.getDirectory(); + File info = new File(gitDir, "info"); + assertTrue(info.mkdirs()); + File infoExclude = new File(info, "exclude"); + Files.writeString(infoExclude.toPath(), "dir/a"); + assertSameAsCGit("dir/a", "dir/b"); + } + + @Test + public void testCoreExcludes() throws Exception { + createFiles("dir/a", "dir/b"); + writeTrashFile(".fake_git_ignore", "dir/a"); + assertSameAsCGit("dir/b"); + } + + @Test + public void testInfoCoreExcludes() throws Exception { + createFiles("dir/a", "dir/b"); + File gitDir = db.getDirectory(); + File info = new File(gitDir, "info"); + assertTrue(info.mkdirs()); + File infoExclude = new File(info, "exclude"); + Files.writeString(infoExclude.toPath(), "!a"); + writeTrashFile(".fake_git_ignore", "dir/a"); + assertSameAsCGit("dir/b"); + } + + @Test + public void testInfoCoreExcludesPrecedence() throws Exception { + createFiles("dir/a", "dir/b"); + File gitDir = db.getDirectory(); + File info = new File(gitDir, "info"); + assertTrue(info.mkdirs()); + File infoExclude = new File(info, "exclude"); + Files.writeString(infoExclude.toPath(), "!dir/a"); + writeTrashFile(".fake_git_ignore", "dir/a"); + assertSameAsCGit("dir/a", "dir/b"); + } + + @Test + public void testInfoCoreExcludesPrecedence2() throws Exception { + createFiles("dir/a", "dir/b"); + File gitDir = db.getDirectory(); + File info = new File(gitDir, "info"); + assertTrue(info.mkdirs()); + File infoExclude = new File(info, "exclude"); + Files.writeString(infoExclude.toPath(), "dir/a"); + writeTrashFile(".fake_git_ignore", "!dir/a"); + assertSameAsCGit("dir/b"); + } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergerTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergerTest.java index cbacaed728..dc119c90ff 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergerTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergerTest.java @@ -1002,6 +1002,39 @@ public class MergerTest extends RepositoryTestCase { } } + @Theory + public void fileBecomesDir_noTree(MergeStrategy strategy) + throws Exception { + Git git = Git.wrap(db); + + writeTrashFile("file", "1\n2\n3"); + writeTrashFile("side", "1\n2\n3"); + git.add().addFilepattern("file").addFilepattern("side").call(); + RevCommit first = git.commit().setMessage("base").call(); + + writeTrashFile("side", "our changed"); + RevCommit ours = git.commit().setAll(true) + .setMessage("ours").call(); + + git.checkout().setCreateBranch(true).setStartPoint(first) + .setName("theirs").call(); + deleteTrashFile("file"); + writeTrashFile("file/file", "in subdir"); + git.add().addFilepattern("file/file").call(); + + RevCommit theirs = git.commit().setAll(true) + .setMessage("theirs").call(); + + // Exercise inCore flavor of the merge. + try (ObjectInserter ins = db.newObjectInserter()) { + ResolveMerger merger = + (ResolveMerger) strategy.newMerger(ins, db.getConfig()); + boolean success = merger.merge(ours, theirs); + assertTrue(success); + assertTrue(merger.getModifiedFiles().isEmpty()); + } + } + /** * Merging after criss-cross merges. In this case we merge together two * commits which have two equally good common ancestors diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SymlinkMergeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SymlinkMergeTest.java new file mode 100644 index 0000000000..3cdc8da34e --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SymlinkMergeTest.java @@ -0,0 +1,296 @@ +/* + * Copyright (C) 2022 Thomas Wolf <twolf@apache.org> and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.merge; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeTrue; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.LinkOption; + +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.MergeResult; +import org.eclipse.jgit.api.MergeResult.MergeStatus; +import org.eclipse.jgit.api.ResetCommand.ResetType; +import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.junit.TestRepository; +import org.eclipse.jgit.lib.ConfigConstants; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.lib.StoredConfig; +import org.eclipse.jgit.revwalk.RevCommit; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +/** + * Tests for merges involving symlinks. + */ +@RunWith(Parameterized.class) +public class SymlinkMergeTest extends RepositoryTestCase { + + @Parameters(name = "target={0}, core.symlinks={1}") + public static Object[][] parameters() { + return new Object[][] { + { Target.NONE, Boolean.TRUE }, + { Target.FILE, Boolean.TRUE }, + { Target.DIRECTORY, Boolean.TRUE }, + { Target.NONE, Boolean.FALSE }, + { Target.FILE, Boolean.FALSE }, + { Target.DIRECTORY, Boolean.FALSE }, + }; + } + + public enum Target { + NONE, FILE, DIRECTORY + } + + @Parameter(0) + public Target target; + + @Parameter(1) + public boolean useSymLinks; + + private void setTargets() throws IOException { + switch (target) { + case DIRECTORY: + assertTrue(new File(trash, "target").mkdir()); + assertTrue(new File(trash, "target1").mkdir()); + assertTrue(new File(trash, "target2").mkdir()); + break; + case FILE: + writeTrashFile("target", "t"); + writeTrashFile("target1", "t1"); + writeTrashFile("target2", "t2"); + break; + default: + break; + } + } + + private void checkTargets() throws IOException { + File t = new File(trash, "target"); + File t1 = new File(trash, "target1"); + File t2 = new File(trash, "target2"); + switch (target) { + case DIRECTORY: + assertTrue(t.isDirectory()); + assertTrue(t1.isDirectory()); + assertTrue(t2.isDirectory()); + break; + case FILE: + checkFile(t, "t"); + checkFile(t1, "t1"); + checkFile(t2, "t2"); + break; + default: + assertFalse(Files.exists(t.toPath(), LinkOption.NOFOLLOW_LINKS)); + assertFalse(Files.exists(t1.toPath(), LinkOption.NOFOLLOW_LINKS)); + assertFalse(Files.exists(t2.toPath(), LinkOption.NOFOLLOW_LINKS)); + break; + } + } + + private void assertSymLink(File link, String content) throws Exception { + if (useSymLinks) { + assertTrue(Files.isSymbolicLink(link.toPath())); + assertEquals(content, db.getFS().readSymLink(link)); + } else { + assertFalse(Files.isSymbolicLink(link.toPath())); + assertTrue(link.isFile()); + checkFile(link, content); + } + } + + // Link/link conflict: C git records the conflict but leaves the link in the + // working tree unchanged. + + @Test + public void mergeWithSymlinkConflict() throws Exception { + assumeTrue(db.getFS().supportsSymlinks() || !useSymLinks); + StoredConfig config = db.getConfig(); + config.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_SYMLINKS, useSymLinks); + config.save(); + try (TestRepository<Repository> repo = new TestRepository<>(db)) { + db.incrementOpen(); + // Create the links directly in the git repo, then use a hard reset + // to get them into the workspace. This enables us to run these + // tests also with core.symLinks = false. + RevCommit base = repo + .commit(repo.tree(repo.link("link", repo.blob("target")))); + RevCommit side = repo.commit( + repo.tree(repo.link("link", repo.blob("target1"))), base); + RevCommit head = repo.commit( + repo.tree(repo.link("link", repo.blob("target2"))), base); + try (Git git = new Git(db)) { + setTargets(); + git.reset().setMode(ResetType.HARD).setRef(head.name()).call(); + File link = new File(trash, "link"); + assertSymLink(link, "target2"); + MergeResult result = git.merge().include(side) + .setMessage("merged").call(); + assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus()); + // Link should be unmodified + assertSymLink(link, "target2"); + checkTargets(); + assertEquals("[link, mode:120000, stage:1, content:target]" + + "[link, mode:120000, stage:2, content:target2]" + + "[link, mode:120000, stage:3, content:target1]", + indexState(CONTENT)); + } + } + } + + // In file/link conflicts, C git never does a content merge. It records the + // stages in the index, and always puts the file into the workspace. + + @Test + public void mergeWithFileSymlinkConflict() throws Exception { + assumeTrue(db.getFS().supportsSymlinks() || !useSymLinks); + StoredConfig config = db.getConfig(); + config.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_SYMLINKS, useSymLinks); + config.save(); + try (TestRepository<Repository> repo = new TestRepository<>(db)) { + db.incrementOpen(); + RevCommit base = repo.commit(repo.tree()); + RevCommit side = repo.commit( + repo.tree(repo.link("link", repo.blob("target1"))), base); + RevCommit head = repo.commit( + repo.tree(repo.file("link", repo.blob("not a link"))), + base); + try (Git git = new Git(db)) { + setTargets(); + git.reset().setMode(ResetType.HARD).setRef(head.name()).call(); + File link = new File(trash, "link"); + assertFalse(Files.isSymbolicLink(link.toPath())); + checkFile(link, "not a link"); + MergeResult result = git.merge().include(side) + .setMessage("merged").call(); + assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus()); + // File should be unmodified + assertFalse(Files.isSymbolicLink(link.toPath())); + checkFile(link, "not a link"); + checkTargets(); + assertEquals("[link, mode:100644, stage:2, content:not a link]" + + "[link, mode:120000, stage:3, content:target1]", + indexState(CONTENT)); + } + } + } + + @Test + public void mergeWithSymlinkFileConflict() throws Exception { + assumeTrue(db.getFS().supportsSymlinks() || !useSymLinks); + StoredConfig config = db.getConfig(); + config.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_SYMLINKS, useSymLinks); + config.save(); + try (TestRepository<Repository> repo = new TestRepository<>(db)) { + db.incrementOpen(); + RevCommit base = repo.commit(repo.tree()); + RevCommit side = repo.commit( + repo.tree(repo.file("link", repo.blob("not a link"))), + base); + RevCommit head = repo.commit( + repo.tree(repo.link("link", repo.blob("target2"))), base); + try (Git git = new Git(db)) { + setTargets(); + git.reset().setMode(ResetType.HARD).setRef(head.name()).call(); + File link = new File(trash, "link"); + assertSymLink(link, "target2"); + MergeResult result = git.merge().include(side) + .setMessage("merged").call(); + assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus()); + // Should now be a file! + assertFalse(Files.isSymbolicLink(link.toPath())); + checkFile(link, "not a link"); + checkTargets(); + assertEquals("[link, mode:120000, stage:2, content:target2]" + + "[link, mode:100644, stage:3, content:not a link]", + indexState(CONTENT)); + } + } + } + + // In Delete/modify conflicts with the non-deleted side a link, C git puts + // the link into the working tree. + + @Test + public void mergeWithSymlinkDeleteModify() throws Exception { + assumeTrue(db.getFS().supportsSymlinks() || !useSymLinks); + StoredConfig config = db.getConfig(); + config.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_SYMLINKS, useSymLinks); + config.save(); + try (TestRepository<Repository> repo = new TestRepository<>(db)) { + db.incrementOpen(); + RevCommit base = repo + .commit(repo.tree(repo.link("link", repo.blob("target")))); + RevCommit side = repo.commit( + repo.tree(repo.link("link", repo.blob("target1"))), base); + RevCommit head = repo.commit(repo.tree(), base); + try (Git git = new Git(db)) { + setTargets(); + git.reset().setMode(ResetType.HARD).setRef(head.name()).call(); + File link = new File(trash, "link"); + assertFalse( + Files.exists(link.toPath(), LinkOption.NOFOLLOW_LINKS)); + MergeResult result = git.merge().include(side) + .setMessage("merged").call(); + assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus()); + // Link should have the content from side + assertSymLink(link, "target1"); + checkTargets(); + assertEquals("[link, mode:120000, stage:1, content:target]" + + "[link, mode:120000, stage:3, content:target1]", + indexState(CONTENT)); + } + } + } + + @Test + public void mergeWithSymlinkModifyDelete() throws Exception { + assumeTrue(db.getFS().supportsSymlinks() || !useSymLinks); + StoredConfig config = db.getConfig(); + config.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_SYMLINKS, useSymLinks); + config.save(); + try (TestRepository<Repository> repo = new TestRepository<>(db)) { + db.incrementOpen(); + RevCommit base = repo + .commit(repo.tree(repo.link("link", repo.blob("target")))); + RevCommit side = repo.commit(repo.tree(), base); + RevCommit head = repo.commit( + repo.tree(repo.link("link", repo.blob("target2"))), base); + try (Git git = new Git(db)) { + setTargets(); + git.reset().setMode(ResetType.HARD).setRef(head.name()).call(); + File link = new File(trash, "link"); + assertSymLink(link, "target2"); + MergeResult result = git.merge().include(side) + .setMessage("merged").call(); + assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus()); + // Link should be unmodified + assertSymLink(link, "target2"); + checkTargets(); + assertEquals("[link, mode:120000, stage:1, content:target]" + + "[link, mode:120000, stage:2, content:target2]", + indexState(CONTENT)); + } + } + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevCommitParseTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevCommitParseTest.java index 0e4c05d792..82af34ded2 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevCommitParseTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevCommitParseTest.java @@ -78,7 +78,7 @@ public class RevCommitParseTest extends RepositoryTestCase { c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); assertNull(c.getTree()); - assertNull(c.parents); + assertNull(c.getParents()); try (RevWalk rw = new RevWalk(db)) { c.parseCanonical(rw, body.toString().getBytes(UTF_8)); @@ -86,23 +86,26 @@ public class RevCommitParseTest extends RepositoryTestCase { assertEquals(treeId, c.getTree().getId()); assertSame(rw.lookupTree(treeId), c.getTree()); } - assertNotNull(c.parents); - assertEquals(0, c.parents.length); + assertNotNull(c.getParents()); + assertEquals(0, c.getParentCount()); assertEquals("", c.getFullMessage()); final PersonIdent cAuthor = c.getAuthorIdent(); assertNotNull(cAuthor); assertEquals(authorName, cAuthor.getName()); assertEquals(authorEmail, cAuthor.getEmailAddress()); - assertEquals((long)authorTime * 1000, cAuthor.getWhen().getTime()); - assertEquals(TimeZone.getTimeZone("GMT" + authorTimeZone), cAuthor.getTimeZone()); + assertEquals((long) authorTime * 1000, cAuthor.getWhen().getTime()); + assertEquals(TimeZone.getTimeZone("GMT" + authorTimeZone), + cAuthor.getTimeZone()); final PersonIdent cCommitter = c.getCommitterIdent(); assertNotNull(cCommitter); assertEquals(committerName, cCommitter.getName()); assertEquals(committerEmail, cCommitter.getEmailAddress()); - assertEquals((long)committerTime * 1000, cCommitter.getWhen().getTime()); - assertEquals(TimeZone.getTimeZone("GMT" + committerTimeZone), cCommitter.getTimeZone()); + assertEquals((long) committerTime * 1000, + cCommitter.getWhen().getTime()); + assertEquals(TimeZone.getTimeZone("GMT" + committerTimeZone), + cCommitter.getTimeZone()); } private RevCommit create(String msg) throws Exception { @@ -149,16 +152,22 @@ public class RevCommitParseTest extends RepositoryTestCase { try (RevWalk rw = new RevWalk(db)) { c.parseCanonical(rw, b.toString().getBytes(UTF_8)); } - assertEquals(new PersonIdent("", "a_u_thor@example.com", 1218123387000l, 7), c.getAuthorIdent()); - assertEquals(new PersonIdent("", "", 1218123390000l, -5), c.getCommitterIdent()); + assertEquals( + new PersonIdent("", "a_u_thor@example.com", 1218123387000l, 7), + c.getAuthorIdent()); + assertEquals(new PersonIdent("", "", 1218123390000l, -5), + c.getCommitterIdent()); } @Test public void testParse_implicit_UTF8_encoded() throws Exception { final ByteArrayOutputStream b = new ByteArrayOutputStream(); - b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes(UTF_8)); - b.write("author F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n".getBytes(UTF_8)); - b.write("committer C O. Miter <c@example.com> 1218123390 -0500\n".getBytes(UTF_8)); + b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n" + .getBytes(UTF_8)); + b.write("author F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n" + .getBytes(UTF_8)); + b.write("committer C O. Miter <c@example.com> 1218123390 -0500\n" + .getBytes(UTF_8)); b.write("\n".getBytes(UTF_8)); b.write("Sm\u00f6rg\u00e5sbord\n".getBytes(UTF_8)); b.write("\n".getBytes(UTF_8)); @@ -171,15 +180,19 @@ public class RevCommitParseTest extends RepositoryTestCase { assertSame(UTF_8, c.getEncoding()); assertEquals("F\u00f6r fattare", c.getAuthorIdent().getName()); assertEquals("Sm\u00f6rg\u00e5sbord", c.getShortMessage()); - assertEquals("Sm\u00f6rg\u00e5sbord\n\n\u304d\u308c\u3044\n", c.getFullMessage()); + assertEquals("Sm\u00f6rg\u00e5sbord\n\n\u304d\u308c\u3044\n", + c.getFullMessage()); } @Test public void testParse_implicit_mixed_encoded() throws Exception { final ByteArrayOutputStream b = new ByteArrayOutputStream(); - b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes(UTF_8)); - b.write("author F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n".getBytes(ISO_8859_1)); - b.write("committer C O. Miter <c@example.com> 1218123390 -0500\n".getBytes(UTF_8)); + b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n" + .getBytes(UTF_8)); + b.write("author F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n" + .getBytes(ISO_8859_1)); + b.write("committer C O. Miter <c@example.com> 1218123390 -0500\n" + .getBytes(UTF_8)); b.write("\n".getBytes(UTF_8)); b.write("Sm\u00f6rg\u00e5sbord\n".getBytes(UTF_8)); b.write("\n".getBytes(UTF_8)); @@ -192,7 +205,8 @@ public class RevCommitParseTest extends RepositoryTestCase { assertSame(UTF_8, c.getEncoding()); assertEquals("F\u00f6r fattare", c.getAuthorIdent().getName()); assertEquals("Sm\u00f6rg\u00e5sbord", c.getShortMessage()); - assertEquals("Sm\u00f6rg\u00e5sbord\n\n\u304d\u308c\u3044\n", c.getFullMessage()); + assertEquals("Sm\u00f6rg\u00e5sbord\n\n\u304d\u308c\u3044\n", + c.getFullMessage()); } /** @@ -203,9 +217,12 @@ public class RevCommitParseTest extends RepositoryTestCase { @Test public void testParse_explicit_encoded() throws Exception { final ByteArrayOutputStream b = new ByteArrayOutputStream(); - b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes("EUC-JP")); - b.write("author F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n".getBytes("EUC-JP")); - b.write("committer C O. Miter <c@example.com> 1218123390 -0500\n".getBytes("EUC-JP")); + b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n" + .getBytes("EUC-JP")); + b.write("author F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n" + .getBytes("EUC-JP")); + b.write("committer C O. Miter <c@example.com> 1218123390 -0500\n" + .getBytes("EUC-JP")); b.write("encoding euc_JP\n".getBytes("EUC-JP")); b.write("\n".getBytes("EUC-JP")); b.write("\u304d\u308c\u3044\n".getBytes("EUC-JP")); @@ -235,9 +252,12 @@ public class RevCommitParseTest extends RepositoryTestCase { @Test public void testParse_explicit_bad_encoded() throws Exception { final ByteArrayOutputStream b = new ByteArrayOutputStream(); - b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes(UTF_8)); - b.write("author F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n".getBytes(ISO_8859_1)); - b.write("committer C O. Miter <c@example.com> 1218123390 -0500\n".getBytes(UTF_8)); + b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n" + .getBytes(UTF_8)); + b.write("author F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n" + .getBytes(ISO_8859_1)); + b.write("committer C O. Miter <c@example.com> 1218123390 -0500\n" + .getBytes(UTF_8)); b.write("encoding EUC-JP\n".getBytes(UTF_8)); b.write("\n".getBytes(UTF_8)); b.write("\u304d\u308c\u3044\n".getBytes(UTF_8)); @@ -256,21 +276,25 @@ public class RevCommitParseTest extends RepositoryTestCase { } /** - * This is a twisted case too, but show what we expect here. We can revise the - * expectations provided this case is updated. + * This is a twisted case too, but show what we expect here. We can revise + * the expectations provided this case is updated. * * What happens here is that an encoding us given, but data is not encoded - * that way (and we can detect it), so we try other encodings. Here data could - * actually be decoded in the stated encoding, but we override using UTF-8. + * that way (and we can detect it), so we try other encodings. Here data + * could actually be decoded in the stated encoding, but we override using + * UTF-8. * * @throws Exception */ @Test public void testParse_explicit_bad_encoded2() throws Exception { final ByteArrayOutputStream b = new ByteArrayOutputStream(); - b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes(UTF_8)); - b.write("author F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n".getBytes(UTF_8)); - b.write("committer C O. Miter <c@example.com> 1218123390 -0500\n".getBytes(UTF_8)); + b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n" + .getBytes(UTF_8)); + b.write("author F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n" + .getBytes(UTF_8)); + b.write("committer C O. Miter <c@example.com> 1218123390 -0500\n" + .getBytes(UTF_8)); b.write("encoding ISO-8859-1\n".getBytes(UTF_8)); b.write("\n".getBytes(UTF_8)); b.write("\u304d\u308c\u3044\n".getBytes(UTF_8)); @@ -319,9 +343,11 @@ public class RevCommitParseTest extends RepositoryTestCase { @Test public void testParse_illegalEncoding() throws Exception { ByteArrayOutputStream b = new ByteArrayOutputStream(); - b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes(UTF_8)); + b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n" + .getBytes(UTF_8)); b.write("author au <a@example.com> 1218123387 +0700\n".getBytes(UTF_8)); - b.write("committer co <c@example.com> 1218123390 -0500\n".getBytes(UTF_8)); + b.write("committer co <c@example.com> 1218123390 -0500\n" + .getBytes(UTF_8)); b.write("encoding utf-8logoutputencoding=gbk\n".getBytes(UTF_8)); b.write("\n".getBytes(UTF_8)); b.write("message\n".getBytes(UTF_8)); @@ -348,9 +374,11 @@ public class RevCommitParseTest extends RepositoryTestCase { @Test public void testParse_unsupportedEncoding() throws Exception { ByteArrayOutputStream b = new ByteArrayOutputStream(); - b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes(UTF_8)); + b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n" + .getBytes(UTF_8)); b.write("author au <a@example.com> 1218123387 +0700\n".getBytes(UTF_8)); - b.write("committer co <c@example.com> 1218123390 -0500\n".getBytes(UTF_8)); + b.write("committer co <c@example.com> 1218123390 -0500\n" + .getBytes(UTF_8)); b.write("encoding it_IT.UTF8\n".getBytes(UTF_8)); b.write("\n".getBytes(UTF_8)); b.write("message\n".getBytes(UTF_8)); @@ -474,21 +502,18 @@ public class RevCommitParseTest extends RepositoryTestCase { @Test public void testParse_gpgSig() throws Exception { - String commit = "tree e3a1035abd2b319bb01e57d69b0ba6cab289297e\n" + - "parent 54e895b87c0768d2317a2b17062e3ad9f76a8105\n" + - "committer A U Thor <author@xample.com 1528968566 +0200\n" + - "gpgsig -----BEGIN PGP SIGNATURE-----\n" + - " \n" + - " wsBcBAABCAAQBQJbGB4pCRBK7hj4Ov3rIwAAdHIIAENrvz23867ZgqrmyPemBEZP\n" + - " U24B1Tlq/DWvce2buaxmbNQngKZ0pv2s8VMc11916WfTIC9EKvioatmpjduWvhqj\n" + - " znQTFyiMor30pyYsfrqFuQZvqBW01o8GEWqLg8zjf9Rf0R3LlOEw86aT8CdHRlm6\n" + - " wlb22xb8qoX4RB+LYfz7MhK5F+yLOPXZdJnAVbuyoMGRnDpwdzjL5Hj671+XJxN5\n" + - " SasRdhxkkfw/ZnHxaKEc4juMz8Nziz27elRwhOQqlTYoXNJnsV//wy5Losd7aKi1\n" + - " xXXyUpndEOmT0CIcKHrN/kbYoVL28OJaxoBuva3WYQaRrzEe3X02NMxZe9gkSqA=\n" + - " =TClh\n" + - " -----END PGP SIGNATURE-----\n" + - "some other header\n\n" + - "commit message"; + String commit = "tree e3a1035abd2b319bb01e57d69b0ba6cab289297e\n" + + "parent 54e895b87c0768d2317a2b17062e3ad9f76a8105\n" + + "committer A U Thor <author@xample.com 1528968566 +0200\n" + + "gpgsig -----BEGIN PGP SIGNATURE-----\n" + " \n" + + " wsBcBAABCAAQBQJbGB4pCRBK7hj4Ov3rIwAAdHIIAENrvz23867ZgqrmyPemBEZP\n" + + " U24B1Tlq/DWvce2buaxmbNQngKZ0pv2s8VMc11916WfTIC9EKvioatmpjduWvhqj\n" + + " znQTFyiMor30pyYsfrqFuQZvqBW01o8GEWqLg8zjf9Rf0R3LlOEw86aT8CdHRlm6\n" + + " wlb22xb8qoX4RB+LYfz7MhK5F+yLOPXZdJnAVbuyoMGRnDpwdzjL5Hj671+XJxN5\n" + + " SasRdhxkkfw/ZnHxaKEc4juMz8Nziz27elRwhOQqlTYoXNJnsV//wy5Losd7aKi1\n" + + " xXXyUpndEOmT0CIcKHrN/kbYoVL28OJaxoBuva3WYQaRrzEe3X02NMxZe9gkSqA=\n" + + " =TClh\n" + " -----END PGP SIGNATURE-----\n" + + "some other header\n\n" + "commit message"; final RevCommit c; c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevCommitWithOverriddenParentTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevCommitWithOverriddenParentTest.java new file mode 100644 index 0000000000..b06f9fc0b1 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevCommitWithOverriddenParentTest.java @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2022, Google Inc. and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.eclipse.jgit.revwalk; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; + +import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription; +import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository; +import org.eclipse.jgit.junit.TestRepository; +import org.eclipse.jgit.lib.AnyObjectId; +import org.eclipse.jgit.lib.ObjectLoader; +import org.eclipse.jgit.revwalk.filter.RevFilter; +import org.junit.Before; +import org.junit.Test; + +public class RevCommitWithOverriddenParentTest { + private TestRepository<InMemoryRepository> tr; + + private RevWalk rw; + + @Before + public void setUp() throws Exception { + tr = new TestRepository<>( + new InMemoryRepository(new DfsRepositoryDescription("test"))); + rw = tr.getRevWalk(); + } + + @Test + public void testParseBody() throws Exception { + RevCommit a = tr.commit().add("a", "foo").create(); + RevCommit b = tr.commit().parent(a).add("b", "bar").create(); + RevCommit c = tr.commit().parent(b).message("commit3").add("a", "foo'") + .create(); + + RevCommit cBar = new RevCommit(c.getId()) { + @Override + public int getParentCount() { + return 1; + } + + @Override + public RevCommit getParent(int nth) { + return a; + } + + @Override + public RevCommit[] getParents() { + return new RevCommit[] { a }; + } + }; + + rw.parseBody(cBar); + assertEquals(a, cBar.getParents()[0]); + assertEquals("commit3", cBar.getFullMessage()); + assertEquals("foo'", blobAsString(cBar, "a")); + } + + @Test + public void testParseHeader() throws Exception { + RevCommit a = tr.commit().add("a", "foo").create(); + RevCommit b = tr.commit().parent(a).add("b", "bar").create(); + RevCommit c = tr.commit().parent(b).message("commit3").add("a", "foo'") + .create(); + + RevCommit cBar = new RevCommit(c.getId()) { + @Override + public int getParentCount() { + return 1; + } + + @Override + public RevCommit getParent(int nth) { + return a; + } + + @Override + public RevCommit[] getParents() { + return new RevCommit[] { a }; + } + }; + + RevCommit parsed = rw.parseCommit(cBar.getId()); + rw.parseHeaders(cBar); + + assertEquals(c.getId(), parsed.getId()); + assertEquals(parsed.getTree(), cBar.getTree()); + assertEquals(parsed.getCommitTime(), cBar.getCommitTime()); + assertEquals(parsed.getAuthorIdent(), cBar.getAuthorIdent()); + } + + @Test + public void testFilter() throws Exception { + RevCommit a = tr.commit().add("a", "foo").create(); + RevCommit b = tr.commit().parent(a).add("b", "bar").create(); + RevCommit c = tr.commit().parent(b).message("commit3").add("a", "foo'") + .create(); + + RevCommit cBar = new RevCommit(c.getId()) { + @Override + public int getParentCount() { + return 1; + } + + @Override + public RevCommit getParent(int nth) { + return a; + } + + @Override + public RevCommit[] getParents() { + return new RevCommit[] { a }; + } + }; + + rw.setRevFilter(RevFilter.ALL); + rw.markStart(cBar); + assertSame(cBar, rw.next()); + assertSame(a, rw.next()); + assertNull(rw.next()); + } + + @Test + public void testFlag() throws Exception { + RevCommit root = tr.commit().add("todelete", "to be deleted").create(); + RevCommit orig = tr.commit().parent(root).rm("todelete") + .add("foo", "foo contents").add("bar", "bar contents") + .add("dir/baz", "baz contents").create(); + + RevCommit commitOrigBar = new RevCommit(orig.getId()) { + @Override + public int getParentCount() { + return 1; + } + + @Override + public RevCommit getParent(int nth) { + return root; + } + + @Override + public RevCommit[] getParents() { + return new RevCommit[] { root }; + } + }; + + assertEquals(RevObject.PARSED, orig.flags); + assertEquals(0, commitOrigBar.flags); + commitOrigBar.parseBody(rw); + assertEquals(RevObject.PARSED, commitOrigBar.flags); + } + + private String blobAsString(AnyObjectId treeish, String path) + throws Exception { + RevObject obj = tr.get(rw.parseTree(treeish), path); + assertSame(RevBlob.class, obj.getClass()); + ObjectLoader loader = rw.getObjectReader().open(obj); + return new String(loader.getCachedBytes(), UTF_8); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkCullTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkCullTest.java index 722b2d2927..7b0e2b2267 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkCullTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkCullTest.java @@ -75,6 +75,6 @@ public class RevWalkCullTest extends RevWalkTestCase { // We should have aborted before we got back so far that "a" // would be parsed. Thus, its parents shouldn't be allocated. // - assertNull(a2.parents); + assertNull(a2.getParents()); } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV0ParserTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV0ParserTest.java index c0db83a820..b2a4af30ab 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV0ParserTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV0ParserTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018, Google LLC. and others + * Copyright (C) 2018, 2022 Google LLC. and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at @@ -15,6 +15,7 @@ import static org.eclipse.jgit.lib.Constants.OBJ_TAG; import static org.eclipse.jgit.lib.Constants.OBJ_TREE; import static org.eclipse.jgit.transport.ObjectIdMatcher.hasOnlyObjectIds; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -133,6 +134,42 @@ public class ProtocolV0ParserTest { } @Test + public void testRecvWantsDeepenSince() + throws PackProtocolException, IOException { + PacketLineIn pckIn = formatAsPacketLine( + "want 4624442d68ee402a94364191085b77137618633e\n", + "want f900c8326a43303685c46b279b9f70411bff1a4b\n", + "deepen-since 1652773020\n", + PacketLineIn.end()); + ProtocolV0Parser parser = new ProtocolV0Parser(defaultConfig()); + FetchV0Request request = parser.recvWants(pckIn); + assertTrue(request.getClientCapabilities().isEmpty()); + assertEquals(1652773020, request.getDeepenSince()); + assertThat(request.getWantIds(), + hasOnlyObjectIds("4624442d68ee402a94364191085b77137618633e", + "f900c8326a43303685c46b279b9f70411bff1a4b")); + } + + @Test + public void testRecvWantsDeepenNots() + throws PackProtocolException, IOException { + PacketLineIn pckIn = formatAsPacketLine( + "want 4624442d68ee402a94364191085b77137618633e\n", + "want f900c8326a43303685c46b279b9f70411bff1a4b\n", + "deepen-not 856d5138d7269a483efe276d4a6b5c25b4fbb1a4\n", + "deepen-not heads/refs/test\n", + PacketLineIn.end()); + ProtocolV0Parser parser = new ProtocolV0Parser(defaultConfig()); + FetchV0Request request = parser.recvWants(pckIn); + assertTrue(request.getClientCapabilities().isEmpty()); + assertThat(request.getDeepenNots(), contains("856d5138d7269a483efe276d4a6b5c25b4fbb1a4", + "heads/refs/test")); + assertThat(request.getWantIds(), + hasOnlyObjectIds("4624442d68ee402a94364191085b77137618633e", + "f900c8326a43303685c46b279b9f70411bff1a4b")); + } + + @Test public void testRecvWantsShallow() throws PackProtocolException, IOException { PacketLineIn pckIn = formatAsPacketLine( diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV2ParserTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV2ParserTest.java index 837bdce919..167b5b72c6 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV2ParserTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV2ParserTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018, Google LLC. and others + * Copyright (C) 2018, 2022 Google LLC. and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at @@ -152,7 +152,7 @@ public class ProtocolV2ParserTest { assertThat(request.getClientShallowCommits(), hasOnlyObjectIds("28274d02c489f4c7e68153056e9061a46f62d7a0", "145e683b229dcab9d0e2ccb01b386f9ecc17d29d")); - assertTrue(request.getDeepenNotRefs().isEmpty()); + assertTrue(request.getDeepenNots().isEmpty()); assertEquals(15, request.getDepth()); assertTrue(request.getClientCapabilities() .contains(GitProtocolConstants.OPTION_DEEPEN_RELATIVE)); @@ -171,7 +171,7 @@ public class ProtocolV2ParserTest { assertThat(request.getClientShallowCommits(), hasOnlyObjectIds("28274d02c489f4c7e68153056e9061a46f62d7a0", "145e683b229dcab9d0e2ccb01b386f9ecc17d29d")); - assertThat(request.getDeepenNotRefs(), + assertThat(request.getDeepenNots(), hasItems("a08595f76159b09d57553e37a5123f1091bb13e7")); } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java index 0d49cd3396..e463e9070a 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java @@ -303,12 +303,16 @@ public class FileTreeIteratorTest extends RepositoryTestCase { DirCacheEntry dce = db.readDirCache().getEntry("symlink"); dce.setFileMode(FileMode.SYMLINK); try (ObjectReader objectReader = db.newObjectReader()) { - DirCacheCheckout.checkoutEntry(db, dce, objectReader, false, null); + WorkingTreeOptions options = db.getConfig() + .get(WorkingTreeOptions.KEY); + DirCacheCheckout.checkoutEntry(db, dce, objectReader, false, null, + options); FileTreeIterator fti = new FileTreeIterator(trash, db.getFS(), - db.getConfig().get(WorkingTreeOptions.KEY)); - while (!fti.getEntryPathString().equals("symlink")) + options); + while (!fti.getEntryPathString().equals("symlink")) { fti.next(1); + } assertFalse(fti.isModified(dce, false, objectReader)); } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/NameConflictTreeWalkTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/NameConflictTreeWalkTest.java index 36a96b0e2d..f03163d491 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/NameConflictTreeWalkTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/NameConflictTreeWalkTest.java @@ -138,6 +138,54 @@ public class NameConflictTreeWalkTest extends RepositoryTestCase { } @Test + public void testDF_specialFileNames() throws Exception { + final DirCache tree0 = db.readDirCache(); + final DirCache tree1 = db.readDirCache(); + final DirCache tree2 = db.readDirCache(); + { + final DirCacheBuilder b0 = tree0.builder(); + final DirCacheBuilder b1 = tree1.builder(); + final DirCacheBuilder b2 = tree2.builder(); + + b0.add(createEntry("gradle.properties", REGULAR_FILE)); + b0.add(createEntry("gradle/nested_file.txt", REGULAR_FILE)); + + b1.add(createEntry("gradle.properties", REGULAR_FILE)); + + b2.add(createEntry("gradle", REGULAR_FILE)); + b2.add(createEntry("gradle.properties", REGULAR_FILE)); + + b0.finish(); + b1.finish(); + b2.finish(); + assertEquals(2, tree0.getEntryCount()); + assertEquals(1, tree1.getEntryCount()); + assertEquals(2, tree2.getEntryCount()); + } + + try (NameConflictTreeWalk tw = new NameConflictTreeWalk(db)) { + tw.addTree(new DirCacheIterator(tree0)); + tw.addTree(new DirCacheIterator(tree1)); + tw.addTree(new DirCacheIterator(tree2)); + + assertModes("gradle", TREE, MISSING, REGULAR_FILE, tw); + assertTrue(tw.isSubtree()); + assertTrue(tw.isDirectoryFileConflict()); + tw.enterSubtree(); + assertModes("gradle/nested_file.txt", REGULAR_FILE, MISSING, + MISSING, tw); + assertFalse(tw.isSubtree()); + // isDirectoryFileConflict is true, because the conflict is detected + // on parent. + assertTrue(tw.isDirectoryFileConflict()); + assertModes("gradle.properties", REGULAR_FILE, REGULAR_FILE, + REGULAR_FILE, tw); + assertFalse(tw.isSubtree()); + assertFalse(tw.isDirectoryFileConflict()); + } + } + + @Test public void testDF_SkipsSeenSubtree() throws Exception { final DirCache tree0 = db.readDirCache(); final DirCache tree1 = db.readDirCache(); @@ -218,11 +266,29 @@ public class NameConflictTreeWalkTest extends RepositoryTestCase { } } - private static void assertModes(final String path, final FileMode mode0, - final FileMode mode1, final TreeWalk tw) throws Exception { + private static void assertModes(String path, FileMode mode0, FileMode mode1, + TreeWalk tw) throws Exception { assertTrue("has " + path, tw.next()); assertEquals(path, tw.getPathString()); assertEquals(mode0, tw.getFileMode(0)); assertEquals(mode1, tw.getFileMode(1)); } + + private static void assertModes(String path, FileMode mode0, FileMode mode1, + FileMode mode2, TreeWalk tw) throws Exception { + assertTrue("has " + path, tw.next()); + assertEquals(path, tw.getPathString()); + if (tw.getFileMode(0) != FileMode.MISSING) { + assertEquals(path, TreeWalk.pathOf(tw.trees[0])); + } + if (tw.getFileMode(1) != FileMode.MISSING) { + assertEquals(path, TreeWalk.pathOf(tw.trees[1])); + } + if (tw.getFileMode(2) != FileMode.MISSING) { + assertEquals(path, TreeWalk.pathOf(tw.trees[2])); + } + assertEquals(mode0, tw.getFileMode(0)); + assertEquals(mode1, tw.getFileMode(1)); + assertEquals(mode2, tw.getFileMode(2)); + } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/HookTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/HookTest.java index 33ed360efd..1231aefee0 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/HookTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/HookTest.java @@ -9,6 +9,7 @@ */ package org.eclipse.jgit.util; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; @@ -77,7 +78,7 @@ public class HookTest extends RepositoryTestCase { "Rejected by \"commit-msg\" hook.\nstderr\n", e.getMessage()); assertEquals("unexpected output from commit-msg hook", "test\n", - out.toString()); + out.toString(UTF_8)); } } @@ -95,7 +96,7 @@ public class HookTest extends RepositoryTestCase { git.commit().setMessage("commit") .setHookOutputStream(new PrintStream(out)).call(); assertEquals(".git/COMMIT_EDITMSG\n", - out.toString("UTF-8")); + out.toString(UTF_8)); } @Test @@ -129,9 +130,9 @@ public class HookTest extends RepositoryTestCase { new PrintStream(out), new PrintStream(err), "stdin"); assertEquals("unexpected hook output", "test arg1 arg2\nstdin\n", - out.toString("UTF-8")); + out.toString(UTF_8)); assertEquals("unexpected output on stderr stream", "stderr\n", - err.toString("UTF-8")); + err.toString(UTF_8)); assertEquals("unexpected exit code", 0, res.getExitCode()); assertEquals("unexpected process status", ProcessResult.Status.OK, res.getStatus()); @@ -160,7 +161,7 @@ public class HookTest extends RepositoryTestCase { } assertEquals("unexpected hook output", "test pre-commit\ntest commit-msg .git/COMMIT_EDITMSG\ntest post-commit\n", - out.toString("UTF-8")); + out.toString(UTF_8)); } @Test @@ -181,9 +182,9 @@ public class HookTest extends RepositoryTestCase { assertEquals("unexpected hook output", "test arg1 arg2\nstdin\n" + db.getDirectory().getAbsolutePath() + '\n' + db.getWorkTree().getAbsolutePath() + '\n', - out.toString("UTF-8")); + out.toString(UTF_8)); assertEquals("unexpected output on stderr stream", "stderr\n", - err.toString("UTF-8")); + err.toString(UTF_8)); assertEquals("unexpected exit code", 0, res.getExitCode()); assertEquals("unexpected process status", ProcessResult.Status.OK, res.getStatus()); @@ -214,9 +215,9 @@ public class HookTest extends RepositoryTestCase { "test arg1 arg2\nstdin\n" + db.getDirectory().getAbsolutePath() + '\n' + db.getWorkTree().getAbsolutePath() + '\n', - out.toString("UTF-8")); + out.toString(UTF_8)); assertEquals("unexpected output on stderr stream", "stderr\n", - err.toString("UTF-8")); + err.toString(UTF_8)); assertEquals("unexpected exit code", 0, res.getExitCode()); assertEquals("unexpected process status", ProcessResult.Status.OK, res.getStatus()); @@ -249,9 +250,9 @@ public class HookTest extends RepositoryTestCase { "test arg1 arg2\nstdin\n" + db.getDirectory().getAbsolutePath() + '\n' + db.getWorkTree().getAbsolutePath() + '\n', - out.toString("UTF-8")); + out.toString(UTF_8)); assertEquals("unexpected output on stderr stream", "stderr\n", - err.toString("UTF-8")); + err.toString(UTF_8)); assertEquals("unexpected exit code", 0, res.getExitCode()); assertEquals("unexpected process status", ProcessResult.Status.OK, res.getStatus()); @@ -281,9 +282,9 @@ public class HookTest extends RepositoryTestCase { "test arg1 arg2\nstdin\n" + db.getDirectory().getAbsolutePath() + '\n' + db.getWorkTree().getAbsolutePath() + '\n', - out.toString("UTF-8")); + out.toString(UTF_8)); assertEquals("unexpected output on stderr stream", "stderr\n", - err.toString("UTF-8")); + err.toString(UTF_8)); assertEquals("unexpected exit code", 0, res.getExitCode()); assertEquals("unexpected process status", ProcessResult.Status.OK, res.getStatus()); @@ -310,7 +311,7 @@ public class HookTest extends RepositoryTestCase { "Rejected by \"pre-commit\" hook.\nstderr\n", e.getMessage()); assertEquals("unexpected output from pre-commit hook", "test\n", - out.toString()); + out.toString(UTF_8)); } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/PathsTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/PathsTest.java index c6976882e4..2fae9099fb 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/PathsTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/PathsTest.java @@ -13,7 +13,9 @@ package org.eclipse.jgit.util; import static org.eclipse.jgit.util.Paths.compare; import static org.eclipse.jgit.util.Paths.compareSameName; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.FileMode; @@ -32,6 +34,23 @@ public class PathsTest { } @Test + public void testPrefix() { + assertTrue(Paths.isEqualOrPrefix("a", "a")); + assertTrue(Paths.isEqualOrPrefix("a", "a/b")); + assertTrue(Paths.isEqualOrPrefix("a", "a/a.txt")); + assertFalse(Paths.isEqualOrPrefix("a", "ab")); + assertFalse(Paths.isEqualOrPrefix("a", "a.txt")); + assertFalse(Paths.isEqualOrPrefix("a", "b/a.txt")); + assertFalse(Paths.isEqualOrPrefix("a", "b/a")); + assertFalse(Paths.isEqualOrPrefix("a", "ab/a.txt")); + assertFalse(Paths.isEqualOrPrefix("", "a")); + assertTrue(Paths.isEqualOrPrefix("", "")); + assertTrue(Paths.isEqualOrPrefix("a/b", "a/b")); + assertTrue(Paths.isEqualOrPrefix("a/b", "a/b/c")); + assertFalse(Paths.isEqualOrPrefix("a/b", "a/bc")); + } + + @Test public void testPathCompare() { byte[] a = Constants.encode("afoo/bar.c"); byte[] b = Constants.encode("bfoo/bar.c"); |