summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit.test
diff options
context:
space:
mode:
authorAndrey Loskutov <loskutov@gmx.de>2014-08-11 09:28:52 +0200
committerMatthias Sohn <matthias.sohn@sap.com>2014-10-27 19:26:42 +0100
commit2f5a08798eb29e8141c452c0dc2622bc8fe90dd0 (patch)
treec719668c07c7bb8740251789e0bac95ff8008fd9 /org.eclipse.jgit.test
parent6eca51923f49026d6e91052bc959472732332560 (diff)
downloadjgit-2f5a08798eb29e8141c452c0dc2622bc8fe90dd0.tar.gz
jgit-2f5a08798eb29e8141c452c0dc2622bc8fe90dd0.zip
Reimplementation of ignore rule parser
The current IgnoreRule/FileNameMatcher implementation scales not well with huge repositories - it is both slow and memory expensive while parsing glob expressions (bug 440732). Addtitionally, the "double star" pattern (/**/) is not understood by the old parser (bug 416348). The proposed implementation is a complete clean room rewrite of the gitignore parser, aiming to add missing double star pattern support and improve the performance and memory consumption. The glob expressions from .gitignore rules are converted to Java regular expressions (java.util.regex.Pattern). java.util.regex.Pattern code can evaluate expression from gitignore rules considerable faster (and with less memory consumption) as the old FileNameMatcher implementation. CQ: 8828 Bug: 416348 Bug: 440732 Change-Id: Ibefb930381f2f16eddb9947e592752f8ae2b76e1 Signed-off-by: Andrey Loskutov <loskutov@gmx.de> Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
Diffstat (limited to 'org.eclipse.jgit.test')
-rw-r--r--org.eclipse.jgit.test/META-INF/MANIFEST.MF4
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/BasicRuleTest.java74
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/FastIgnoreRuleTest.java561
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreMatcherParametrizedTest.java371
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreMatcherTest.java9
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreRuleSpecialCasesTest.java904
6 files changed, 1918 insertions, 5 deletions
diff --git a/org.eclipse.jgit.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.test/META-INF/MANIFEST.MF
index d493ae4e10..7b9bd64bc1 100644
--- a/org.eclipse.jgit.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.test/META-INF/MANIFEST.MF
@@ -20,6 +20,7 @@ Import-Package: com.googlecode.javaewah;version="[0.7.9,0.8.0)",
org.eclipse.jgit.fnmatch;version="[3.6.0,3.7.0)",
org.eclipse.jgit.gitrepo;version="[3.6.0,3.7.0)",
org.eclipse.jgit.ignore;version="[3.6.0,3.7.0)",
+ org.eclipse.jgit.ignore.internal;version="[3.6.0,3.7.0)",
org.eclipse.jgit.internal;version="[3.6.0,3.7.0)",
org.eclipse.jgit.internal.storage.dfs;version="[3.6.0,3.7.0)",
org.eclipse.jgit.internal.storage.file;version="[3.6.0,3.7.0)",
@@ -47,5 +48,6 @@ Import-Package: com.googlecode.javaewah;version="[0.7.9,0.8.0)",
org.hamcrest;version="[1.1.0,2.0.0)",
org.junit;version="[4.4.0,5.0.0)",
org.junit.experimental.theories;version="[4.4.0,5.0.0)",
- org.junit.runner;version="[4.4.0,5.0.0)"
+ org.junit.runner;version="[4.4.0,5.0.0)",
+ org.junit.runners;version="[4.11.0,5.0.0)"
Require-Bundle: org.hamcrest.core;bundle-version="[1.1.0,2.0.0)"
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/BasicRuleTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/BasicRuleTest.java
new file mode 100644
index 0000000000..2349b55c64
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/BasicRuleTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2014, Andrey Loskutov <loskutov@gmx.de>
+ * 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.*;
+
+import org.eclipse.jgit.ignore.FastIgnoreRule;
+import org.junit.Test;
+
+public class BasicRuleTest {
+
+ @Test
+ public void test() {
+ FastIgnoreRule rule1 = new FastIgnoreRule("/hello/[a]/");
+ FastIgnoreRule rule2 = new FastIgnoreRule("/hello/[a]/");
+ FastIgnoreRule rule3 = new FastIgnoreRule("!/hello/[a]/");
+ FastIgnoreRule rule4 = new FastIgnoreRule("/hello/[a]");
+ assertTrue(rule1.dirOnly());
+ assertTrue(rule3.dirOnly());
+ assertFalse(rule4.dirOnly());
+ assertFalse(rule1.getNegation());
+ assertTrue(rule3.getNegation());
+ assertNotEquals(rule1, null);
+ assertEquals(rule1, rule1);
+ assertEquals(rule1, rule2);
+ assertNotEquals(rule1, rule3);
+ assertNotEquals(rule1, rule4);
+ assertEquals(rule1.hashCode(), rule2.hashCode());
+ assertNotEquals(rule1.hashCode(), rule3.hashCode());
+ assertEquals(rule1.toString(), rule2.toString());
+ assertNotEquals(rule1.toString(), rule3.toString());
+ }
+
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/FastIgnoreRuleTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/FastIgnoreRuleTest.java
new file mode 100644
index 0000000000..dab4e351a3
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/FastIgnoreRuleTest.java
@@ -0,0 +1,561 @@
+/*
+ * Copyright (C) 2014, Andrey Loskutov <loskutov@gmx.de>
+ * 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.eclipse.jgit.ignore.internal.Strings.split;
+import static org.junit.Assert.*;
+import static org.junit.Assume.*;
+
+import java.util.Arrays;
+
+import org.eclipse.jgit.ignore.FastIgnoreRule;
+import org.eclipse.jgit.ignore.IgnoreRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.*;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@SuppressWarnings("deprecation")
+@RunWith(Parameterized.class)
+public class FastIgnoreRuleTest {
+
+ @Parameters(name = "JGit? {0}")
+ public static Iterable<Boolean[]> data() {
+ return Arrays.asList(new Boolean[][] { { Boolean.FALSE },
+ { Boolean.TRUE } });
+ }
+
+ @Parameter
+ public Boolean useJGitRule;
+
+ @Test
+ public void testSimpleCharClass() {
+ assertMatched("[a]", "a");
+ assertMatched("[a]", "a/");
+ assertMatched("[a]", "a/b");
+
+ assertMatched("[a]", "b/a");
+ assertMatched("[a]", "b/a/");
+ assertMatched("[a]", "b/a/b");
+
+ assertMatched("[a]", "/a/");
+ assertMatched("[a]", "/a/b");
+
+ assertMatched("[a]", "c/a/b");
+ assertMatched("[a]", "c/b/a");
+
+ assertMatched("/[a]", "a");
+ assertMatched("/[a]", "a/");
+ assertMatched("/[a]", "a/b");
+ assertMatched("/[a]", "/a");
+ assertMatched("/[a]", "/a/");
+ assertMatched("/[a]", "/a/b");
+
+ assertMatched("[a]/", "a/");
+ assertMatched("[a]/", "a/b");
+ assertMatched("[a]/", "/a/");
+ assertMatched("[a]/", "/a/b");
+
+ assertMatched("/[a]/", "a/");
+ assertMatched("/[a]/", "a/b");
+ assertMatched("/[a]/", "/a/");
+ assertMatched("/[a]/", "/a/b");
+ }
+
+ @Test
+ public void testCharClass() {
+ assertMatched("[v-z]", "x");
+ assertMatched("[v-z]", "x/");
+ assertMatched("[v-z]", "x/b");
+
+ assertMatched("[v-z]", "b/x");
+ assertMatched("[v-z]", "b/x/");
+ assertMatched("[v-z]", "b/x/b");
+
+ assertMatched("[v-z]", "/x/");
+ assertMatched("[v-z]", "/x/b");
+
+ assertMatched("[v-z]", "c/x/b");
+ assertMatched("[v-z]", "c/b/x");
+
+ assertMatched("/[v-z]", "x");
+ assertMatched("/[v-z]", "x/");
+ assertMatched("/[v-z]", "x/b");
+ assertMatched("/[v-z]", "/x");
+ assertMatched("/[v-z]", "/x/");
+ assertMatched("/[v-z]", "/x/b");
+
+ assertMatched("[v-z]/", "x/");
+ assertMatched("[v-z]/", "x/b");
+ assertMatched("[v-z]/", "/x/");
+ assertMatched("[v-z]/", "/x/b");
+
+ assertMatched("/[v-z]/", "x/");
+ assertMatched("/[v-z]/", "x/b");
+ assertMatched("/[v-z]/", "/x/");
+ assertMatched("/[v-z]/", "/x/b");
+ }
+
+ @Test
+ public void testAsteriskDot() {
+ assertMatched("*.a", ".a");
+ assertMatched("*.a", "/.a");
+ assertMatched("*.a", "a.a");
+ assertMatched("*.a", "/b.a");
+ assertMatched("*.a", "b.a");
+ assertMatched("*.a", "/a/b.a");
+ assertMatched("*.a", "/b/.a");
+ }
+
+ @Test
+ public void testAsteriskDotDoNotMatch() {
+ assertNotMatched("*.a", ".ab");
+ assertNotMatched("*.a", "/.ab");
+ assertNotMatched("*.a", "/b.ba");
+ assertNotMatched("*.a", "a.ab");
+ assertNotMatched("*.a", "/b.ab");
+ assertNotMatched("*.a", "b.ab");
+ assertNotMatched("*.a", "/a/b.ab");
+ assertNotMatched("*.a", "/b/.ab");
+ }
+
+ @Test
+ public void testDotAsteriskMatch() {
+ assertMatched("a.*", "a.");
+ assertMatched("a.*", "a./");
+ assertMatched("a.*", "a.b");
+
+ assertMatched("a.*", "b/a.b");
+ assertMatched("a.*", "b/a.b/");
+ assertMatched("a.*", "b/a.b/b");
+
+ assertMatched("a.*", "/a.b/");
+ assertMatched("a.*", "/a.b/b");
+
+ assertMatched("a.*", "c/a.b/b");
+ assertMatched("a.*", "c/b/a.b");
+
+ assertMatched("/a.*", "a.b");
+ assertMatched("/a.*", "a.b/");
+ assertMatched("/a.*", "a.b/b");
+ assertMatched("/a.*", "/a.b");
+ assertMatched("/a.*", "/a.b/");
+ assertMatched("/a.*", "/a.b/b");
+
+ assertMatched("/a.*/b", "a.b/b");
+ assertMatched("/a.*/b", "/a.b/b");
+ assertMatched("/a.*/b", "/a.bc/b");
+ assertMatched("/a.*/b", "/a./b");
+ }
+
+ @Test
+ public void testAsterisk() {
+ assertMatched("a*", "a");
+ assertMatched("a*", "a/");
+ assertMatched("a*", "ab");
+
+ assertMatched("a*", "b/ab");
+ assertMatched("a*", "b/ab/");
+ assertMatched("a*", "b/ab/b");
+
+ assertMatched("a*", "b/abc");
+ assertMatched("a*", "b/abc/");
+ assertMatched("a*", "b/abc/b");
+
+ assertMatched("a*", "/abc/");
+ assertMatched("a*", "/abc/b");
+
+ assertMatched("a*", "c/abc/b");
+ assertMatched("a*", "c/b/abc");
+
+ assertMatched("/a*", "abc");
+ assertMatched("/a*", "abc/");
+ assertMatched("/a*", "abc/b");
+ assertMatched("/a*", "/abc");
+ assertMatched("/a*", "/abc/");
+ assertMatched("/a*", "/abc/b");
+
+ assertMatched("/a*/b", "abc/b");
+ assertMatched("/a*/b", "/abc/b");
+ assertMatched("/a*/b", "/abcd/b");
+ assertMatched("/a*/b", "/a/b");
+ }
+
+ @Test
+ public void testQuestionmark() {
+ assertMatched("a?", "ab");
+ assertMatched("a?", "ab/");
+
+ assertMatched("a?", "b/ab");
+ assertMatched("a?", "b/ab/");
+ assertMatched("a?", "b/ab/b");
+
+ assertMatched("a?", "/ab/");
+ assertMatched("a?", "/ab/b");
+
+ assertMatched("a?", "c/ab/b");
+ assertMatched("a?", "c/b/ab");
+
+ assertMatched("/a?", "ab");
+ assertMatched("/a?", "ab/");
+ assertMatched("/a?", "ab/b");
+ assertMatched("/a?", "/ab");
+ assertMatched("/a?", "/ab/");
+ assertMatched("/a?", "/ab/b");
+
+ assertMatched("/a?/b", "ab/b");
+ assertMatched("/a?/b", "/ab/b");
+ }
+
+ @Test
+ public void testQuestionmarkDoNotMatch() {
+ assertNotMatched("a?", "a/");
+ assertNotMatched("a?", "abc");
+ assertNotMatched("a?", "abc/");
+
+ assertNotMatched("a?", "b/abc");
+ assertNotMatched("a?", "b/abc/");
+
+ assertNotMatched("a?", "/abc/");
+ assertNotMatched("a?", "/abc/b");
+
+ assertNotMatched("a?", "c/abc/b");
+ assertNotMatched("a?", "c/b/abc");
+
+ assertNotMatched("/a?", "abc");
+ assertNotMatched("/a?", "abc/");
+ assertNotMatched("/a?", "abc/b");
+ assertNotMatched("/a?", "/abc");
+ assertNotMatched("/a?", "/abc/");
+ assertNotMatched("/a?", "/abc/b");
+
+ assertNotMatched("/a?/b", "abc/b");
+ assertNotMatched("/a?/b", "/abc/b");
+ assertNotMatched("/a?/b", "/a/b");
+ }
+
+ @Test
+ public void testSimplePatterns() {
+ assertMatched("a", "a");
+ assertMatched("a", "a/");
+ assertMatched("a", "a/b");
+
+ assertMatched("a", "b/a");
+ assertMatched("a", "b/a/");
+ assertMatched("a", "b/a/b");
+
+ assertMatched("a", "/a/");
+ assertMatched("a", "/a/b");
+
+ assertMatched("a", "c/a/b");
+ assertMatched("a", "c/b/a");
+
+ assertMatched("/a", "a");
+ assertMatched("/a", "a/");
+ assertMatched("/a", "a/b");
+ assertMatched("/a", "/a");
+ assertMatched("/a", "/a/");
+ assertMatched("/a", "/a/b");
+
+ assertMatched("a/", "a/");
+ assertMatched("a/", "a/b");
+ assertMatched("a/", "/a/");
+ assertMatched("a/", "/a/b");
+
+ assertMatched("/a/", "a/");
+ assertMatched("/a/", "a/b");
+ assertMatched("/a/", "/a/");
+ assertMatched("/a/", "/a/b");
+
+ }
+
+ @Test
+ public void testSimplePatternsDoNotMatch() {
+ assertNotMatched("ab", "a");
+ assertNotMatched("abc", "a/");
+ assertNotMatched("abc", "a/b");
+
+ assertNotMatched("a", "ab");
+ assertNotMatched("a", "ba");
+ assertNotMatched("a", "aa");
+
+ assertNotMatched("a", "b/ab");
+ assertNotMatched("a", "b/ba");
+
+ assertNotMatched("a", "b/ba");
+ assertNotMatched("a", "b/ab");
+
+ assertNotMatched("a", "b/ba/");
+ assertNotMatched("a", "b/ba/b");
+
+ assertNotMatched("a", "/aa");
+ assertNotMatched("a", "aa/");
+ assertNotMatched("a", "/aa/");
+
+ assertNotMatched("/a", "b/a");
+ assertNotMatched("/a", "/b/a/");
+
+ assertNotMatched("a/", "a");
+ assertNotMatched("a/", "b/a");
+
+ assertNotMatched("/a/", "a");
+ assertNotMatched("/a/", "/a");
+ assertNotMatched("/a/", "b/a");
+ }
+
+ @Test
+ public void testSegments() {
+ assertMatched("/a/b", "a/b");
+ assertMatched("/a/b", "/a/b");
+ assertMatched("/a/b", "/a/b/");
+ assertMatched("/a/b", "/a/b/c");
+
+ assertMatched("a/b", "a/b");
+ assertMatched("a/b", "/a/b");
+ assertMatched("a/b", "/a/b/");
+ assertMatched("a/b", "/a/b/c");
+
+ assertMatched("a/b/", "a/b/");
+ assertMatched("a/b/", "/a/b/");
+ assertMatched("a/b/", "/a/b/c");
+ }
+
+ @Test
+ public void testSegmentsDoNotMatch() {
+ assertNotMatched("a/b", "/a/bb");
+ assertNotMatched("a/b", "/aa/b");
+ assertNotMatched("a/b", "a/bb");
+ assertNotMatched("a/b", "aa/b");
+ assertNotMatched("a/b", "c/aa/b");
+ assertNotMatched("a/b", "c/a/bb");
+ assertNotMatched("a/b/", "/a/b");
+ assertNotMatched("/a/b/", "/a/b");
+ assertNotMatched("/a/b", "c/a/b");
+ assertNotMatched("/a/b/", "c/a/b");
+ assertNotMatched("/a/b/", "c/a/b/");
+
+ // XXX why is it like this????
+ assertNotMatched("a/b", "c/a/b");
+ assertNotMatched("a/b", "c/a/b/");
+ assertNotMatched("a/b", "c/a/b/c");
+ assertNotMatched("a/b/", "c/a/b/");
+ assertNotMatched("a/b/", "c/a/b/c");
+ }
+
+ @SuppressWarnings("boxing")
+ @Test
+ public void testWildmatch() {
+ if (useJGitRule)
+ System.err
+ .println("IgnoreRule can't understand wildmatch rules, skipping testWildmatch!");
+
+ Boolean assume = useJGitRule;
+ assertMatched("**/a/b", "a/b", assume);
+ assertMatched("**/a/b", "c/a/b", assume);
+ assertMatched("**/a/b", "c/d/a/b", assume);
+ assertMatched("**/**/a/b", "c/d/a/b", assume);
+
+ assertMatched("/**/a/b", "a/b", assume);
+ assertMatched("/**/a/b", "c/a/b", assume);
+ assertMatched("/**/a/b", "c/d/a/b", assume);
+ assertMatched("/**/**/a/b", "c/d/a/b", assume);
+
+ assertMatched("a/b/**", "a/b", assume);
+ assertMatched("a/b/**", "a/b/c", assume);
+ assertMatched("a/b/**", "a/b/c/d/", assume);
+ assertMatched("a/b/**/**", "a/b/c/d", assume);
+
+ assertMatched("**/a/**/b", "c/d/a/b", assume);
+ assertMatched("**/a/**/b", "c/d/a/e/b", assume);
+ assertMatched("**/**/a/**/**/b", "c/d/a/e/b", assume);
+
+ assertMatched("/**/a/**/b", "c/d/a/b", assume);
+ assertMatched("/**/a/**/b", "c/d/a/e/b", assume);
+ assertMatched("/**/**/a/**/**/b", "c/d/a/e/b", assume);
+
+ assertMatched("a/**/b", "a/b", assume);
+ assertMatched("a/**/b", "a/c/b", assume);
+ assertMatched("a/**/b", "a/c/d/b", assume);
+ assertMatched("a/**/**/b", "a/c/d/b", assume);
+
+ assertMatched("a/**/b/**/c", "a/c/b/d/c", assume);
+ assertMatched("a/**/**/b/**/**/c", "a/c/b/d/c", assume);
+ }
+
+ @SuppressWarnings("boxing")
+ @Test
+ public void testWildmatchDoNotMatch() {
+ if (useJGitRule)
+ System.err
+ .println("IgnoreRule can't understand wildmatch rules, skipping testWildmatchDoNotMatch!");
+
+ Boolean assume = useJGitRule;
+ assertNotMatched("**/a/b", "a/c/b", assume);
+ assertNotMatched("!/**/*.zip", "c/a/b.zip", assume);
+ assertNotMatched("!**/*.zip", "c/a/b.zip", assume);
+ assertNotMatched("a/**/b", "a/c/bb", assume);
+ }
+
+ @SuppressWarnings("unused")
+ @Test
+ public void testSimpleRules() {
+ try {
+ new FastIgnoreRule(null);
+ fail("Illegal input allowed!");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ assertFalse(new FastIgnoreRule("/").isMatch("/", false));
+ assertFalse(new FastIgnoreRule("//").isMatch("//", false));
+ assertFalse(new FastIgnoreRule("#").isMatch("#", false));
+ assertFalse(new FastIgnoreRule("").isMatch("", false));
+ assertFalse(new FastIgnoreRule(" ").isMatch(" ", false));
+ }
+
+ @Test
+ public void testSplit() {
+ try {
+ split("/", '/').toArray();
+ fail("should not allow single slash");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ assertArrayEquals(new String[] { "a", "b" }, split("a/b", '/')
+ .toArray());
+ assertArrayEquals(new String[] { "a", "b/" }, split("a/b/", '/')
+ .toArray());
+ assertArrayEquals(new String[] { "/a", "b" }, split("/a/b", '/')
+ .toArray());
+ assertArrayEquals(new String[] { "/a", "b/" }, split("/a/b/", '/')
+ .toArray());
+ assertArrayEquals(new String[] { "/a", "b", "c" }, split("/a/b/c", '/')
+ .toArray());
+ assertArrayEquals(new String[] { "/a", "b", "c/" },
+ split("/a/b/c/", '/').toArray());
+ }
+
+ public void assertMatched(String pattern, String path, Boolean... assume) {
+ boolean match = match(pattern, path);
+ String result = path + " is " + (match ? "ignored" : "not ignored")
+ + " via '" + pattern + "' rule";
+ if (!match)
+ System.err.println(result);
+ if (assume.length == 0 || !assume[0].booleanValue())
+ assertTrue("Expected a match for: " + pattern + " with: " + path,
+ match);
+ else
+ assumeTrue("Expected a match for: " + pattern + " with: " + path,
+ match);
+
+ if (pattern.startsWith("!"))
+ pattern = pattern.substring(1);
+ else
+ pattern = "!" + pattern;
+ match = match(pattern, path);
+ if (assume.length == 0 || !assume[0].booleanValue())
+ assertFalse("Expected no match for: " + pattern + " with: " + path,
+ match);
+ else
+ assumeFalse("Expected no match for: " + pattern + " with: " + path,
+ match);
+ }
+
+ public void assertNotMatched(String pattern, String path, Boolean... assume) {
+ boolean match = match(pattern, path);
+ String result = path + " is " + (match ? "ignored" : "not ignored")
+ + " via '" + pattern + "' rule";
+ if (match)
+ System.err.println(result);
+ if (assume.length == 0 || !assume[0].booleanValue())
+ assertFalse("Expected no match for: " + pattern + " with: " + path,
+ match);
+ else
+ assumeFalse("Expected no match for: " + pattern + " with: " + path,
+ match);
+
+ if (pattern.startsWith("!"))
+ pattern = pattern.substring(1);
+ else
+ pattern = "!" + pattern;
+ match = match(pattern, path);
+ if (assume.length == 0 || !assume[0].booleanValue())
+ assertTrue("Expected a match for: " + pattern + " with: " + path,
+ match);
+ else
+ assumeTrue("Expected a match for: " + pattern + " with: " + path,
+ match);
+ }
+
+ /**
+ * Check for a match. If target ends with "/", match will assume that the
+ * target is meant to be a directory.
+ *
+ * @param pattern
+ * Pattern as it would appear in a .gitignore file
+ * @param target
+ * Target file path relative to repository's GIT_DIR
+ * @return Result of {@link FastIgnoreRule#isMatch(String, boolean)}
+ */
+ private boolean match(String pattern, String target) {
+ boolean isDirectory = target.endsWith("/");
+ if (useJGitRule.booleanValue()) {
+ IgnoreRule r = new IgnoreRule(pattern);
+ // If speed of this test is ever an issue, we can use a presetRule
+ // field
+ // to avoid recompiling a pattern each time.
+ boolean match = r.isMatch(target, isDirectory);
+ if (r.getNegation())
+ match = !match;
+ return match;
+ }
+ FastIgnoreRule r = new FastIgnoreRule(pattern);
+ // If speed of this test is ever an issue, we can use a presetRule field
+ // to avoid recompiling a pattern each time.
+ boolean match = r.isMatch(target, isDirectory);
+ if (r.getNegation())
+ match = !match;
+ return match;
+ }
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreMatcherParametrizedTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreMatcherParametrizedTest.java
new file mode 100644
index 0000000000..a51582ab3d
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreMatcherParametrizedTest.java
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2010, Red Hat Inc.
+ * 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.*;
+
+import java.util.Arrays;
+
+import org.eclipse.jgit.ignore.FastIgnoreRule;
+import org.eclipse.jgit.ignore.IgnoreRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.*;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+/**
+ * Tests ignore pattern matches
+ */
+@SuppressWarnings("deprecation")
+@RunWith(Parameterized.class)
+public class IgnoreMatcherParametrizedTest {
+
+ @Parameters(name = "JGit? {0}")
+ public static Iterable<Boolean[]> data() {
+ return Arrays.asList(new Boolean[][] { { Boolean.FALSE },
+ { Boolean.TRUE } });
+ }
+
+ @Parameter
+ public Boolean useJGitRule;
+
+ @Test
+ public void testBasic() {
+ String pattern = "/test.stp";
+ assertMatched(pattern, "/test.stp");
+
+ pattern = "#/test.stp";
+ assertNotMatched(pattern, "/test.stp");
+ }
+
+ @Test
+ public void testFileNameWildcards() {
+ // Test basic * and ? for any pattern + any character
+ String pattern = "*.st?";
+ assertMatched(pattern, "/test.stp");
+ assertMatched(pattern, "/anothertest.stg");
+ assertMatched(pattern, "/anothertest.st0");
+ assertNotMatched(pattern, "/anothertest.sta1");
+ // Check that asterisk does not expand to "/"
+ assertNotMatched(pattern, "/another/test.sta1");
+
+ // Same as above, with a leading slash to ensure that doesn't cause
+ // problems
+ pattern = "/*.st?";
+ assertMatched(pattern, "/test.stp");
+ assertMatched(pattern, "/anothertest.stg");
+ assertMatched(pattern, "/anothertest.st0");
+ assertNotMatched(pattern, "/anothertest.sta1");
+ // Check that asterisk does not expand to "/"
+ assertNotMatched(pattern, "/another/test.sta1");
+
+ // Test for numbers
+ pattern = "*.sta[0-5]";
+ assertMatched(pattern, "/test.sta5");
+ assertMatched(pattern, "/test.sta4");
+ assertMatched(pattern, "/test.sta3");
+ assertMatched(pattern, "/test.sta2");
+ assertMatched(pattern, "/test.sta1");
+ assertMatched(pattern, "/test.sta0");
+ assertMatched(pattern, "/anothertest.sta2");
+ assertNotMatched(pattern, "test.stag");
+ assertNotMatched(pattern, "test.sta6");
+
+ // Test for letters
+ pattern = "/[tv]est.sta[a-d]";
+ assertMatched(pattern, "/test.staa");
+ assertMatched(pattern, "/test.stab");
+ assertMatched(pattern, "/test.stac");
+ assertMatched(pattern, "/test.stad");
+ assertMatched(pattern, "/vest.stac");
+ assertNotMatched(pattern, "test.stae");
+ assertNotMatched(pattern, "test.sta9");
+
+ // Test child directory/file is matched
+ 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.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");
+ assertMatched(pattern, "/neb");
+ assertNotMatched(pattern, "/src/new.c");
+ }
+
+ @Test
+ public void testTargetWithoutLeadingSlash() {
+ // Test basic * and ? for any pattern + any character
+ String pattern = "/*.st?";
+ assertMatched(pattern, "test.stp");
+ assertMatched(pattern, "anothertest.stg");
+ assertMatched(pattern, "anothertest.st0");
+ assertNotMatched(pattern, "anothertest.sta1");
+ // Check that asterisk does not expand to ""
+ assertNotMatched(pattern, "another/test.sta1");
+
+ // Same as above, with a leading slash to ensure that doesn't cause
+ // problems
+ pattern = "/*.st?";
+ assertMatched(pattern, "test.stp");
+ assertMatched(pattern, "anothertest.stg");
+ assertMatched(pattern, "anothertest.st0");
+ assertNotMatched(pattern, "anothertest.sta1");
+ // Check that asterisk does not expand to ""
+ assertNotMatched(pattern, "another/test.sta1");
+
+ // Test for numbers
+ pattern = "/*.sta[0-5]";
+ assertMatched(pattern, "test.sta5");
+ assertMatched(pattern, "test.sta4");
+ assertMatched(pattern, "test.sta3");
+ assertMatched(pattern, "test.sta2");
+ assertMatched(pattern, "test.sta1");
+ assertMatched(pattern, "test.sta0");
+ assertMatched(pattern, "anothertest.sta2");
+ assertNotMatched(pattern, "test.stag");
+ assertNotMatched(pattern, "test.sta6");
+
+ // Test for letters
+ pattern = "/[tv]est.sta[a-d]";
+ assertMatched(pattern, "test.staa");
+ assertMatched(pattern, "test.stab");
+ assertMatched(pattern, "test.stac");
+ assertMatched(pattern, "test.stad");
+ assertMatched(pattern, "vest.stac");
+ assertNotMatched(pattern, "test.stae");
+ assertNotMatched(pattern, "test.sta9");
+
+ // Test child directory/file is matched
+ 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.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");
+ assertMatched(pattern, "neb");
+ assertNotMatched(pattern, "src/new.c");
+ }
+
+ @Test
+ public void testParentDirectoryGitIgnores() {
+ // Contains git ignore patterns such as might be seen in a parent
+ // directory
+
+ // Test for wildcards
+ String pattern = "/*/*.c";
+ assertMatched(pattern, "/file/a.c");
+ assertMatched(pattern, "/src/a.c");
+ assertNotMatched(pattern, "/src/new/a.c");
+
+ // Test child directory/file is matched
+ 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.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");
+ 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/b2/file.c");
+ assertNotMatched(pattern, "/src/new/a/bb1/file.c");
+ assertNotMatched(pattern, "/src/new/a/file.c");
+ }
+
+ @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");
+ assertNotMatched(pattern, "/srcA/");
+ }
+
+ @Test
+ public void testNameOnlyMatches() {
+ /*
+ * Name-only matches do not contain any path separators
+ */
+ // Test matches for file extension
+ String pattern = "*.stp";
+ assertMatched(pattern, "/test.stp");
+ assertMatched(pattern, "/src/test.stp");
+ assertNotMatched(pattern, "/test.stp1");
+ assertNotMatched(pattern, "/test.astp");
+
+ // 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");
+ 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");
+ assertNotMatched(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");
+ 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");
+ assertMatched(pattern, "/file/src");
+ assertMatched(pattern, "/src/");
+ assertMatched(pattern, "/srb/a.c");
+ assertMatched(pattern, "/grb/new/a.c");
+ assertMatched(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");
+ assertMatched(pattern, "/file/dra");
+ assertMatched(pattern, "/era/");
+ assertNotMatched(pattern, "/crg");
+ assertNotMatched(pattern, "/cr3");
+ }
+
+ @Test
+ public void testNegation() {
+ String pattern = "!/test.stp";
+ assertMatched(pattern, "/test.stp");
+ }
+
+ /**
+ * Check for a match. If target ends with "/", match will assume that the
+ * target is meant to be a directory.
+ *
+ * @param pattern
+ * Pattern as it would appear in a .gitignore file
+ * @param target
+ * Target file path relative to repository's GIT_DIR
+ */
+ public void assertMatched(String pattern, String target) {
+ boolean value = match(pattern, target);
+ assertTrue("Expected a match for: " + pattern + " with: " + target,
+ value);
+ }
+
+ /**
+ * Check for a match. If target ends with "/", match will assume that the
+ * target is meant to be a directory.
+ *
+ * @param pattern
+ * Pattern as it would appear in a .gitignore file
+ * @param target
+ * Target file path relative to repository's GIT_DIR
+ */
+ public void assertNotMatched(String pattern, String target) {
+ boolean value = match(pattern, target);
+ assertFalse("Expected no match for: " + pattern + " with: " + target,
+ value);
+ }
+
+ /**
+ * Check for a match. If target ends with "/", match will assume that the
+ * target is meant to be a directory.
+ *
+ * @param pattern
+ * Pattern as it would appear in a .gitignore file
+ * @param target
+ * Target file path relative to repository's GIT_DIR
+ * @return Result of {@link FastIgnoreRule#isMatch(String, boolean)}
+ */
+ private boolean match(String pattern, String target) {
+ boolean isDirectory = target.endsWith("/");
+ if (useJGitRule.booleanValue()) {
+ IgnoreRule r = new IgnoreRule(pattern);
+ // If speed of this test is ever an issue, we can use a presetRule
+ // field
+ // to avoid recompiling a pattern each time.
+ return r.isMatch(target, isDirectory);
+ }
+ FastIgnoreRule r = new FastIgnoreRule(pattern);
+ // If speed of this test is ever an issue, we can use a presetRule field
+ // to avoid recompiling a pattern each time.
+ return r.isMatch(target, isDirectory);
+ }
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreMatcherTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreMatcherTest.java
index aa98696b24..0713b1ad16 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreMatcherTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreMatcherTest.java
@@ -52,6 +52,7 @@ import org.junit.Test;
/**
* Tests ignore pattern matches
*/
+@SuppressWarnings("deprecation")
public class IgnoreMatcherTest {
@Test
@@ -383,12 +384,12 @@ public class IgnoreMatcherTest {
/**
* Check for a match. If target ends with "/", match will assume that the
* target is meant to be a directory.
+ *
* @param pattern
- * Pattern as it would appear in a .gitignore file
+ * Pattern as it would appear in a .gitignore file
* @param target
- * Target file path relative to repository's GIT_DIR
- * @return
- * Result of {@link IgnoreRule#isMatch(String, boolean)}
+ * Target file path relative to repository's GIT_DIR
+ * @return Result of IgnoreRule.isMatch(String, boolean)
*/
private static boolean match(String pattern, String target) {
IgnoreRule r = new IgnoreRule(pattern);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreRuleSpecialCasesTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreRuleSpecialCasesTest.java
new file mode 100644
index 0000000000..41180e70c2
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreRuleSpecialCasesTest.java
@@ -0,0 +1,904 @@
+/*
+ * Copyright (C) 2008, Florian Koeberle <florianskarten@web.de>
+ * Copyright (C) 2008, Florian Köberle <florianskarten@web.de>
+ * 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.*;
+import static org.junit.Assume.*;
+
+import java.util.Arrays;
+
+import org.eclipse.jgit.ignore.FastIgnoreRule;
+import org.eclipse.jgit.ignore.IgnoreRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.*;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+@SuppressWarnings({ "deprecation", "boxing" })
+public class IgnoreRuleSpecialCasesTest {
+
+ @Parameters(name = "JGit? {0}")
+ public static Iterable<Boolean[]> data() {
+ return Arrays.asList(new Boolean[][] { { Boolean.FALSE },
+ { Boolean.TRUE } });
+ }
+
+ @Parameter
+ public Boolean useJGitRule;
+
+ private void assertMatch(final String pattern, final String input,
+ final boolean matchExpected, Boolean... assume) {
+ boolean assumeDir = input.endsWith("/");
+ if (useJGitRule.booleanValue()) {
+ final IgnoreRule matcher = new IgnoreRule(pattern);
+ if (assume.length == 0 || !assume[0].booleanValue())
+ assertEquals(matchExpected, matcher.isMatch(input, assumeDir));
+ else
+ assumeTrue(matchExpected == matcher.isMatch(input, assumeDir));
+ } else {
+ FastIgnoreRule matcher = new FastIgnoreRule(pattern);
+ if (assume.length == 0 || !assume[0].booleanValue())
+ assertEquals(matchExpected, matcher.isMatch(input, assumeDir));
+ else
+ assumeTrue(matchExpected == matcher.isMatch(input, assumeDir));
+ }
+ }
+
+ private void assertFileNameMatch(final String pattern, final String input,
+ final boolean matchExpected) {
+ boolean assumeDir = input.endsWith("/");
+ if (useJGitRule.booleanValue()) {
+ final IgnoreRule matcher = new IgnoreRule(pattern);
+ assertEquals(matchExpected, matcher.isMatch(input, assumeDir));
+ } else {
+ FastIgnoreRule matcher = new FastIgnoreRule(pattern);
+ assertEquals(matchExpected, matcher.isMatch(input, assumeDir));
+ }
+ }
+
+ @Test
+ public void testVerySimplePatternCase0() throws Exception {
+ if (useJGitRule)
+ System.err
+ .println("IgnoreRule can't understand blank lines, skipping");
+ Boolean assume = useJGitRule;
+ assertMatch("", "", false, assume);
+ }
+
+ @Test
+ public void testVerySimplePatternCase1() throws Exception {
+ assertMatch("ab", "a", false);
+ }
+
+ @Test
+ public void testVerySimplePatternCase2() throws Exception {
+ assertMatch("ab", "ab", true);
+ }
+
+ @Test
+ public void testVerySimplePatternCase3() throws Exception {
+ assertMatch("ab", "ac", false);
+ }
+
+ @Test
+ public void testVerySimplePatternCase4() throws Exception {
+ assertMatch("ab", "abc", false);
+ }
+
+ @Test
+ public void testVerySimpleWildcardCase0() throws Exception {
+ assertMatch("?", "a", true);
+ }
+
+ @Test
+ public void testVerySimpleWildCardCase1() throws Exception {
+ assertMatch("??", "a", false);
+ }
+
+ @Test
+ public void testVerySimpleWildCardCase2() throws Exception {
+ assertMatch("??", "ab", true);
+ }
+
+ @Test
+ public void testVerySimpleWildCardCase3() throws Exception {
+ assertMatch("??", "abc", false);
+ }
+
+ @Test
+ public void testVerySimpleStarCase0() throws Exception {
+ // can't happen, but blank lines should never match
+ assertMatch("*", "", false);
+ }
+
+ @Test
+ public void testVerySimpleStarCase1() throws Exception {
+ assertMatch("*", "a", true);
+ }
+
+ @Test
+ public void testVerySimpleStarCase2() throws Exception {
+ assertMatch("*", "ab", true);
+ }
+
+ @Test
+ public void testSimpleStarCase0() throws Exception {
+ assertMatch("a*b", "a", false);
+ }
+
+ @Test
+ public void testSimpleStarCase1() throws Exception {
+ assertMatch("a*c", "ac", true);
+ }
+
+ @Test
+ public void testSimpleStarCase2() throws Exception {
+ assertMatch("a*c", "ab", false);
+ }
+
+ @Test
+ public void testSimpleStarCase3() throws Exception {
+ assertMatch("a*c", "abc", true);
+ }
+
+ @Test
+ public void testManySolutionsCase0() throws Exception {
+ assertMatch("a*a*a", "aaa", true);
+ }
+
+ @Test
+ public void testManySolutionsCase1() throws Exception {
+ assertMatch("a*a*a", "aaaa", true);
+ }
+
+ @Test
+ public void testManySolutionsCase2() throws Exception {
+ assertMatch("a*a*a", "ababa", true);
+ }
+
+ @Test
+ public void testManySolutionsCase3() throws Exception {
+ assertMatch("a*a*a", "aaaaaaaa", true);
+ }
+
+ @Test
+ public void testManySolutionsCase4() throws Exception {
+ assertMatch("a*a*a", "aaaaaaab", false);
+ }
+
+ @Test
+ public void testVerySimpleGroupCase0() throws Exception {
+ assertMatch("[ab]", "a", true);
+ }
+
+ @Test
+ public void testVerySimpleGroupCase1() throws Exception {
+ assertMatch("[ab]", "b", true);
+ }
+
+ @Test
+ public void testVerySimpleGroupCase2() throws Exception {
+ assertMatch("[ab]", "ab", false);
+ }
+
+ @Test
+ public void testVerySimpleGroupRangeCase0() throws Exception {
+ assertMatch("[b-d]", "a", false);
+ }
+
+ @Test
+ public void testVerySimpleGroupRangeCase1() throws Exception {
+ assertMatch("[b-d]", "b", true);
+ }
+
+ @Test
+ public void testVerySimpleGroupRangeCase2() throws Exception {
+ assertMatch("[b-d]", "c", true);
+ }
+
+ @Test
+ public void testVerySimpleGroupRangeCase3() throws Exception {
+ assertMatch("[b-d]", "d", true);
+ }
+
+ @Test
+ public void testVerySimpleGroupRangeCase4() throws Exception {
+ assertMatch("[b-d]", "e", false);
+ }
+
+ @Test
+ public void testVerySimpleGroupRangeCase5() throws Exception {
+ assertMatch("[b-d]", "-", false);
+ }
+
+ @Test
+ public void testTwoGroupsCase0() throws Exception {
+ assertMatch("[b-d][ab]", "bb", true);
+ }
+
+ @Test
+ public void testTwoGroupsCase1() throws Exception {
+ assertMatch("[b-d][ab]", "ca", true);
+ }
+
+ @Test
+ public void testTwoGroupsCase2() throws Exception {
+ assertMatch("[b-d][ab]", "fa", false);
+ }
+
+ @Test
+ public void testTwoGroupsCase3() throws Exception {
+ assertMatch("[b-d][ab]", "bc", false);
+ }
+
+ @Test
+ public void testTwoRangesInOneGroupCase0() throws Exception {
+ assertMatch("[b-ce-e]", "a", false);
+ }
+
+ @Test
+ public void testTwoRangesInOneGroupCase1() throws Exception {
+ assertMatch("[b-ce-e]", "b", true);
+ }
+
+ @Test
+ public void testTwoRangesInOneGroupCase2() throws Exception {
+ assertMatch("[b-ce-e]", "c", true);
+ }
+
+ @Test
+ public void testTwoRangesInOneGroupCase3() throws Exception {
+ assertMatch("[b-ce-e]", "d", false);
+ }
+
+ @Test
+ public void testTwoRangesInOneGroupCase4() throws Exception {
+ assertMatch("[b-ce-e]", "e", true);
+ }
+
+ @Test
+ public void testTwoRangesInOneGroupCase5() throws Exception {
+ assertMatch("[b-ce-e]", "f", false);
+ }
+
+ @Test
+ public void testIncompleteRangesInOneGroupCase0() throws Exception {
+ assertMatch("a[b-]", "ab", true);
+ }
+
+ @Test
+ public void testIncompleteRangesInOneGroupCase1() throws Exception {
+ assertMatch("a[b-]", "ac", false);
+ }
+
+ @Test
+ public void testIncompleteRangesInOneGroupCase2() throws Exception {
+ assertMatch("a[b-]", "a-", true);
+ }
+
+ @Test
+ public void testCombinedRangesInOneGroupCase0() throws Exception {
+ assertMatch("[a-c-e]", "b", true);
+ }
+
+ /**
+ * The c belongs to the range a-c. "-e" is no valid range so d should not
+ * match.
+ *
+ * @throws Exception
+ * for some reasons
+ */
+ @Test
+ public void testCombinedRangesInOneGroupCase1() throws Exception {
+ assertMatch("[a-c-e]", "d", false);
+ }
+
+ @Test
+ public void testCombinedRangesInOneGroupCase2() throws Exception {
+ assertMatch("[a-c-e]", "e", true);
+ }
+
+ @Test
+ public void testInversedGroupCase0() throws Exception {
+ assertMatch("[!b-c]", "a", true);
+ }
+
+ @Test
+ public void testInversedGroupCase1() throws Exception {
+ assertMatch("[!b-c]", "b", false);
+ }
+
+ @Test
+ public void testInversedGroupCase2() throws Exception {
+ assertMatch("[!b-c]", "c", false);
+ }
+
+ @Test
+ public void testInversedGroupCase3() throws Exception {
+ assertMatch("[!b-c]", "d", true);
+ }
+
+ @Test
+ public void testAlphaGroupCase0() throws Exception {
+ assertMatch("[[:alpha:]]", "d", true);
+ }
+
+ @Test
+ public void testAlphaGroupCase1() throws Exception {
+ assertMatch("[[:alpha:]]", ":", false);
+ }
+
+ @Test
+ public void testAlphaGroupCase2() throws Exception {
+ // \u00f6 = 'o' with dots on it
+ assertMatch("[[:alpha:]]", "\u00f6", true);
+ }
+
+ @Test
+ public void test2AlphaGroupsCase0() throws Exception {
+ // \u00f6 = 'o' with dots on it
+ assertMatch("[[:alpha:]][[:alpha:]]", "a\u00f6", true);
+ assertMatch("[[:alpha:]][[:alpha:]]", "a1", false);
+ }
+
+ @Test
+ public void testAlnumGroupCase0() throws Exception {
+ assertMatch("[[:alnum:]]", "a", true);
+ }
+
+ @Test
+ public void testAlnumGroupCase1() throws Exception {
+ assertMatch("[[:alnum:]]", "1", true);
+ }
+
+ @Test
+ public void testAlnumGroupCase2() throws Exception {
+ assertMatch("[[:alnum:]]", ":", false);
+ }
+
+ @Test
+ public void testBlankGroupCase0() throws Exception {
+ assertMatch("[[:blank:]]", " ", true);
+ }
+
+ @Test
+ public void testBlankGroupCase1() throws Exception {
+ assertMatch("[[:blank:]]", "\t", true);
+ }
+
+ @Test
+ public void testBlankGroupCase2() throws Exception {
+ assertMatch("[[:blank:]]", "\r", false);
+ }
+
+ @Test
+ public void testBlankGroupCase3() throws Exception {
+ assertMatch("[[:blank:]]", "\n", false);
+ }
+
+ @Test
+ public void testBlankGroupCase4() throws Exception {
+ assertMatch("[[:blank:]]", "a", false);
+ }
+
+ @Test
+ public void testCntrlGroupCase0() throws Exception {
+ assertMatch("[[:cntrl:]]", "a", false);
+ }
+
+ @Test
+ public void testCntrlGroupCase1() throws Exception {
+ assertMatch("[[:cntrl:]]", String.valueOf((char) 7), true);
+ }
+
+ @Test
+ public void testDigitGroupCase0() throws Exception {
+ assertMatch("[[:digit:]]", "0", true);
+ }
+
+ @Test
+ public void testDigitGroupCase1() throws Exception {
+ assertMatch("[[:digit:]]", "5", true);
+ }
+
+ @Test
+ public void testDigitGroupCase2() throws Exception {
+ assertMatch("[[:digit:]]", "9", true);
+ }
+
+ @Test
+ public void testDigitGroupCase3() throws Exception {
+ // \u06f9 = EXTENDED ARABIC-INDIC DIGIT NINE
+ assertMatch("[[:digit:]]", "\u06f9", true);
+ }
+
+ @Test
+ public void testDigitGroupCase4() throws Exception {
+ assertMatch("[[:digit:]]", "a", false);
+ }
+
+ @Test
+ public void testDigitGroupCase5() throws Exception {
+ assertMatch("[[:digit:]]", "]", false);
+ }
+
+ @Test
+ public void testGraphGroupCase0() throws Exception {
+ assertMatch("[[:graph:]]", "]", true);
+ }
+
+ @Test
+ public void testGraphGroupCase1() throws Exception {
+ assertMatch("[[:graph:]]", "a", true);
+ }
+
+ @Test
+ public void testGraphGroupCase2() throws Exception {
+ assertMatch("[[:graph:]]", ".", true);
+ }
+
+ @Test
+ public void testGraphGroupCase3() throws Exception {
+ assertMatch("[[:graph:]]", "0", true);
+ }
+
+ @Test
+ public void testGraphGroupCase4() throws Exception {
+ assertMatch("[[:graph:]]", " ", false);
+ }
+
+ @Test
+ public void testGraphGroupCase5() throws Exception {
+ // \u00f6 = 'o' with dots on it
+ assertMatch("[[:graph:]]", "\u00f6", true);
+ }
+
+ @Test
+ public void testLowerGroupCase0() throws Exception {
+ assertMatch("[[:lower:]]", "a", true);
+ }
+
+ @Test
+ public void testLowerGroupCase1() throws Exception {
+ assertMatch("[[:lower:]]", "h", true);
+ }
+
+ @Test
+ public void testLowerGroupCase2() throws Exception {
+ assertMatch("[[:lower:]]", "A", false);
+ }
+
+ @Test
+ public void testLowerGroupCase3() throws Exception {
+ assertMatch("[[:lower:]]", "H", false);
+ }
+
+ @Test
+ public void testLowerGroupCase4() throws Exception {
+ // \u00e4 = small 'a' with dots on it
+ assertMatch("[[:lower:]]", "\u00e4", true);
+ }
+
+ @Test
+ public void testLowerGroupCase5() throws Exception {
+ assertMatch("[[:lower:]]", ".", false);
+ }
+
+ @Test
+ public void testPrintGroupCase0() throws Exception {
+ assertMatch("[[:print:]]", "]", true);
+ }
+
+ @Test
+ public void testPrintGroupCase1() throws Exception {
+ assertMatch("[[:print:]]", "a", true);
+ }
+
+ @Test
+ public void testPrintGroupCase2() throws Exception {
+ assertMatch("[[:print:]]", ".", true);
+ }
+
+ @Test
+ public void testPrintGroupCase3() throws Exception {
+ assertMatch("[[:print:]]", "0", true);
+ }
+
+ @Test
+ public void testPrintGroupCase4() throws Exception {
+ assertMatch("[[:print:]]", " ", true);
+ }
+
+ @Test
+ public void testPrintGroupCase5() throws Exception {
+ // \u00f6 = 'o' with dots on it
+ assertMatch("[[:print:]]", "\u00f6", true);
+ }
+
+ @Test
+ public void testPunctGroupCase0() throws Exception {
+ assertMatch("[[:punct:]]", ".", true);
+ }
+
+ @Test
+ public void testPunctGroupCase1() throws Exception {
+ assertMatch("[[:punct:]]", "@", true);
+ }
+
+ @Test
+ public void testPunctGroupCase2() throws Exception {
+ assertMatch("[[:punct:]]", " ", false);
+ }
+
+ @Test
+ public void testPunctGroupCase3() throws Exception {
+ assertMatch("[[:punct:]]", "a", false);
+ }
+
+ @Test
+ public void testSpaceGroupCase0() throws Exception {
+ assertMatch("[[:space:]]", " ", true);
+ }
+
+ @Test
+ public void testSpaceGroupCase1() throws Exception {
+ assertMatch("[[:space:]]", "\t", true);
+ }
+
+ @Test
+ public void testSpaceGroupCase2() throws Exception {
+ assertMatch("[[:space:]]", "\r", true);
+ }
+
+ @Test
+ public void testSpaceGroupCase3() throws Exception {
+ assertMatch("[[:space:]]", "\n", true);
+ }
+
+ @Test
+ public void testSpaceGroupCase4() throws Exception {
+ assertMatch("[[:space:]]", "a", false);
+ }
+
+ @Test
+ public void testUpperGroupCase0() throws Exception {
+ assertMatch("[[:upper:]]", "a", false);
+ }
+
+ @Test
+ public void testUpperGroupCase1() throws Exception {
+ assertMatch("[[:upper:]]", "h", false);
+ }
+
+ @Test
+ public void testUpperGroupCase2() throws Exception {
+ assertMatch("[[:upper:]]", "A", true);
+ }
+
+ @Test
+ public void testUpperGroupCase3() throws Exception {
+ assertMatch("[[:upper:]]", "H", true);
+ }
+
+ @Test
+ public void testUpperGroupCase4() throws Exception {
+ // \u00c4 = 'A' with dots on it
+ assertMatch("[[:upper:]]", "\u00c4", true);
+ }
+
+ @Test
+ public void testUpperGroupCase5() throws Exception {
+ assertMatch("[[:upper:]]", ".", false);
+ }
+
+ @Test
+ public void testXDigitGroupCase0() throws Exception {
+ assertMatch("[[:xdigit:]]", "a", true);
+ }
+
+ @Test
+ public void testXDigitGroupCase1() throws Exception {
+ assertMatch("[[:xdigit:]]", "d", true);
+ }
+
+ @Test
+ public void testXDigitGroupCase2() throws Exception {
+ assertMatch("[[:xdigit:]]", "f", true);
+ }
+
+ @Test
+ public void testXDigitGroupCase3() throws Exception {
+ assertMatch("[[:xdigit:]]", "0", true);
+ }
+
+ @Test
+ public void testXDigitGroupCase4() throws Exception {
+ assertMatch("[[:xdigit:]]", "5", true);
+ }
+
+ @Test
+ public void testXDigitGroupCase5() throws Exception {
+ assertMatch("[[:xdigit:]]", "9", true);
+ }
+
+ @Test
+ public void testXDigitGroupCase6() throws Exception {
+ assertMatch("[[:xdigit:]]", "۹", false);
+ }
+
+ @Test
+ public void testXDigitGroupCase7() throws Exception {
+ assertMatch("[[:xdigit:]]", ".", false);
+ }
+
+ @Test
+ public void testWordGroupCase0() throws Exception {
+ assertMatch("[[:word:]]", "g", true);
+ }
+
+ @Test
+ public void testWordGroupCase1() throws Exception {
+ // \u00f6 = 'o' with dots on it
+ assertMatch("[[:word:]]", "\u00f6", true);
+ }
+
+ @Test
+ public void testWordGroupCase2() throws Exception {
+ assertMatch("[[:word:]]", "5", true);
+ }
+
+ @Test
+ public void testWordGroupCase3() throws Exception {
+ assertMatch("[[:word:]]", "_", true);
+ }
+
+ @Test
+ public void testWordGroupCase4() throws Exception {
+ assertMatch("[[:word:]]", " ", false);
+ }
+
+ @Test
+ public void testWordGroupCase5() throws Exception {
+ assertMatch("[[:word:]]", ".", false);
+ }
+
+ @Test
+ public void testMixedGroupCase0() throws Exception {
+ assertMatch("[A[:lower:]C3-5]", "A", true);
+ }
+
+ @Test
+ public void testMixedGroupCase1() throws Exception {
+ assertMatch("[A[:lower:]C3-5]", "C", true);
+ }
+
+ @Test
+ public void testMixedGroupCase2() throws Exception {
+ assertMatch("[A[:lower:]C3-5]", "e", true);
+ }
+
+ @Test
+ public void testMixedGroupCase3() throws Exception {
+ assertMatch("[A[:lower:]C3-5]", "3", true);
+ }
+
+ @Test
+ public void testMixedGroupCase4() throws Exception {
+ assertMatch("[A[:lower:]C3-5]", "4", true);
+ }
+
+ @Test
+ public void testMixedGroupCase5() throws Exception {
+ assertMatch("[A[:lower:]C3-5]", "5", true);
+ }
+
+ @Test
+ public void testMixedGroupCase6() throws Exception {
+ assertMatch("[A[:lower:]C3-5]", "B", false);
+ }
+
+ @Test
+ public void testMixedGroupCase7() throws Exception {
+ assertMatch("[A[:lower:]C3-5]", "2", false);
+ }
+
+ @Test
+ public void testMixedGroupCase8() throws Exception {
+ assertMatch("[A[:lower:]C3-5]", "6", false);
+ }
+
+ @Test
+ public void testMixedGroupCase9() throws Exception {
+ assertMatch("[A[:lower:]C3-5]", ".", false);
+ }
+
+ @Test
+ public void testSpecialGroupCase0() throws Exception {
+ assertMatch("[[]", "[", true);
+ }
+
+ @Test
+ public void testSpecialGroupCase1() throws Exception {
+ assertMatch("[]]", "]", true);
+ }
+
+ @Test
+ public void testSpecialGroupCase2() throws Exception {
+ assertMatch("[]a]", "]", true);
+ }
+
+ @Test
+ public void testSpecialGroupCase3() throws Exception {
+ assertMatch("[a[]", "[", true);
+ }
+
+ @Test
+ public void testSpecialGroupCase4() throws Exception {
+ assertMatch("[a[]", "a", true);
+ }
+
+ @Test
+ public void testSpecialGroupCase5() throws Exception {
+ assertMatch("[!]]", "]", false);
+ }
+
+ @Test
+ public void testSpecialGroupCase6() throws Exception {
+ assertMatch("[!]]", "x", true);
+ }
+
+ @Test
+ public void testSpecialGroupCase7() throws Exception {
+ assertMatch("[:]]", ":]", true);
+ }
+
+ @Test
+ public void testSpecialGroupCase8() throws Exception {
+ assertMatch("[:]]", ":", false);
+ }
+
+ @Test
+ public void testSpecialGroupCase9() throws Exception {
+ if (useJGitRule)
+ System.err.println("IgnoreRule can't understand [[:], skipping");
+ Boolean assume = useJGitRule;
+ // Second bracket is threated literally, so both [ and : should match
+ assertMatch("[[:]", ":", true, assume);
+ assertMatch("[[:]", "[", true, assume);
+ }
+
+ @Test
+ public void testUnsupportedGroupCase0() throws Exception {
+ assertMatch("[[=a=]]", "a", false);
+ assertMatch("[[=a=]]", "=", false);
+ assertMatch("[=a=]", "a", true);
+ assertMatch("[=a=]", "=", true);
+ }
+
+ @Test
+ public void testUnsupportedGroupCase01() throws Exception {
+ assertMatch("[.a.]*[.a.]", "aha", true);
+ }
+
+ @Test
+ public void testUnsupportedGroupCase1() throws Exception {
+ assertMatch("[[.a.]]", "a", false);
+ assertMatch("[[.a.]]", ".", false);
+ assertMatch("[.a.]", "a", true);
+ assertMatch("[.a.]", ".", true);
+ }
+
+ @Test
+ public void testEscapedBracket1() throws Exception {
+ assertMatch("\\[", "[", true);
+ }
+
+ @Test
+ public void testEscapedBracket2() throws Exception {
+ assertMatch("\\[[a]", "[", false);
+ }
+
+ @Test
+ public void testEscapedBracket3() throws Exception {
+ assertMatch("\\[[a]", "a", false);
+ }
+
+ @Test
+ public void testEscapedBracket4() throws Exception {
+ assertMatch("\\[[a]", "[a", true);
+ }
+
+ @Test
+ public void testEscapedBracket5() throws Exception {
+ assertMatch("[a\\]]", "]", true);
+ }
+
+ @Test
+ public void testEscapedBracket6() throws Exception {
+ assertMatch("[a\\]]", "a", true);
+ }
+
+ @Test
+ public void testEscapedBackslash() throws Exception {
+ if (useJGitRule)
+ System.err
+ .println("IgnoreRule can't understand escaped backslashes, skipping");
+ Boolean assume = useJGitRule;
+ // In Git CLI a\\b matches a\b file
+ assertMatch("a\\\\b", "a\\b", true, assume);
+ }
+
+ @Test
+ public void testMultipleEscapedCharacters1() throws Exception {
+ assertMatch("\\]a?c\\*\\[d\\?\\]", "]abc*[d?]", true);
+ }
+
+ @Test
+ public void testFilePathSimpleCase() throws Exception {
+ assertFileNameMatch("a/b", "a/b", true);
+ }
+
+ @Test
+ public void testFilePathCase0() throws Exception {
+ assertFileNameMatch("a*b", "a/b", false);
+ }
+
+ @Test
+ public void testFilePathCase1() throws Exception {
+ assertFileNameMatch("a?b", "a/b", false);
+ }
+
+ @Test
+ public void testFilePathCase2() throws Exception {
+ assertFileNameMatch("a*b", "a\\b", true);
+ }
+
+ @Test
+ public void testFilePathCase3() throws Exception {
+ assertFileNameMatch("a?b", "a\\b", true);
+ }
+
+} \ No newline at end of file