123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523 |
- /*
- * 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.assertArrayEquals;
- import static org.junit.Assert.assertFalse;
- import static org.junit.Assert.assertTrue;
- import static org.junit.Assert.fail;
-
- import org.junit.Test;
-
- public class FastIgnoreRuleTest {
-
- @Test
- public void testSimpleCharClass() {
- assertMatched("][a]", "]a");
- assertMatched("[a]", "a");
- 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 testTrailingSpaces() {
- assertMatched("a ", "a");
- assertMatched("a/ ", "a/");
- assertMatched("a/ ", "a/b");
- assertMatched("a/\\ ", "a/ ");
- assertNotMatched("a/\\ ", "a/");
- assertNotMatched("a/\\ ", "a/b");
- assertNotMatched("/ ", "a");
- }
-
- @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");
- }
-
- @Test
- public void testWildmatch() {
- assertMatched("**/a/b", "a/b");
- assertMatched("**/a/b", "c/a/b");
- assertMatched("**/a/b", "c/d/a/b");
- assertMatched("**/**/a/b", "c/d/a/b");
-
- assertMatched("/**/a/b", "a/b");
- assertMatched("/**/a/b", "c/a/b");
- assertMatched("/**/a/b", "c/d/a/b");
- assertMatched("/**/**/a/b", "c/d/a/b");
-
- assertMatched("a/b/**", "a/b");
- assertMatched("a/b/**", "a/b/c");
- assertMatched("a/b/**", "a/b/c/d/");
- assertMatched("a/b/**/**", "a/b/c/d");
-
- assertMatched("**/a/**/b", "c/d/a/b");
- assertMatched("**/a/**/b", "c/d/a/e/b");
- assertMatched("**/**/a/**/**/b", "c/d/a/e/b");
-
- assertMatched("/**/a/**/b", "c/d/a/b");
- assertMatched("/**/a/**/b", "c/d/a/e/b");
- assertMatched("/**/**/a/**/**/b", "c/d/a/e/b");
-
- assertMatched("a/**/b", "a/b");
- assertMatched("a/**/b", "a/c/b");
- assertMatched("a/**/b", "a/c/d/b");
- assertMatched("a/**/**/b", "a/c/d/b");
-
- assertMatched("a/**/b/**/c", "a/c/b/d/c");
- assertMatched("a/**/**/b/**/**/c", "a/c/b/d/c");
- }
-
- @Test
- public void testWildmatchDoNotMatch() {
- assertNotMatched("**/a/b", "a/c/b");
- assertNotMatched("!/**/*.zip", "c/a/b.zip");
- assertNotMatched("!**/*.zip", "c/a/b.zip");
- assertNotMatched("a/**/b", "a/c/bb");
- }
-
- @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 match = match(pattern, path);
- String result = path + " is " + (match ? "ignored" : "not ignored")
- + " via '" + pattern + "' rule";
- if (!match) {
- System.err.println(result);
- }
- assertTrue("Expected a match for: " + pattern + " with: " + path,
- match);
-
- if (pattern.startsWith("!")) {
- pattern = pattern.substring(1);
- } else {
- pattern = "!" + pattern;
- }
- match = match(pattern, path);
- assertFalse("Expected no match for: " + pattern + " with: " + path,
- match);
- }
-
- public void assertNotMatched(String pattern, String path) {
- boolean match = match(pattern, path);
- String result = path + " is " + (match ? "ignored" : "not ignored")
- + " via '" + pattern + "' rule";
- if (match) {
- System.err.println(result);
- }
- assertFalse("Expected no match for: " + pattern + " with: " + path,
- match);
-
- if (pattern.startsWith("!")) {
- pattern = pattern.substring(1);
- } else {
- pattern = "!" + pattern;
- }
- match = match(pattern, path);
- assertTrue("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("/");
- 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;
- }
- }
|