aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit.test
diff options
context:
space:
mode:
authorMatthias Sohn <matthias.sohn@sap.com>2023-09-03 02:16:04 +0200
committerMatthias Sohn <matthias.sohn@sap.com>2023-09-03 02:16:04 +0200
commit7a6e8527455616c33b2b5ccfba1a823416bca1c8 (patch)
tree87f9e01d58cc46c7980599508a6343ac07b1c0e1 /org.eclipse.jgit.test
parent96934c9a80bdc307933eeef53fec2748b3a000cb (diff)
parent43d6bc5ef1add70315b411969aac2ad84bf0f492 (diff)
downloadjgit-7a6e8527455616c33b2b5ccfba1a823416bca1c8.tar.gz
jgit-7a6e8527455616c33b2b5ccfba1a823416bca1c8.zip
Merge branch 'stable-6.6' into stable-6.7
* stable-6.6: Prepare 6.6.2-SNAPSHOT builds JGit v6.6.1.202309021850-r Checkout: better directory handling Change-Id: Ice82d68b2d343a5fac214807cdb369e486481aab
Diffstat (limited to 'org.eclipse.jgit.test')
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/dotgit.patch9
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/dotgit2.patch9
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/symlinks/.gitattributes1
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/symlinks/dirtest.patch9
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheEntryTest.java12
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/InvalidPathCheckoutTest.java61
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchApplierTest.java26
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/symlinks/DirectoryTest.java259
8 files changed, 385 insertions, 1 deletions
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/dotgit.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/dotgit.patch
new file mode 100644
index 0000000000..802fa15465
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/dotgit.patch
@@ -0,0 +1,9 @@
+diff --git a/.git/b b/.git/b
+new file mode 100644
+index 0000000..de98044
+--- /dev/null
++++ b/.git/b
+@@ -0,0 +1,3 @@
++a
++b
++c \ No newline at end of file
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/dotgit2.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/dotgit2.patch
new file mode 100644
index 0000000000..03cacbaeed
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/dotgit2.patch
@@ -0,0 +1,9 @@
+diff --git a/.GIT/b b/.GIT/b
+new file mode 100644
+index 0000000..de98044
+--- /dev/null
++++ b/.git/b
+@@ -0,0 +1,3 @@
++a
++b
++c \ No newline at end of file
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/symlinks/.gitattributes b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/symlinks/.gitattributes
new file mode 100644
index 0000000000..b38f87f9e3
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/symlinks/.gitattributes
@@ -0,0 +1 @@
+*.patch -crlf
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/symlinks/dirtest.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/symlinks/dirtest.patch
new file mode 100644
index 0000000000..a275c8593f
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/symlinks/dirtest.patch
@@ -0,0 +1,9 @@
+diff --git a/a/b b/a/b
+new file mode 100644
+index 0000000..de98044
+--- /dev/null
++++ b/a/b
+@@ -0,0 +1,3 @@
++a
++b
++c \ No newline at end of file
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheEntryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheEntryTest.java
index 8e84dfa318..01d1e0282d 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheEntryTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheEntryTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, 2020 Google Inc. and others
+ * Copyright (C) 2009, 2023 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
@@ -46,6 +46,16 @@ public class DirCacheEntryTest {
assertFalse(isValidPath("a/"));
assertFalse(isValidPath("ab/cd/ef/"));
assertFalse(isValidPath("a\u0000b"));
+ assertFalse(isValidPath(".git"));
+ assertFalse(isValidPath(".GIT"));
+ assertFalse(isValidPath(".Git"));
+ assertFalse(isValidPath(".git/b"));
+ assertFalse(isValidPath(".GIT/b"));
+ assertFalse(isValidPath(".Git/b"));
+ assertFalse(isValidPath("x/y/.git/z/b"));
+ assertFalse(isValidPath("x/y/.GIT/z/b"));
+ assertFalse(isValidPath("x/y/.Git/z/b"));
+ assertTrue(isValidPath("git/b"));
}
@SuppressWarnings("unused")
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/InvalidPathCheckoutTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/InvalidPathCheckoutTest.java
new file mode 100644
index 0000000000..e3bc85a512
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/InvalidPathCheckoutTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2023 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.dircache;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThrows;
+
+import java.io.File;
+
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.ResetCommand.ResetType;
+import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevBlob;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.junit.Test;
+
+/**
+ * Tests for checking out with invalid paths.
+ */
+public class InvalidPathCheckoutTest extends RepositoryTestCase {
+
+ private DirCacheEntry brokenEntry(String fileName, RevBlob blob) {
+ DirCacheEntry entry = new DirCacheEntry("XXXX/" + fileName);
+ entry.path[0] = '.';
+ entry.path[1] = 'g';
+ entry.path[2] = 'i';
+ entry.path[3] = 't';
+ entry.setFileMode(FileMode.REGULAR_FILE);
+ entry.setObjectId(blob);
+ return entry;
+ }
+
+ @Test
+ public void testCheckoutIntoDotGit() throws Exception {
+ try (TestRepository<Repository> repo = new TestRepository<>(db)) {
+ db.incrementOpen();
+ // DirCacheEntry does not allow any path component to contain
+ // ".git". C git also forbids this. But what if somebody creates
+ // such an entry explicitly?
+ RevCommit base = repo
+ .commit(repo.tree(brokenEntry("b", repo.blob("test"))));
+ try (Git git = new Git(db)) {
+ assertThrows(InvalidPathException.class, () -> git.reset()
+ .setMode(ResetType.HARD).setRef(base.name()).call());
+ File b = new File(new File(trash, ".git"), "b");
+ assertFalse(".git/b should not exist", b.exists());
+ }
+ }
+ }
+
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchApplierTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchApplierTest.java
index e2637257c5..92d47c2966 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchApplierTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchApplierTest.java
@@ -24,6 +24,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
+
import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.attributes.FilterCommand;
@@ -892,5 +893,30 @@ public class PatchApplierTest {
FilterCommandRegistry.unregister("jgit://builtin/a2e/smudge");
}
}
+
+ private void dotGitTest(String fileName) throws Exception {
+ init(fileName, false, false);
+ Result result = null;
+ IOException ex = null;
+ try {
+ result = applyPatch();
+ } catch (IOException e) {
+ ex = e;
+ }
+ assertTrue(ex != null
+ || (result != null && !result.getErrors().isEmpty()));
+ File b = new File(new File(trash, ".git"), "b");
+ assertFalse(".git/b should not exist", b.exists());
+ }
+
+ @Test
+ public void testDotGit() throws Exception {
+ dotGitTest("dotgit");
+ }
+
+ @Test
+ public void testDotGit2() throws Exception {
+ dotGitTest("dotgit2");
+ }
}
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/symlinks/DirectoryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/symlinks/DirectoryTest.java
new file mode 100644
index 0000000000..490c45b558
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/symlinks/DirectoryTest.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2023 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.symlinks;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
+
+import org.eclipse.jgit.api.Git;
+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.patch.Patch;
+import org.eclipse.jgit.patch.PatchApplier;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.util.FS;
+import org.eclipse.jgit.util.FileUtils;
+import org.junit.Assume;
+import org.junit.BeforeClass;
+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;
+
+@RunWith(Parameterized.class)
+public class DirectoryTest extends RepositoryTestCase {
+
+ @BeforeClass
+ public static void checkPrecondition() throws Exception {
+ Assume.assumeTrue(FS.DETECTED.supportsSymlinks());
+ Path tempDir = Files.createTempDirectory("jgit");
+ try {
+ Path a = tempDir.resolve("a");
+ Files.writeString(a, "test");
+ Path b = tempDir.resolve("A");
+ Assume.assumeTrue(Files.exists(b));
+ } finally {
+ FileUtils.delete(tempDir.toFile(),
+ FileUtils.RECURSIVE | FileUtils.IGNORE_ERRORS);
+ }
+ }
+
+ @Parameters(name = "core.symlinks={0}")
+ public static Boolean[] parameters() {
+ return new Boolean[] { Boolean.TRUE, Boolean.FALSE };
+ }
+
+ @Parameter(0)
+ public boolean useSymlinks;
+
+ private void checkFiles() throws Exception {
+ File a = new File(trash, "a");
+ assertTrue("a should be a directory",
+ Files.isDirectory(a.toPath(), LinkOption.NOFOLLOW_LINKS));
+ File b = new File(a, "b");
+ assertTrue("a/b should exist", b.isFile());
+ File x = new File(trash, "x");
+ assertTrue("x should be a directory",
+ Files.isDirectory(x.toPath(), LinkOption.NOFOLLOW_LINKS));
+ File y = new File(x, "y");
+ assertTrue("x/y should exist", y.isFile());
+ }
+
+ @Test
+ public void testCheckout() throws Exception {
+ 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 links directly in the git repo, then use a hard reset
+ // to get them into the workspace.
+ RevCommit base = repo.commit(
+ repo.tree(
+ repo.link("A", repo.blob(".git")),
+ repo.file("a/b", repo.blob("test")),
+ repo.file("x/y", repo.blob("test2"))));
+ try (Git git = new Git(db)) {
+ git.reset().setMode(ResetType.HARD).setRef(base.name()).call();
+ File b = new File(new File(trash, ".git"), "b");
+ assertFalse(".git/b should not exist", b.exists());
+ checkFiles();
+ }
+ }
+ }
+
+ @Test
+ public void testCheckout2() throws Exception {
+ 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("A/B", repo.blob("../.git")),
+ repo.file("a/b/a/b", repo.blob("test")),
+ repo.file("x/y", repo.blob("test2"))));
+ try (Git git = new Git(db)) {
+ boolean testFiles = true;
+ try {
+ git.reset().setMode(ResetType.HARD).setRef(base.name())
+ .call();
+ } catch (Exception e) {
+ if (!useSymlinks) {
+ // There is a file in the middle of the path where we'd
+ // expect a directory. This case is not handled
+ // anywhere. What would be a better reply than an IOE?
+ testFiles = false;
+ } else {
+ throw e;
+ }
+ }
+ File a = new File(new File(trash, ".git"), "a");
+ assertFalse(".git/a should not exist", a.exists());
+ if (testFiles) {
+ a = new File(trash, "a");
+ assertTrue("a should be a directory", Files.isDirectory(
+ a.toPath(), LinkOption.NOFOLLOW_LINKS));
+ File b = new File(a, "b");
+ assertTrue("a/b should be a directory", Files.isDirectory(
+ a.toPath(), LinkOption.NOFOLLOW_LINKS));
+ a = new File(b, "a");
+ assertTrue("a/b/a should be a directory", Files.isDirectory(
+ a.toPath(), LinkOption.NOFOLLOW_LINKS));
+ b = new File(a, "b");
+ assertTrue("a/b/a/b should exist", b.isFile());
+ File x = new File(trash, "x");
+ assertTrue("x should be a directory", Files.isDirectory(
+ x.toPath(), LinkOption.NOFOLLOW_LINKS));
+ File y = new File(x, "y");
+ assertTrue("x/y should exist", y.isFile());
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testMerge() throws Exception {
+ 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.file("q", repo.blob("test"))));
+ RevCommit side = repo.commit(
+ repo.tree(
+ repo.link("A", repo.blob(".git")),
+ repo.file("a/b", repo.blob("test")),
+ repo.file("x/y", repo.blob("test2"))));
+ try (Git git = new Git(db)) {
+ git.reset().setMode(ResetType.HARD).setRef(base.name()).call();
+ git.merge().include(side)
+ .setMessage("merged").call();
+ File b = new File(new File(trash, ".git"), "b");
+ assertFalse(".git/b should not exist", b.exists());
+ checkFiles();
+ }
+ }
+ }
+
+ @Test
+ public void testMerge2() throws Exception {
+ 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.file("q", repo.blob("test")),
+ repo.link("A", repo.blob(".git"))));
+ RevCommit side = repo.commit(
+ repo.tree(
+ repo.file("a/b", repo.blob("test")),
+ repo.file("x/y", repo.blob("test2"))));
+ try (Git git = new Git(db)) {
+ git.reset().setMode(ResetType.HARD).setRef(base.name()).call();
+ git.merge().include(side)
+ .setMessage("merged").call();
+ File b = new File(new File(trash, ".git"), "b");
+ assertFalse(".git/b should not exist", b.exists());
+ checkFiles();
+ }
+ }
+ }
+
+ @Test
+ public void testApply() throws Exception {
+ StoredConfig config = db.getConfig();
+ config.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
+ ConfigConstants.CONFIG_KEY_SYMLINKS, useSymlinks);
+ config.save();
+ // PatchApplier doesn't do symlinks yet.
+ try (TestRepository<Repository> repo = new TestRepository<>(db)) {
+ db.incrementOpen();
+ RevCommit base = repo.commit(
+ repo.tree(
+ repo.file("x", repo.blob("test")),
+ repo.link("A", repo.blob(".git"))));
+ try (Git git = new Git(db)) {
+ git.reset().setMode(ResetType.HARD).setRef(base.name()).call();
+ Patch patch = new Patch();
+ try (InputStream patchStream = this.getClass()
+ .getResourceAsStream("dirtest.patch")) {
+ patch.parse(patchStream);
+ }
+ boolean testFiles = true;
+ try {
+ PatchApplier.Result result = new PatchApplier(db)
+ .applyPatch(patch);
+ assertNotNull(result);
+ } catch (IOException e) {
+ if (!useSymlinks) {
+ // There is a file there, so the patch won't apply.
+ // Unclear whether an IOE is the correct response,
+ // though. Probably some negative PatchApplier.Result is
+ // more appropriate.
+ testFiles = false;
+ } else {
+ throw e;
+ }
+ }
+ File b = new File(new File(trash, ".git"), "b");
+ assertFalse(".git/b should not exist", b.exists());
+ if (testFiles) {
+ File a = new File(trash, "a");
+ assertTrue("a should be a directory",
+ Files.isDirectory(a.toPath(), LinkOption.NOFOLLOW_LINKS));
+ b = new File(a, "b");
+ assertTrue("a/b should exist", b.isFile());
+ }
+ }
+ }
+ }
+}