aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit.test/tst/org/eclipse
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit.test/tst/org/eclipse')
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java29
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesHandlerTest.java268
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesMatcherTest.java92
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/CGitAttributesTest.java380
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/CGitIgnoreTest.java243
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectCheckerTest.java98
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/OpenSshConfigTest.java217
7 files changed, 1273 insertions, 54 deletions
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 ae0b8dd3c2..e687a6ca7f 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
@@ -76,6 +76,7 @@ import org.eclipse.jgit.submodule.SubmoduleStatusType;
import org.eclipse.jgit.submodule.SubmoduleWalk;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.RemoteConfig;
+import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.util.SystemReader;
import org.junit.Test;
@@ -145,16 +146,36 @@ public class CloneCommandTest extends RepositoryTestCase {
File directory = createTempDirectory("testCloneRepository");
CloneCommand command = Git.cloneRepository();
command.setDirectory(directory);
- command.setGitDir(new File(directory, ".git"));
+ command.setGitDir(new File(directory, Constants.DOT_GIT));
command.setURI(fileUri());
Git git2 = command.call();
addRepoToClose(git2.getRepository());
assertEquals(directory, git2.getRepository().getWorkTree());
- assertEquals(new File(directory, ".git"), git2.getRepository()
+ assertEquals(new File(directory, Constants.DOT_GIT), git2.getRepository()
.getDirectory());
}
@Test
+ public void testCloneRepositoryDefaultDirectory()
+ throws URISyntaxException, JGitInternalException {
+ CloneCommand command = Git.cloneRepository().setURI(fileUri());
+
+ command.verifyDirectories(new URIish(fileUri()));
+ File directory = command.getDirectory();
+ assertEquals(git.getRepository().getWorkTree().getName(), directory.getName());
+ }
+
+ @Test
+ public void testCloneBareRepositoryDefaultDirectory()
+ throws URISyntaxException, JGitInternalException {
+ CloneCommand command = Git.cloneRepository().setURI(fileUri()).setBare(true);
+
+ command.verifyDirectories(new URIish(fileUri()));
+ File directory = command.getDirectory();
+ assertEquals(git.getRepository().getWorkTree().getName() + Constants.DOT_GIT_EXT, directory.getName());
+ }
+
+ @Test
public void testCloneRepositoryExplicitGitDirNonStd() throws IOException,
JGitInternalException, GitAPIException {
File directory = createTempDirectory("testCloneRepository");
@@ -168,8 +189,8 @@ public class CloneCommandTest extends RepositoryTestCase {
assertEquals(directory, git2.getRepository().getWorkTree());
assertEquals(gDir, git2.getRepository()
.getDirectory());
- assertTrue(new File(directory, ".git").isFile());
- assertFalse(new File(gDir, ".git").exists());
+ assertTrue(new File(directory, Constants.DOT_GIT).isFile());
+ assertFalse(new File(gDir, Constants.DOT_GIT).exists());
}
@Test
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesHandlerTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesHandlerTest.java
index 50d020c57c..5868482c88 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesHandlerTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesHandlerTest.java
@@ -1,4 +1,7 @@
/*
+ * Copyright (C) 2015, 2017 Ivan Motsch <ivan.motsch@bsiag.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
@@ -259,25 +262,274 @@ public class AttributesHandlerTest extends RepositoryTestCase {
setupRepo("sub/ global", "sub/** init",
"sub/** top_sub\n*.txt top",
"sub/** subsub\nsub/ subsub2\n*.txt foo");
- // The last two sub/** and sub/ rules are in sub/.gitattributes. They
- // must not apply to any of the files here. They would match for a
- // further subdirectory sub/sub.
+ // The last sub/** is in sub/.gitattributes. It must not
+ // apply to any of the files here. It would match for a
+ // further subdirectory sub/sub. The sub/ rules must match
+ // only for directories.
walk = beginWalk();
assertIteration(F, ".gitattributes");
assertIteration(D, "sub", attrs("global"));
- assertIteration(F, "sub/.gitattributes", attrs("init top_sub global"));
- assertIteration(F, "sub/a.txt", attrs("init foo top top_sub global"));
+ assertIteration(F, "sub/.gitattributes", attrs("init top_sub"));
+ assertIteration(F, "sub/a.txt", attrs("init foo top top_sub"));
endWalk();
// All right, let's see that they *do* apply in sub/sub:
writeTrashFile("sub/sub/b.txt", "b");
walk = beginWalk();
assertIteration(F, ".gitattributes");
assertIteration(D, "sub", attrs("global"));
- assertIteration(F, "sub/.gitattributes", attrs("init top_sub global"));
- assertIteration(F, "sub/a.txt", attrs("init foo top top_sub global"));
+ assertIteration(F, "sub/.gitattributes", attrs("init top_sub"));
+ assertIteration(F, "sub/a.txt", attrs("init foo top top_sub"));
assertIteration(D, "sub/sub", attrs("init subsub2 top_sub global"));
assertIteration(F, "sub/sub/b.txt",
- attrs("init foo subsub2 subsub top top_sub global"));
+ attrs("init foo subsub top top_sub"));
+ endWalk();
+ }
+
+ @Test
+ public void testNestedMatchNot() throws Exception {
+ setupRepo(null, null, "*.xml xml\n*.jar jar", null);
+ writeTrashFile("foo.xml/bar.jar", "b");
+ writeTrashFile("foo.xml/bar.xml", "bx");
+ writeTrashFile("sub/b.jar", "bj");
+ writeTrashFile("sub/b.xml", "bx");
+ // On foo.xml/bar.jar we must not have 'xml'
+ walk = beginWalk();
+ assertIteration(F, ".gitattributes");
+ assertIteration(D, "foo.xml", attrs("xml"));
+ assertIteration(F, "foo.xml/bar.jar", attrs("jar"));
+ assertIteration(F, "foo.xml/bar.xml", attrs("xml"));
+ assertIteration(D, "sub");
+ assertIteration(F, "sub/a.txt");
+ assertIteration(F, "sub/b.jar", attrs("jar"));
+ assertIteration(F, "sub/b.xml", attrs("xml"));
+ endWalk();
+ }
+
+ @Test
+ public void testNestedMatch() throws Exception {
+ // See also CGitAttributeTest.testNestedMatch()
+ setupRepo(null, null, "foo/ xml\nsub/foo/ sub\n*.jar jar", null);
+ writeTrashFile("foo/bar.jar", "b");
+ writeTrashFile("foo/bar.xml", "bx");
+ writeTrashFile("sub/b.jar", "bj");
+ writeTrashFile("sub/b.xml", "bx");
+ writeTrashFile("sub/foo/b.jar", "bf");
+ walk = beginWalk();
+ assertIteration(F, ".gitattributes");
+ assertIteration(D, "foo", attrs("xml"));
+ assertIteration(F, "foo/bar.jar", attrs("jar"));
+ assertIteration(F, "foo/bar.xml");
+ assertIteration(D, "sub");
+ assertIteration(F, "sub/a.txt");
+ assertIteration(F, "sub/b.jar", attrs("jar"));
+ assertIteration(F, "sub/b.xml");
+ assertIteration(D, "sub/foo", attrs("sub xml"));
+ assertIteration(F, "sub/foo/b.jar", attrs("jar"));
+ endWalk();
+ }
+
+ @Test
+ public void testNestedMatchRecursive() throws Exception {
+ setupRepo(null, null, "foo/** xml\n*.jar jar", null);
+ writeTrashFile("foo/bar.jar", "b");
+ writeTrashFile("foo/bar.xml", "bx");
+ writeTrashFile("sub/b.jar", "bj");
+ writeTrashFile("sub/b.xml", "bx");
+ writeTrashFile("sub/foo/b.jar", "bf");
+ // On foo.xml/bar.jar we must not have 'xml'
+ walk = beginWalk();
+ assertIteration(F, ".gitattributes");
+ assertIteration(D, "foo");
+ assertIteration(F, "foo/bar.jar", attrs("jar xml"));
+ assertIteration(F, "foo/bar.xml", attrs("xml"));
+ assertIteration(D, "sub");
+ assertIteration(F, "sub/a.txt");
+ assertIteration(F, "sub/b.jar", attrs("jar"));
+ assertIteration(F, "sub/b.xml");
+ assertIteration(D, "sub/foo");
+ assertIteration(F, "sub/foo/b.jar", attrs("jar"));
+ endWalk();
+ }
+
+ @Test
+ public void testStarMatchOnSlashNot() throws Exception {
+ setupRepo(null, null, "s*xt bar", null);
+ writeTrashFile("sub/a.txt", "1");
+ writeTrashFile("foo/sext", "2");
+ writeTrashFile("foo/s.txt", "3");
+ walk = beginWalk();
+ assertIteration(F, ".gitattributes");
+ assertIteration(D, "foo");
+ assertIteration(F, "foo/s.txt", attrs("bar"));
+ assertIteration(F, "foo/sext", attrs("bar"));
+ assertIteration(D, "sub");
+ assertIteration(F, "sub/a.txt");
+ endWalk();
+ }
+
+ @Test
+ public void testPrefixMatchNot() throws Exception {
+ setupRepo(null, null, "sub/new bar", null);
+ writeTrashFile("sub/new/foo.txt", "1");
+ walk = beginWalk();
+ assertIteration(F, ".gitattributes");
+ assertIteration(D, "sub");
+ assertIteration(F, "sub/a.txt");
+ assertIteration(D, "sub/new", attrs("bar"));
+ assertIteration(F, "sub/new/foo.txt");
+ endWalk();
+ }
+
+ @Test
+ public void testComplexPathMatch() throws Exception {
+ setupRepo(null, null, "s[t-v]b/n[de]w bar", null);
+ writeTrashFile("sub/new/foo.txt", "1");
+ writeTrashFile("sub/ndw", "2");
+ walk = beginWalk();
+ assertIteration(F, ".gitattributes");
+ assertIteration(D, "sub");
+ assertIteration(F, "sub/a.txt");
+ assertIteration(F, "sub/ndw", attrs("bar"));
+ assertIteration(D, "sub/new", attrs("bar"));
+ assertIteration(F, "sub/new/foo.txt");
+ endWalk();
+ }
+
+ @Test
+ public void testStarPathMatch() throws Exception {
+ setupRepo(null, null, "sub/new/* bar", null);
+ writeTrashFile("sub/new/foo.txt", "1");
+ writeTrashFile("sub/new/lower/foo.txt", "2");
+ walk = beginWalk();
+ assertIteration(F, ".gitattributes");
+ assertIteration(D, "sub");
+ assertIteration(F, "sub/a.txt");
+ assertIteration(D, "sub/new");
+ assertIteration(F, "sub/new/foo.txt", attrs("bar"));
+ assertIteration(D, "sub/new/lower", attrs("bar"));
+ assertIteration(F, "sub/new/lower/foo.txt");
+ endWalk();
+ }
+
+ @Test
+ public void testDirectoryMatchSubSimple() throws Exception {
+ setupRepo(null, null, "sub/new/ bar", null);
+ writeTrashFile("sub/new/foo.txt", "1");
+ writeTrashFile("foo/sub/new/foo.txt", "2");
+ writeTrashFile("sub/sub/new/foo.txt", "3");
+ walk = beginWalk();
+ assertIteration(F, ".gitattributes");
+ assertIteration(D, "foo");
+ assertIteration(D, "foo/sub");
+ assertIteration(D, "foo/sub/new");
+ assertIteration(F, "foo/sub/new/foo.txt");
+ assertIteration(D, "sub");
+ assertIteration(F, "sub/a.txt");
+ assertIteration(D, "sub/new", attrs("bar"));
+ assertIteration(F, "sub/new/foo.txt");
+ assertIteration(D, "sub/sub");
+ assertIteration(D, "sub/sub/new");
+ assertIteration(F, "sub/sub/new/foo.txt");
+ endWalk();
+ }
+
+ @Test
+ public void testDirectoryMatchSubRecursive() throws Exception {
+ setupRepo(null, null, "**/sub/new/ bar", null);
+ writeTrashFile("sub/new/foo.txt", "1");
+ writeTrashFile("foo/sub/new/foo.txt", "2");
+ walk = beginWalk();
+ assertIteration(F, ".gitattributes");
+ assertIteration(D, "foo");
+ assertIteration(D, "foo/sub");
+ assertIteration(D, "foo/sub/new", attrs("bar"));
+ assertIteration(F, "foo/sub/new/foo.txt");
+ assertIteration(D, "sub");
+ assertIteration(F, "sub/a.txt");
+ assertIteration(D, "sub/new", attrs("bar"));
+ assertIteration(F, "sub/new/foo.txt");
+ endWalk();
+ }
+
+ @Test
+ public void testDirectoryMatchSubRecursiveBacktrack() throws Exception {
+ setupRepo(null, null, "**/sub/new/ bar", null);
+ writeTrashFile("sub/new/foo.txt", "1");
+ writeTrashFile("foo/sub/new/foo.txt", "2");
+ writeTrashFile("sub/sub/new/foo.txt", "3");
+ walk = beginWalk();
+ assertIteration(F, ".gitattributes");
+ assertIteration(D, "foo");
+ assertIteration(D, "foo/sub");
+ assertIteration(D, "foo/sub/new", attrs("bar"));
+ assertIteration(F, "foo/sub/new/foo.txt");
+ assertIteration(D, "sub");
+ assertIteration(F, "sub/a.txt");
+ assertIteration(D, "sub/new", attrs("bar"));
+ assertIteration(F, "sub/new/foo.txt");
+ assertIteration(D, "sub/sub");
+ assertIteration(D, "sub/sub/new", attrs("bar"));
+ assertIteration(F, "sub/sub/new/foo.txt");
+ endWalk();
+ }
+
+ @Test
+ public void testDirectoryMatchSubRecursiveBacktrack2() throws Exception {
+ setupRepo(null, null, "**/**/sub/new/ bar", null);
+ writeTrashFile("sub/new/foo.txt", "1");
+ writeTrashFile("foo/sub/new/foo.txt", "2");
+ writeTrashFile("sub/sub/new/foo.txt", "3");
+ walk = beginWalk();
+ assertIteration(F, ".gitattributes");
+ assertIteration(D, "foo");
+ assertIteration(D, "foo/sub");
+ assertIteration(D, "foo/sub/new", attrs("bar"));
+ assertIteration(F, "foo/sub/new/foo.txt");
+ assertIteration(D, "sub");
+ assertIteration(F, "sub/a.txt");
+ assertIteration(D, "sub/new", attrs("bar"));
+ assertIteration(F, "sub/new/foo.txt");
+ assertIteration(D, "sub/sub");
+ assertIteration(D, "sub/sub/new", attrs("bar"));
+ assertIteration(F, "sub/sub/new/foo.txt");
+ endWalk();
+ }
+
+ @Test
+ public void testDirectoryMatchSubComplex() throws Exception {
+ setupRepo(null, null, "s[uv]b/n*/ bar", null);
+ writeTrashFile("sub/new/foo.txt", "1");
+ writeTrashFile("foo/sub/new/foo.txt", "2");
+ walk = beginWalk();
+ assertIteration(F, ".gitattributes");
+ assertIteration(D, "foo");
+ assertIteration(D, "foo/sub");
+ assertIteration(D, "foo/sub/new");
+ assertIteration(F, "foo/sub/new/foo.txt");
+ assertIteration(D, "sub");
+ assertIteration(F, "sub/a.txt");
+ assertIteration(D, "sub/new", attrs("bar"));
+ assertIteration(F, "sub/new/foo.txt");
+ endWalk();
+ }
+
+ @Test
+ public void testDirectoryMatch() throws Exception {
+ setupRepo(null, null, "new/ bar", null);
+ writeTrashFile("sub/new/foo.txt", "1");
+ writeTrashFile("foo/sub/new/foo.txt", "2");
+ writeTrashFile("foo/new", "3");
+ walk = beginWalk();
+ assertIteration(F, ".gitattributes");
+ assertIteration(D, "foo");
+ assertIteration(F, "foo/new");
+ assertIteration(D, "foo/sub");
+ assertIteration(D, "foo/sub/new", attrs("bar"));
+ assertIteration(F, "foo/sub/new/foo.txt");
+ assertIteration(D, "sub");
+ assertIteration(F, "sub/a.txt");
+ assertIteration(D, "sub/new", attrs("bar"));
+ assertIteration(F, "sub/new/foo.txt");
endWalk();
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesMatcherTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesMatcherTest.java
index e8dd952324..23c416a45b 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesMatcherTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesMatcherTest.java
@@ -109,16 +109,16 @@ public class AttributesMatcherTest {
pattern = "/src/ne?";
assertMatched(pattern, "/src/new/");
assertMatched(pattern, "/src/new");
- assertMatched(pattern, "/src/new/a.c");
- assertMatched(pattern, "/src/new/a/a.c");
+ assertNotMatched(pattern, "/src/new/a.c");
+ assertNotMatched(pattern, "/src/new/a/a.c");
assertNotMatched(pattern, "/src/new.c");
//Test name-only fnmatcher matches
pattern = "ne?";
assertMatched(pattern, "/src/new/");
assertMatched(pattern, "/src/new");
- assertMatched(pattern, "/src/new/a.c");
- assertMatched(pattern, "/src/new/a/a.c");
+ assertNotMatched(pattern, "/src/new/a.c");
+ assertNotMatched(pattern, "/src/new/a/a.c");
assertMatched(pattern, "/neb");
assertNotMatched(pattern, "/src/new.c");
}
@@ -169,16 +169,16 @@ public class AttributesMatcherTest {
pattern = "/src/ne?";
assertMatched(pattern, "src/new/");
assertMatched(pattern, "src/new");
- assertMatched(pattern, "src/new/a.c");
- assertMatched(pattern, "src/new/a/a.c");
+ assertNotMatched(pattern, "src/new/a.c");
+ assertNotMatched(pattern, "src/new/a/a.c");
assertNotMatched(pattern, "src/new.c");
//Test name-only fnmatcher matches
pattern = "ne?";
assertMatched(pattern, "src/new/");
assertMatched(pattern, "src/new");
- assertMatched(pattern, "src/new/a.c");
- assertMatched(pattern, "src/new/a/a.c");
+ assertNotMatched(pattern, "src/new/a.c");
+ assertNotMatched(pattern, "src/new/a/a.c");
assertMatched(pattern, "neb");
assertNotMatched(pattern, "src/new.c");
}
@@ -197,35 +197,50 @@ public class AttributesMatcherTest {
pattern = "/src/new";
assertMatched(pattern, "/src/new/");
assertMatched(pattern, "/src/new");
- assertMatched(pattern, "/src/new/a.c");
- assertMatched(pattern, "/src/new/a/a.c");
+ assertNotMatched(pattern, "/src/new/a.c");
+ assertNotMatched(pattern, "/src/new/a/a.c");
assertNotMatched(pattern, "/src/new.c");
//Test child directory is matched, slash after name
pattern = "/src/new/";
assertMatched(pattern, "/src/new/");
- assertMatched(pattern, "/src/new/a.c");
- assertMatched(pattern, "/src/new/a/a.c");
+ assertNotMatched(pattern, "/src/new/a.c");
+ assertNotMatched(pattern, "/src/new/a/a.c");
assertNotMatched(pattern, "/src/new");
assertNotMatched(pattern, "/src/new.c");
//Test directory is matched by name only
pattern = "b1";
- assertMatched(pattern, "/src/new/a/b1/a.c");
+ assertNotMatched(pattern, "/src/new/a/b1/a.c");
assertNotMatched(pattern, "/src/new/a/b2/file.c");
assertNotMatched(pattern, "/src/new/a/bb1/file.c");
assertNotMatched(pattern, "/src/new/a/file.c");
+ assertNotMatched(pattern, "/src/new/a/bb1");
+ assertMatched(pattern, "/src/new/a/b1");
}
@Test
public void testTrailingSlash() {
String pattern = "/src/";
assertMatched(pattern, "/src/");
- assertMatched(pattern, "/src/new");
- assertMatched(pattern, "/src/new/a.c");
- assertMatched(pattern, "/src/a.c");
+ assertNotMatched(pattern, "/src/new");
+ assertNotMatched(pattern, "/src/new/a.c");
+ assertNotMatched(pattern, "/src/a.c");
assertNotMatched(pattern, "/src");
assertNotMatched(pattern, "/srcA/");
+
+ pattern = "src/";
+ assertMatched(pattern, "src/");
+ assertMatched(pattern, "/src/");
+ assertNotMatched(pattern, "src");
+ assertNotMatched(pattern, "/src/new");
+ assertNotMatched(pattern, "/src/new/a.c");
+ assertNotMatched(pattern, "/src/a.c");
+ assertNotMatched(pattern, "foo/src/a.c");
+ assertNotMatched(pattern, "foo/src/bar/a.c");
+ assertNotMatched(pattern, "foo/src/bar/src");
+ assertMatched(pattern, "foo/src/");
+ assertMatched(pattern, "foo/src/bar/src/");
}
@Test
@@ -239,51 +254,58 @@ public class AttributesMatcherTest {
assertMatched(pattern, "/src/test.stp");
assertNotMatched(pattern, "/test.stp1");
assertNotMatched(pattern, "/test.astp");
+ assertNotMatched(pattern, "test.stp/foo.bar");
+ assertMatched(pattern, "test.stp");
+ assertMatched(pattern, "test.stp/");
+ assertMatched(pattern, "test.stp/test.stp");
//Test matches for name-only, applies to file name or folder name
pattern = "src";
assertMatched(pattern, "/src");
assertMatched(pattern, "/src/");
- assertMatched(pattern, "/src/a.c");
- assertMatched(pattern, "/src/new/a.c");
- assertMatched(pattern, "/new/src/a.c");
+ assertNotMatched(pattern, "/src/a.c");
+ assertNotMatched(pattern, "/src/new/a.c");
+ assertNotMatched(pattern, "/new/src/a.c");
assertMatched(pattern, "/file/src");
//Test matches for name-only, applies only to folder names
pattern = "src/";
- assertMatched(pattern, "/src/");
- assertMatched(pattern, "/src/a.c");
- assertMatched(pattern, "/src/new/a.c");
- assertMatched(pattern, "/new/src/a.c");
+ assertNotMatched(pattern, "/src/a.c");
+ assertNotMatched(pattern, "/src/new/a.c");
+ assertNotMatched(pattern, "/new/src/a.c");
assertNotMatched(pattern, "/src");
assertNotMatched(pattern, "/file/src");
+ assertMatched(pattern, "/file/src/");
//Test matches for name-only, applies to file name or folder name
//With a small wildcard
pattern = "?rc";
- assertMatched(pattern, "/src/a.c");
- assertMatched(pattern, "/src/new/a.c");
- assertMatched(pattern, "/new/src/a.c");
+ assertNotMatched(pattern, "/src/a.c");
+ assertNotMatched(pattern, "/src/new/a.c");
+ assertNotMatched(pattern, "/new/src/a.c");
+ assertMatched(pattern, "/new/src/");
assertMatched(pattern, "/file/src");
assertMatched(pattern, "/src/");
//Test matches for name-only, applies to file name or folder name
//With a small wildcard
pattern = "?r[a-c]";
- assertMatched(pattern, "/src/a.c");
- assertMatched(pattern, "/src/new/a.c");
- assertMatched(pattern, "/new/src/a.c");
+ assertNotMatched(pattern, "/src/a.c");
+ assertNotMatched(pattern, "/src/new/a.c");
+ assertNotMatched(pattern, "/new/src/a.c");
assertMatched(pattern, "/file/src");
assertMatched(pattern, "/src/");
- assertMatched(pattern, "/srb/a.c");
- assertMatched(pattern, "/grb/new/a.c");
- assertMatched(pattern, "/new/crb/a.c");
+ assertNotMatched(pattern, "/srb/a.c");
+ assertNotMatched(pattern, "/grb/new/a.c");
+ assertNotMatched(pattern, "/new/crb/a.c");
assertMatched(pattern, "/file/3rb");
assertMatched(pattern, "/xrb/");
- assertMatched(pattern, "/3ra/a.c");
- assertMatched(pattern, "/5ra/new/a.c");
- assertMatched(pattern, "/new/1ra/a.c");
+ assertNotMatched(pattern, "/3ra/a.c");
+ assertNotMatched(pattern, "/5ra/new/a.c");
+ assertNotMatched(pattern, "/new/1ra/a.c");
+ assertNotMatched(pattern, "/new/1ra/a.c/");
assertMatched(pattern, "/file/dra");
+ assertMatched(pattern, "/file/dra/");
assertMatched(pattern, "/era/");
assertNotMatched(pattern, "/crg");
assertNotMatched(pattern, "/cr3");
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/CGitAttributesTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/CGitAttributesTest.java
new file mode 100644
index 0000000000..6188fa60c9
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/CGitAttributesTest.java
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 2017 Thomas Wolf <thomas.wolf@paranor.ch>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.attributes;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.StoredConfig;
+import org.eclipse.jgit.treewalk.FileTreeIterator;
+import org.eclipse.jgit.treewalk.TreeWalk;
+import org.eclipse.jgit.treewalk.filter.NotIgnoredFilter;
+import org.eclipse.jgit.util.FS;
+import org.eclipse.jgit.util.FS.ExecutionResult;
+import org.eclipse.jgit.util.RawParseUtils;
+import org.eclipse.jgit.util.TemporaryBuffer;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests that verify that the attributes of files in a repository are the same
+ * in JGit and in C-git.
+ */
+public class CGitAttributesTest extends RepositoryTestCase {
+
+ @Before
+ public void initRepo() throws IOException {
+ // Because we run C-git, we must ensure that global or user exclude
+ // files cannot influence the tests. So we set core.excludesFile to an
+ // empty file inside the repository.
+ StoredConfig config = db.getConfig();
+ File fakeUserGitignore = writeTrashFile(".fake_user_gitignore", "");
+ config.setString("core", null, "excludesFile",
+ fakeUserGitignore.getAbsolutePath());
+ // Disable case-insensitivity -- JGit doesn't handle that yet.
+ config.setBoolean("core", null, "ignoreCase", false);
+ // And try to switch off the global attributes file, too.
+ config.setString("core", null, "attributesFile",
+ fakeUserGitignore.getAbsolutePath());
+ config.save();
+ }
+
+ private void createFiles(String... paths) throws IOException {
+ for (String path : paths) {
+ writeTrashFile(path, "x");
+ }
+ }
+
+ private String toString(TemporaryBuffer b) throws IOException {
+ return RawParseUtils.decode(b.toByteArray());
+ }
+
+ private Attribute fromString(String key, String value) {
+ if ("set".equals(value)) {
+ return new Attribute(key, Attribute.State.SET);
+ }
+ if ("unset".equals(value)) {
+ return new Attribute(key, Attribute.State.UNSET);
+ }
+ if ("unspecified".equals(value)) {
+ return new Attribute(key, Attribute.State.UNSPECIFIED);
+ }
+ return new Attribute(key, value);
+ }
+
+ private LinkedHashMap<String, Attributes> cgitAttributes(
+ Set<String> allFiles) throws Exception {
+ FS fs = db.getFS();
+ StringBuilder input = new StringBuilder();
+ for (String filename : allFiles) {
+ input.append(filename).append('\n');
+ }
+ ProcessBuilder builder = fs.runInShell("git",
+ new String[] { "check-attr", "--stdin", "--all" });
+ builder.directory(db.getWorkTree());
+ ExecutionResult result = fs.execute(builder, new ByteArrayInputStream(
+ input.toString().getBytes(Constants.CHARSET)));
+ assertEquals("External git reported errors", "",
+ toString(result.getStderr()));
+ assertEquals("External git failed", 0, result.getRc());
+ LinkedHashMap<String, Attributes> map = new LinkedHashMap<>();
+ try (BufferedReader r = new BufferedReader(new InputStreamReader(
+ new BufferedInputStream(result.getStdout().openInputStream()),
+ Constants.CHARSET))) {
+ r.lines().forEach(line -> {
+ // Parse the line and add to result map
+ int start = 0;
+ int i = line.indexOf(':');
+ String path = line.substring(0, i).trim();
+ start = i + 1;
+ i = line.indexOf(':', start);
+ String key = line.substring(start, i).trim();
+ String value = line.substring(i + 1).trim();
+ Attribute attr = fromString(key, value);
+ Attributes attrs = map.get(path);
+ if (attrs == null) {
+ attrs = new Attributes(attr);
+ map.put(path, attrs);
+ } else {
+ attrs.put(attr);
+ }
+ });
+ }
+ return map;
+ }
+
+ private LinkedHashMap<String, Attributes> jgitAttributes()
+ throws IOException {
+ // Do a tree walk and return a list of all files and directories with
+ // their attributes
+ LinkedHashMap<String, Attributes> result = new LinkedHashMap<>();
+ try (TreeWalk walk = new TreeWalk(db)) {
+ walk.addTree(new FileTreeIterator(db));
+ walk.setFilter(new NotIgnoredFilter(0));
+ while (walk.next()) {
+ String path = walk.getPathString();
+ if (walk.isSubtree() && !path.endsWith("/")) {
+ // git check-attr expects directory paths to end with a
+ // slash
+ path += '/';
+ }
+ Attributes attrs = walk.getAttributes();
+ if (attrs != null && !attrs.isEmpty()) {
+ result.put(path, attrs);
+ } else {
+ result.put(path, null);
+ }
+ if (walk.isSubtree()) {
+ walk.enterSubtree();
+ }
+ }
+ }
+ return result;
+ }
+
+ private void assertSameAsCGit() throws Exception {
+ LinkedHashMap<String, Attributes> jgit = jgitAttributes();
+ LinkedHashMap<String, Attributes> cgit = cgitAttributes(jgit.keySet());
+ // remove all without attributes
+ Iterator<Map.Entry<String, Attributes>> iterator = jgit.entrySet()
+ .iterator();
+ while (iterator.hasNext()) {
+ Map.Entry<String, Attributes> entry = iterator.next();
+ if (entry.getValue() == null) {
+ iterator.remove();
+ }
+ }
+ assertArrayEquals("JGit attributes differ from C git",
+ cgit.entrySet().toArray(), jgit.entrySet().toArray());
+ }
+
+ @Test
+ public void testBug508568() throws Exception {
+ createFiles("foo.xml/bar.jar", "sub/foo.xml/bar.jar");
+ writeTrashFile(".gitattributes", "*.xml xml\n" + "*.jar jar\n");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testRelativePath() throws Exception {
+ createFiles("sub/foo.txt");
+ writeTrashFile("sub/.gitattributes", "sub/** sub\n" + "*.txt txt\n");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testRelativePaths() throws Exception {
+ createFiles("sub/foo.txt", "sub/sub/bar", "foo/sub/a.txt",
+ "foo/sub/bar/a.tmp");
+ writeTrashFile(".gitattributes", "sub/** sub\n" + "*.txt txt\n");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testNestedMatchNot() throws Exception {
+ createFiles("foo.xml/bar.jar", "foo.xml/bar.xml", "sub/b.jar",
+ "sub/b.xml");
+ writeTrashFile("sub/.gitattributes", "*.xml xml\n" + "*.jar jar\n");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testNestedMatch() throws Exception {
+ // This is an interesting test. At the time of this writing, the
+ // gitignore documentation says: "In other words, foo/ will match a
+ // directory foo AND PATHS UNDERNEATH IT, but will not match a regular
+ // file or a symbolic link foo". (Emphasis added.) And gitattributes is
+ // supposed to follow the same rules. But the documentation appears to
+ // lie: C-git will *not* apply the attribute "xml" to *any* files in
+ // any subfolder "foo" here. It will only apply the "jar" attribute
+ // to the three *.jar files.
+ //
+ // The point is probably that ignores are handled top-down, and once a
+ // directory "foo" is matched (here: on paths "foo" and "sub/foo" by
+ // pattern "foo/"), the directory is excluded and the gitignore
+ // documentation also says: "It is not possible to re-include a file if
+ // a parent directory of that file is excluded." So once the pattern
+ // "foo/" has matched, it appears as if everything beneath would also be
+ // matched.
+ //
+ // But not so for gitattributes! The foo/ rule only matches the
+ // directory itself, but not anything beneath.
+ createFiles("foo/bar.jar", "foo/bar.xml", "sub/b.jar", "sub/b.xml",
+ "sub/foo/b.jar");
+ writeTrashFile(".gitattributes",
+ "foo/ xml\n" + "sub/foo/ sub\n" + "*.jar jar\n");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testNestedMatchWithWildcard() throws Exception {
+ // See above.
+ createFiles("foo/bar.jar", "foo/bar.xml", "sub/b.jar", "sub/b.xml",
+ "sub/foo/b.jar");
+ writeTrashFile(".gitattributes",
+ "**/foo/ xml\n" + "*/foo/ sub\n" + "*.jar jar\n");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testNestedMatchRecursive() throws Exception {
+ createFiles("foo/bar.jar", "foo/bar.xml", "sub/b.jar", "sub/b.xml",
+ "sub/foo/b.jar");
+ writeTrashFile(".gitattributes", "foo/** xml\n" + "*.jar jar\n");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testStarMatchOnSlashNot() throws Exception {
+ createFiles("sub/a.txt", "foo/sext", "foo/s.txt");
+ writeTrashFile(".gitattributes", "s*xt bar");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testPrefixMatchNot() throws Exception {
+ createFiles("src/new/foo.txt");
+ writeTrashFile(".gitattributes", "src/new bar\n");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testComplexPathMatchNot() throws Exception {
+ createFiles("src/new/foo.txt", "src/ndw");
+ writeTrashFile(".gitattributes", "s[p-s]c/n[de]w bar\n");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testStarPathMatchNot() throws Exception {
+ createFiles("src/new/foo.txt", "src/ndw");
+ writeTrashFile(".gitattributes", "src/* bar\n");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testDirectoryMatchSubSimple() throws Exception {
+ createFiles("src/new/foo.txt", "foo/src/new/foo.txt", "sub/src/new");
+ writeTrashFile(".gitattributes", "src/new/ bar\n");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testDirectoryMatchSubRecursive() throws Exception {
+ createFiles("src/new/foo.txt", "foo/src/new/foo.txt", "sub/src/new");
+ writeTrashFile(".gitattributes", "**/src/new/ bar\n");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testDirectoryMatchSubRecursiveBacktrack() throws Exception {
+ createFiles("src/new/foo.txt", "src/src/new/foo.txt");
+ writeTrashFile(".gitattributes", "**/src/new/ bar\n");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testDirectoryMatchSubRecursiveBacktrack2() throws Exception {
+ createFiles("src/new/foo.txt", "src/src/new/foo.txt");
+ writeTrashFile(".gitattributes", "**/**/src/new/ bar\n");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testDirectoryMatchSubRecursiveBacktrack3() throws Exception {
+ createFiles("src/new/src/new/foo.txt",
+ "foo/src/new/bar/src/new/foo.txt");
+ writeTrashFile(".gitattributes", "**/src/new/ bar\n");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testDirectoryMatchSubRecursiveBacktrack4() throws Exception {
+ createFiles("src/src/src/new/foo.txt",
+ "foo/src/src/bar/src/new/foo.txt");
+ writeTrashFile(".gitattributes", "**/src/ bar\n");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testDirectoryMatchSubRecursiveBacktrack5() throws Exception {
+ createFiles("x/a/a/b/foo.txt", "x/y/z/b/a/b/foo.txt",
+ "x/y/a/a/a/a/b/foo.txt", "x/y/a/a/a/a/b/a/b/foo.txt");
+ writeTrashFile(".gitattributes", "**/*/a/b bar\n");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testDirectoryMatchSubRecursiveBacktrack6() throws Exception {
+ createFiles("x/a/a/b/foo.txt", "x/y/a/b/a/b/foo.txt");
+ writeTrashFile(".gitattributes", "**/*/**/a/b bar\n");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testDirectoryMatchSubComplex() throws Exception {
+ createFiles("src/new/foo.txt", "foo/src/new/foo.txt", "sub/src/new");
+ writeTrashFile(".gitattributes", "s[rs]c/n*/ bar\n");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testDirectoryMatch() throws Exception {
+ createFiles("src/new/foo.txt", "foo/src/new/foo.txt", "sub/src/new");
+ writeTrashFile(".gitattributes", "new/ bar\n");
+ assertSameAsCGit();
+ }
+}
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
new file mode 100644
index 0000000000..c61f2ea7f6
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/CGitIgnoreTest.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2017 Thomas Wolf <thomas.wolf@paranor.ch>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.ignore;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.StoredConfig;
+import org.eclipse.jgit.treewalk.FileTreeIterator;
+import org.eclipse.jgit.treewalk.TreeWalk;
+import org.eclipse.jgit.treewalk.WorkingTreeIterator;
+import org.eclipse.jgit.treewalk.filter.NotIgnoredFilter;
+import org.eclipse.jgit.util.FS;
+import org.eclipse.jgit.util.FS.ExecutionResult;
+import org.eclipse.jgit.util.RawParseUtils;
+import org.eclipse.jgit.util.TemporaryBuffer;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests that verify that the set of ignore files in a repository is the same in
+ * JGit and in C-git.
+ */
+public class CGitIgnoreTest extends RepositoryTestCase {
+
+ @Before
+ public void initRepo() throws IOException {
+ // These tests focus on .gitignore files inside the repository. Because
+ // we run C-git, we must ensure that global or user exclude files cannot
+ // influence the tests. So we set core.excludesFile to an empty file
+ // inside the repository.
+ File fakeUserGitignore = writeTrashFile(".fake_user_gitignore", "");
+ StoredConfig config = db.getConfig();
+ config.setString("core", null, "excludesFile",
+ fakeUserGitignore.getAbsolutePath());
+ // Disable case-insensitivity -- JGit doesn't handle that yet.
+ config.setBoolean("core", null, "ignoreCase", false);
+ config.save();
+ }
+
+ private void createFiles(String... paths) throws IOException {
+ for (String path : paths) {
+ writeTrashFile(path, "x");
+ }
+ }
+
+ private String toString(TemporaryBuffer b) throws IOException {
+ return RawParseUtils.decode(b.toByteArray());
+ }
+
+ private String[] cgitIgnored() throws Exception {
+ FS fs = db.getFS();
+ ProcessBuilder builder = fs.runInShell("git", new String[] { "ls-files",
+ "--ignored", "--exclude-standard", "-o" });
+ builder.directory(db.getWorkTree());
+ ExecutionResult result = fs.execute(builder,
+ new ByteArrayInputStream(new byte[0]));
+ assertEquals("External git failed", 0, result.getRc());
+ assertEquals("External git reported errors", "",
+ toString(result.getStderr()));
+ try (BufferedReader r = new BufferedReader(new InputStreamReader(
+ new BufferedInputStream(result.getStdout().openInputStream()),
+ Constants.CHARSET))) {
+ return r.lines().toArray(String[]::new);
+ }
+ }
+
+ private LinkedHashSet<String> jgitIgnored() throws IOException {
+ // Do a tree walk that does descend into ignored directories and return
+ // a list of all ignored files
+ LinkedHashSet<String> result = new LinkedHashSet<>();
+ try (TreeWalk walk = new TreeWalk(db)) {
+ walk.addTree(new FileTreeIterator(db));
+ walk.setRecursive(true);
+ while (walk.next()) {
+ if (walk.getTree(WorkingTreeIterator.class).isEntryIgnored()) {
+ result.add(walk.getPathString());
+ }
+ }
+ }
+ return result;
+ }
+
+ private void assertNoIgnoredVisited(Set<String> ignored) throws Exception {
+ // Do a recursive tree walk with a NotIgnoredFilter and verify that none
+ // of the files visited is in the ignored set
+ try (TreeWalk walk = new TreeWalk(db)) {
+ walk.addTree(new FileTreeIterator(db));
+ walk.setFilter(new NotIgnoredFilter(0));
+ walk.setRecursive(true);
+ while (walk.next()) {
+ String path = walk.getPathString();
+ assertFalse("File " + path + " is ignored, should not appear",
+ ignored.contains(path));
+ }
+ }
+ }
+
+ private void assertSameAsCGit(String... notIgnored) throws Exception {
+ LinkedHashSet<String> ignored = jgitIgnored();
+ String[] cgit = cgitIgnored();
+ assertArrayEquals(cgit, ignored.toArray());
+ for (String notExcluded : notIgnored) {
+ assertFalse("File " + notExcluded + " should not be ignored",
+ ignored.contains(notExcluded));
+ }
+ assertNoIgnoredVisited(ignored);
+ }
+
+ @Test
+ public void testSimpleIgnored() throws Exception {
+ createFiles("a.txt", "a.tmp", "src/sub/a.txt", "src/a.tmp",
+ "src/a.txt/b.tmp", "ignored/a.tmp", "ignored/not_ignored/a.tmp",
+ "ignored/other/a.tmp");
+ writeTrashFile(".gitignore",
+ "*.txt\n" + "/ignored/*\n" + "!/ignored/not_ignored");
+ assertSameAsCGit("ignored/not_ignored/a.tmp");
+ }
+
+ @Test
+ public void testDirOnlyMatch() throws Exception {
+ createFiles("a.txt", "src/foo/a.txt", "src/a.txt", "foo/a.txt");
+ writeTrashFile(".gitignore", "foo/");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testDirOnlyMatchDeep() throws Exception {
+ createFiles("a.txt", "src/foo/a.txt", "src/a.txt", "foo/a.txt");
+ writeTrashFile(".gitignore", "**/foo/");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testStarMatchOnSlashNot() throws Exception {
+ createFiles("sub/a.txt", "foo/sext", "foo/s.txt");
+ writeTrashFile(".gitignore", "s*xt");
+ assertSameAsCGit("sub/a.txt");
+ }
+
+ @Test
+ public void testPrefixMatch() throws Exception {
+ createFiles("src/new/foo.txt");
+ writeTrashFile(".gitignore", "src/new");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testDirectoryMatchSubRecursive() throws Exception {
+ createFiles("src/new/foo.txt", "foo/src/new/foo.txt", "sub/src/new");
+ writeTrashFile(".gitignore", "**/src/new/");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testDirectoryMatchSubRecursiveBacktrack() throws Exception {
+ createFiles("src/new/foo.txt", "src/src/new/foo.txt");
+ writeTrashFile(".gitignore", "**/src/new/");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testDirectoryMatchSubRecursiveBacktrack2() throws Exception {
+ createFiles("src/new/foo.txt", "src/src/new/foo.txt");
+ writeTrashFile(".gitignore", "**/**/src/new/");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testDirectoryMatchSubRecursiveBacktrack3() throws Exception {
+ createFiles("x/a/a/b/foo.txt");
+ writeTrashFile(".gitignore", "**/*/a/b/");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testDirectoryMatchSubRecursiveBacktrack4() throws Exception {
+ createFiles("x/a/a/b/foo.txt", "x/y/z/b/a/b/foo.txt",
+ "x/y/a/a/a/a/b/foo.txt", "x/y/a/a/a/a/b/a/b/foo.txt");
+ writeTrashFile(".gitignore", "**/*/a/b bar\n");
+ assertSameAsCGit();
+ }
+
+ @Test
+ public void testDirectoryMatchSubRecursiveBacktrack5() throws Exception {
+ createFiles("x/a/a/b/foo.txt", "x/y/a/b/a/b/foo.txt");
+ writeTrashFile(".gitignore", "**/*/**/a/b bar\n");
+ assertSameAsCGit();
+ }
+
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectCheckerTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectCheckerTest.java
index c8729d9443..7f783536a1 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectCheckerTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectCheckerTest.java
@@ -63,6 +63,7 @@ import static org.eclipse.jgit.lib.ObjectChecker.ErrorType.HAS_DOTGIT;
import static org.eclipse.jgit.lib.ObjectChecker.ErrorType.NULL_SHA1;
import static org.eclipse.jgit.lib.ObjectChecker.ErrorType.TREE_NOT_SORTED;
import static org.eclipse.jgit.lib.ObjectChecker.ErrorType.ZERO_PADDED_FILEMODE;
+import static org.eclipse.jgit.util.RawParseUtils.decode;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.fail;
@@ -73,11 +74,16 @@ import java.text.MessageFormat;
import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.internal.JGitText;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
public class ObjectCheckerTest {
private ObjectChecker checker;
+ @Rule
+ public final ExpectedException thrown = ExpectedException.none();
+
@Before
public void setUp() throws Exception {
checker = new ObjectChecker();
@@ -102,6 +108,98 @@ public class ObjectCheckerTest {
}
@Test
+ public void testCheckBlobNotCorrupt() throws CorruptObjectException {
+ checker = new ObjectChecker() {
+ @Override
+ public void checkBlob(byte[] raw) throws CorruptObjectException {
+ String in = decode(raw);
+ if (in.contains("secret_key")) {
+ throw new CorruptObjectException("don't add a secret key");
+ }
+ }
+ };
+ checker.check(OBJ_BLOB, encodeASCII("key = \"public_key\""));
+ }
+
+ @Test
+ public void testCheckBlobCorrupt() throws CorruptObjectException {
+ checker = new ObjectChecker() {
+ @Override
+ public void checkBlob(byte[] raw) throws CorruptObjectException {
+ String in = decode(raw);
+ if (in.contains("secret_key")) {
+ throw new CorruptObjectException("don't add a secret key");
+ }
+ }
+ };
+ thrown.expect(CorruptObjectException.class);
+ checker.check(OBJ_BLOB, encodeASCII("key = \"secret_key\""));
+ }
+
+ @Test
+ public void testCheckBlobWithBlobObjectCheckerNotCorrupt()
+ throws CorruptObjectException {
+ checker = new ObjectChecker() {
+ @Override
+ public BlobObjectChecker newBlobObjectChecker() {
+ return new BlobObjectChecker() {
+ private boolean containSecretKey;
+
+ @Override
+ public void update(byte[] in, int offset, int len) {
+ String str = decode(in, offset, offset + len);
+ if (str.contains("secret_key")) {
+ containSecretKey = true;
+ }
+ }
+
+ @Override
+ public void endBlob(AnyObjectId id)
+ throws CorruptObjectException {
+ if (containSecretKey) {
+ throw new CorruptObjectException(
+ "don't add a secret key");
+ }
+ }
+ };
+ }
+ };
+ checker.check(OBJ_BLOB, encodeASCII("key = \"public_key\""));
+ }
+
+ @Test
+ public void testCheckBlobWithBlobObjectCheckerCorrupt()
+ throws CorruptObjectException {
+ checker = new ObjectChecker() {
+ @Override
+ public BlobObjectChecker newBlobObjectChecker() {
+ return new BlobObjectChecker() {
+ private boolean containSecretKey;
+
+ @Override
+ public void update(byte[] in, int offset, int len) {
+ String str = decode(in, offset, offset + len);
+ if (str.contains("secret_key")) {
+ containSecretKey = true;
+ }
+ }
+
+ @Override
+ public void endBlob(AnyObjectId id)
+ throws CorruptObjectException {
+ if (containSecretKey) {
+ throw new CorruptObjectException(
+ "don't add a secret key");
+ }
+ }
+ };
+ }
+ };
+ thrown.expect(CorruptObjectException.class);
+ checker.check(OBJ_BLOB, encodeASCII("key = \"secret_key\""));
+ }
+
+ @Test
public void testValidCommitNoParent() throws CorruptObjectException {
StringBuilder b = new StringBuilder();
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/OpenSshConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/OpenSshConfigTest.java
index fc520ab17f..3eb049758e 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/OpenSshConfigTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/OpenSshConfigTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2014 Google Inc.
+ * Copyright (C) 2008, 2017 Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
@@ -43,10 +43,13 @@
package org.eclipse.jgit.transport;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.io.File;
@@ -58,9 +61,12 @@ import org.eclipse.jgit.junit.RepositoryTestCase;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.transport.OpenSshConfig.Host;
import org.eclipse.jgit.util.FileUtils;
+import org.eclipse.jgit.util.SystemReader;
import org.junit.Before;
import org.junit.Test;
+import com.jcraft.jsch.ConfigRepository;
+
public class OpenSshConfigTest extends RepositoryTestCase {
private File home;
@@ -79,15 +85,18 @@ public class OpenSshConfigTest extends RepositoryTestCase {
configFile = new File(new File(home, ".ssh"), Constants.CONFIG);
FileUtils.mkdir(configFile.getParentFile());
- System.setProperty("user.name", "jex_junit");
+ mockSystemReader.setProperty(Constants.OS_USER_NAME_KEY, "jex_junit");
osc = new OpenSshConfig(home, configFile);
}
private void config(final String data) throws IOException {
- final OutputStreamWriter fw = new OutputStreamWriter(
- new FileOutputStream(configFile), "UTF-8");
- fw.write(data);
- fw.close();
+ long lastMtime = configFile.lastModified();
+ do {
+ try (final OutputStreamWriter fw = new OutputStreamWriter(
+ new FileOutputStream(configFile), "UTF-8")) {
+ fw.write(data);
+ }
+ } while (lastMtime == configFile.lastModified());
}
@Test
@@ -155,13 +164,18 @@ public class OpenSshConfigTest extends RepositoryTestCase {
@Test
public void testAlias_DoesNotMatch() throws Exception {
- config("Host orcz\n" + "\tHostName repo.or.cz\n");
+ config("Host orcz\n" + "Port 29418\n" + "\tHostName repo.or.cz\n");
final Host h = osc.lookup("repo.or.cz");
assertNotNull(h);
assertEquals("repo.or.cz", h.getHostName());
assertEquals("jex_junit", h.getUser());
assertEquals(22, h.getPort());
assertNull(h.getIdentityFile());
+ final Host h2 = osc.lookup("orcz");
+ assertEquals("repo.or.cz", h.getHostName());
+ assertEquals("jex_junit", h.getUser());
+ assertEquals(29418, h2.getPort());
+ assertNull(h.getIdentityFile());
}
@Test
@@ -282,4 +296,193 @@ public class OpenSshConfigTest extends RepositoryTestCase {
assertNotNull(h);
assertEquals(1, h.getConnectionAttempts());
}
+
+ @Test
+ public void testDefaultBlock() throws Exception {
+ config("ConnectionAttempts 5\n\nHost orcz\nConnectionAttempts 3\n");
+ final Host h = osc.lookup("orcz");
+ assertNotNull(h);
+ assertEquals(5, h.getConnectionAttempts());
+ }
+
+ @Test
+ public void testHostCaseInsensitive() throws Exception {
+ config("hOsT orcz\nConnectionAttempts 3\n");
+ final Host h = osc.lookup("orcz");
+ assertNotNull(h);
+ assertEquals(3, h.getConnectionAttempts());
+ }
+
+ @Test
+ public void testListValueSingle() throws Exception {
+ config("Host orcz\nUserKnownHostsFile /foo/bar\n");
+ final ConfigRepository.Config c = osc.getConfig("orcz");
+ assertNotNull(c);
+ assertEquals("/foo/bar", c.getValue("UserKnownHostsFile"));
+ }
+
+ @Test
+ public void testListValueMultiple() throws Exception {
+ // Tilde expansion doesn't occur within the parser
+ config("Host orcz\nUserKnownHostsFile \"~/foo/ba z\" /foo/bar \n");
+ final ConfigRepository.Config c = osc.getConfig("orcz");
+ assertNotNull(c);
+ assertArrayEquals(new Object[] { "~/foo/ba z", "/foo/bar" },
+ c.getValues("UserKnownHostsFile"));
+ }
+
+ @Test
+ public void testRepeatedLookups() throws Exception {
+ config("Host orcz\n" + "\tConnectionAttempts 5\n");
+ final Host h1 = osc.lookup("orcz");
+ final Host h2 = osc.lookup("orcz");
+ assertNotNull(h1);
+ assertSame(h1, h2);
+ assertEquals(5, h1.getConnectionAttempts());
+ assertEquals(h1.getConnectionAttempts(), h2.getConnectionAttempts());
+ final ConfigRepository.Config c = osc.getConfig("orcz");
+ assertNotNull(c);
+ assertSame(c, h1.getConfig());
+ assertSame(c, h2.getConfig());
+ }
+
+ @Test
+ public void testRepeatedLookupsWithModification() throws Exception {
+ config("Host orcz\n" + "\tConnectionAttempts -1\n");
+ final Host h1 = osc.lookup("orcz");
+ assertNotNull(h1);
+ assertEquals(1, h1.getConnectionAttempts());
+ config("Host orcz\n" + "\tConnectionAttempts 5\n");
+ final Host h2 = osc.lookup("orcz");
+ assertNotNull(h2);
+ assertNotSame(h1, h2);
+ assertEquals(5, h2.getConnectionAttempts());
+ assertEquals(1, h1.getConnectionAttempts());
+ assertNotSame(h1.getConfig(), h2.getConfig());
+ }
+
+ @Test
+ public void testIdentityFile() throws Exception {
+ config("Host orcz\nIdentityFile \"~/foo/ba z\"\nIdentityFile /foo/bar");
+ final Host h = osc.lookup("orcz");
+ assertNotNull(h);
+ File f = h.getIdentityFile();
+ assertNotNull(f);
+ // Host does tilde replacement
+ assertEquals(new File(home, "foo/ba z"), f);
+ final ConfigRepository.Config c = h.getConfig();
+ // Config doesn't
+ assertArrayEquals(new Object[] { "~/foo/ba z", "/foo/bar" },
+ c.getValues("IdentityFile"));
+ }
+
+ @Test
+ public void testMultiIdentityFile() throws Exception {
+ config("IdentityFile \"~/foo/ba z\"\nHost orcz\nIdentityFile /foo/bar\nHOST *\nIdentityFile /foo/baz");
+ final Host h = osc.lookup("orcz");
+ assertNotNull(h);
+ File f = h.getIdentityFile();
+ assertNotNull(f);
+ // Host does tilde replacement
+ assertEquals(new File(home, "foo/ba z"), f);
+ final ConfigRepository.Config c = h.getConfig();
+ // Config doesn't
+ assertArrayEquals(new Object[] { "~/foo/ba z", "/foo/bar", "/foo/baz" },
+ c.getValues("IdentityFile"));
+ }
+
+ @Test
+ public void testNegatedPattern() throws Exception {
+ config("Host repo.or.cz\nIdentityFile ~/foo/bar\nHOST !*.or.cz\nIdentityFile /foo/baz");
+ final Host h = osc.lookup("repo.or.cz");
+ assertNotNull(h);
+ assertEquals(new File(home, "foo/bar"), h.getIdentityFile());
+ assertArrayEquals(new Object[] { "~/foo/bar" },
+ h.getConfig().getValues("IdentityFile"));
+ }
+
+ @Test
+ public void testPattern() throws Exception {
+ config("Host repo.or.cz\nIdentityFile ~/foo/bar\nHOST *.or.cz\nIdentityFile /foo/baz");
+ final Host h = osc.lookup("repo.or.cz");
+ assertNotNull(h);
+ assertEquals(new File(home, "foo/bar"), h.getIdentityFile());
+ assertArrayEquals(new Object[] { "~/foo/bar", "/foo/baz" },
+ h.getConfig().getValues("IdentityFile"));
+ }
+
+ @Test
+ public void testMultiHost() throws Exception {
+ config("Host orcz *.or.cz\nIdentityFile ~/foo/bar\nHOST *.or.cz\nIdentityFile /foo/baz");
+ final Host h1 = osc.lookup("repo.or.cz");
+ assertNotNull(h1);
+ assertEquals(new File(home, "foo/bar"), h1.getIdentityFile());
+ assertArrayEquals(new Object[] { "~/foo/bar", "/foo/baz" },
+ h1.getConfig().getValues("IdentityFile"));
+ final Host h2 = osc.lookup("orcz");
+ assertNotNull(h2);
+ assertEquals(new File(home, "foo/bar"), h2.getIdentityFile());
+ assertArrayEquals(new Object[] { "~/foo/bar" },
+ h2.getConfig().getValues("IdentityFile"));
+ }
+
+ @Test
+ public void testEqualsSign() throws Exception {
+ config("Host=orcz\n\tConnectionAttempts = 5\n\tUser=\t foobar\t\n");
+ final Host h = osc.lookup("orcz");
+ assertNotNull(h);
+ assertEquals(5, h.getConnectionAttempts());
+ assertEquals("foobar", h.getUser());
+ }
+
+ @Test
+ public void testMissingArgument() throws Exception {
+ config("Host=orcz\n\tSendEnv\nIdentityFile\t\nForwardX11\n\tUser=\t foobar\t\n");
+ final Host h = osc.lookup("orcz");
+ assertNotNull(h);
+ assertEquals("foobar", h.getUser());
+ assertArrayEquals(new String[0], h.getConfig().getValues("SendEnv"));
+ assertNull(h.getIdentityFile());
+ assertNull(h.getConfig().getValue("ForwardX11"));
+ }
+
+ @Test
+ public void testHomeDirUserReplacement() throws Exception {
+ config("Host=orcz\n\tIdentityFile %d/.ssh/%u_id_dsa");
+ final Host h = osc.lookup("orcz");
+ assertNotNull(h);
+ assertEquals(new File(new File(home, ".ssh"), "jex_junit_id_dsa"),
+ h.getIdentityFile());
+ }
+
+ @Test
+ public void testHostnameReplacement() throws Exception {
+ config("Host=orcz\nHost *.*\n\tHostname %h\nHost *\n\tHostname %h.example.org");
+ final Host h = osc.lookup("orcz");
+ assertNotNull(h);
+ assertEquals("orcz.example.org", h.getHostName());
+ }
+
+ @Test
+ public void testRemoteUserReplacement() throws Exception {
+ config("Host=orcz\n\tUser foo\n" + "Host *.*\n\tHostname %h\n"
+ + "Host *\n\tHostname %h.ex%%20ample.org\n\tIdentityFile ~/.ssh/%h_%r_id_dsa");
+ final Host h = osc.lookup("orcz");
+ assertNotNull(h);
+ assertEquals(
+ new File(new File(home, ".ssh"),
+ "orcz.ex%20ample.org_foo_id_dsa"),
+ h.getIdentityFile());
+ }
+
+ @Test
+ public void testLocalhostFQDNReplacement() throws Exception {
+ String localhost = SystemReader.getInstance().getHostname();
+ config("Host=orcz\n\tIdentityFile ~/.ssh/%l_id_dsa");
+ final Host h = osc.lookup("orcz");
+ assertNotNull(h);
+ assertEquals(
+ new File(new File(home, ".ssh"), localhost + "_id_dsa"),
+ h.getIdentityFile());
+ }
}