Browse Source
Was replaced by FastIgnoreRule in 3.6 Change-Id: Ia9c3d1231a5d97f3f5bddc81113954c9f9d8ee1e Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>stable-4.1
Matthias Sohn
10 years ago
6 changed files with 72 additions and 880 deletions
@ -1,400 +0,0 @@ |
|||||||
/* |
|
||||||
* 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.assertEquals; |
|
||||||
import static org.junit.Assert.assertFalse; |
|
||||||
import static org.junit.Assert.assertTrue; |
|
||||||
|
|
||||||
import org.junit.Test; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Tests ignore pattern matches |
|
||||||
*/ |
|
||||||
@SuppressWarnings("deprecation") |
|
||||||
public class IgnoreMatcherTest { |
|
||||||
|
|
||||||
@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"); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testGetters() { |
|
||||||
IgnoreRule r = new IgnoreRule("/pattern/"); |
|
||||||
assertFalse(r.getNameOnly()); |
|
||||||
assertTrue(r.dirOnly()); |
|
||||||
assertFalse(r.getNegation()); |
|
||||||
assertEquals(r.getPattern(), "/pattern"); |
|
||||||
|
|
||||||
r = new IgnoreRule("/patter?/"); |
|
||||||
assertFalse(r.getNameOnly()); |
|
||||||
assertTrue(r.dirOnly()); |
|
||||||
assertFalse(r.getNegation()); |
|
||||||
assertEquals(r.getPattern(), "/patter?"); |
|
||||||
|
|
||||||
r = new IgnoreRule("patt*"); |
|
||||||
assertTrue(r.getNameOnly()); |
|
||||||
assertFalse(r.dirOnly()); |
|
||||||
assertFalse(r.getNegation()); |
|
||||||
assertEquals(r.getPattern(), "patt*"); |
|
||||||
|
|
||||||
r = new IgnoreRule("pattern"); |
|
||||||
assertTrue(r.getNameOnly()); |
|
||||||
assertFalse(r.dirOnly()); |
|
||||||
assertFalse(r.getNegation()); |
|
||||||
assertEquals(r.getPattern(), "pattern"); |
|
||||||
|
|
||||||
r = new IgnoreRule("!pattern"); |
|
||||||
assertTrue(r.getNameOnly()); |
|
||||||
assertFalse(r.dirOnly()); |
|
||||||
assertTrue(r.getNegation()); |
|
||||||
assertEquals(r.getPattern(), "pattern"); |
|
||||||
|
|
||||||
r = new IgnoreRule("!/pattern"); |
|
||||||
assertFalse(r.getNameOnly()); |
|
||||||
assertFalse(r.dirOnly()); |
|
||||||
assertTrue(r.getNegation()); |
|
||||||
assertEquals(r.getPattern(), "/pattern"); |
|
||||||
|
|
||||||
r = new IgnoreRule("!/patter?"); |
|
||||||
assertFalse(r.getNameOnly()); |
|
||||||
assertFalse(r.dirOnly()); |
|
||||||
assertTrue(r.getNegation()); |
|
||||||
assertEquals(r.getPattern(), "/patter?"); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testResetState() { |
|
||||||
String pattern = "/build/*"; |
|
||||||
String target = "/build"; |
|
||||||
// Don't use the assert methods of this class, as we want to test
|
|
||||||
// whether the state in IgnoreRule is reset properly
|
|
||||||
IgnoreRule r = new IgnoreRule(pattern); |
|
||||||
// Result should be the same for the same inputs
|
|
||||||
assertFalse(r.isMatch(target, true)); |
|
||||||
assertFalse(r.isMatch(target, true)); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 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 IgnoreRule.isMatch(String, boolean) |
|
||||||
*/ |
|
||||||
private static boolean match(String pattern, String target) { |
|
||||||
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, target.endsWith("/")); |
|
||||||
} |
|
||||||
} |
|
@ -1,278 +0,0 @@ |
|||||||
/* |
|
||||||
* 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 org.eclipse.jgit.errors.InvalidPatternException; |
|
||||||
import org.eclipse.jgit.fnmatch.FileNameMatcher; |
|
||||||
|
|
||||||
/** |
|
||||||
* A single ignore rule corresponding to one line in a .gitignore or ignore |
|
||||||
* file. Parses the ignore pattern |
|
||||||
* |
|
||||||
* Inspiration from: Ferry Huberts |
|
||||||
* |
|
||||||
* @deprecated this rule does not support double star pattern and is slow |
|
||||||
* parsing glob expressions. Consider to use {@link FastIgnoreRule} |
|
||||||
* instead. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=440732
|
|
||||||
*/ |
|
||||||
@Deprecated |
|
||||||
public class IgnoreRule { |
|
||||||
private String pattern; |
|
||||||
private boolean negation; |
|
||||||
private boolean nameOnly; |
|
||||||
private boolean dirOnly; |
|
||||||
private FileNameMatcher matcher; |
|
||||||
|
|
||||||
/** |
|
||||||
* Create a new ignore rule with the given pattern. Assumes that |
|
||||||
* the pattern is already trimmed. |
|
||||||
* |
|
||||||
* @param pattern |
|
||||||
* Base pattern for the ignore rule. This pattern will |
|
||||||
* be parsed to generate rule parameters. |
|
||||||
*/ |
|
||||||
public IgnoreRule (String pattern) { |
|
||||||
this.pattern = pattern; |
|
||||||
negation = false; |
|
||||||
nameOnly = false; |
|
||||||
dirOnly = false; |
|
||||||
matcher = null; |
|
||||||
setup(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Remove leading/trailing characters as needed. Set up |
|
||||||
* rule variables for later matching. |
|
||||||
*/ |
|
||||||
private void setup() { |
|
||||||
int startIndex = 0; |
|
||||||
int endIndex = pattern.length(); |
|
||||||
if (pattern.startsWith("!")) { //$NON-NLS-1$
|
|
||||||
startIndex++; |
|
||||||
negation = true; |
|
||||||
} |
|
||||||
|
|
||||||
if (pattern.endsWith("/")) { //$NON-NLS-1$
|
|
||||||
endIndex --; |
|
||||||
dirOnly = true; |
|
||||||
} |
|
||||||
|
|
||||||
pattern = pattern.substring(startIndex, endIndex); |
|
||||||
boolean hasSlash = pattern.contains("/"); //$NON-NLS-1$
|
|
||||||
|
|
||||||
if (!hasSlash) |
|
||||||
nameOnly = true; |
|
||||||
else if (!pattern.startsWith("/")) { //$NON-NLS-1$
|
|
||||||
//Contains "/" but does not start with one
|
|
||||||
//Adding / to the start should not interfere with matching
|
|
||||||
pattern = "/" + pattern; //$NON-NLS-1$
|
|
||||||
} |
|
||||||
|
|
||||||
if (pattern.contains("*") || pattern.contains("?") || pattern.contains("[")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
|
||||||
try { |
|
||||||
matcher = new FileNameMatcher(pattern, Character.valueOf('/')); |
|
||||||
} catch (InvalidPatternException e) { |
|
||||||
// Ignore pattern exceptions
|
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @return |
|
||||||
* True if the pattern is just a file name and not a path |
|
||||||
*/ |
|
||||||
public boolean getNameOnly() { |
|
||||||
return nameOnly; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* |
|
||||||
* @return |
|
||||||
* True if the pattern should match directories only |
|
||||||
*/ |
|
||||||
public boolean dirOnly() { |
|
||||||
return dirOnly; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* |
|
||||||
* @return |
|
||||||
* True if the pattern had a "!" in front of it |
|
||||||
*/ |
|
||||||
public boolean getNegation() { |
|
||||||
return negation; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* @return |
|
||||||
* The blob pattern to be used as a matcher |
|
||||||
*/ |
|
||||||
public String getPattern() { |
|
||||||
return pattern; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Returns true if a match was made. |
|
||||||
* <br> |
|
||||||
* This function does NOT return the actual ignore status of the |
|
||||||
* target! Please consult {@link #getResult()} for the ignore status. The actual |
|
||||||
* ignore status may be true or false depending on whether this rule is |
|
||||||
* an ignore rule or a negation rule. |
|
||||||
* |
|
||||||
* @param target |
|
||||||
* Name pattern of the file, relative to the base directory of this rule |
|
||||||
* @param isDirectory |
|
||||||
* Whether the target file is a directory or not |
|
||||||
* @return |
|
||||||
* True if a match was made. This does not necessarily mean that |
|
||||||
* the target is ignored. Call {@link IgnoreRule#getResult() getResult()} for the result. |
|
||||||
*/ |
|
||||||
public boolean isMatch(String target, boolean isDirectory) { |
|
||||||
if (!target.startsWith("/")) //$NON-NLS-1$
|
|
||||||
target = "/" + target; //$NON-NLS-1$
|
|
||||||
|
|
||||||
if (matcher == null) { |
|
||||||
if (target.equals(pattern)) { |
|
||||||
//Exact match
|
|
||||||
if (dirOnly && !isDirectory) |
|
||||||
//Directory expectations not met
|
|
||||||
return false; |
|
||||||
else |
|
||||||
//Directory expectations met
|
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
/* |
|
||||||
* Add slashes for startsWith check. This avoids matching e.g. |
|
||||||
* "/src/new" to /src/newfile" but allows "/src/new" to match |
|
||||||
* "/src/new/newfile", as is the git standard |
|
||||||
*/ |
|
||||||
if ((target).startsWith(pattern + "/")) //$NON-NLS-1$
|
|
||||||
return true; |
|
||||||
|
|
||||||
if (nameOnly) { |
|
||||||
//Iterate through each sub-name
|
|
||||||
final String[] segments = target.split("/"); //$NON-NLS-1$
|
|
||||||
for (int idx = 0; idx < segments.length; idx++) { |
|
||||||
final String segmentName = segments[idx]; |
|
||||||
// String.split("/") creates empty segment for leading slash
|
|
||||||
if (segmentName.length() == 0) |
|
||||||
continue; |
|
||||||
if (segmentName.equals(pattern) && |
|
||||||
doesMatchDirectoryExpectations(isDirectory, idx, segments.length)) |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} else { |
|
||||||
matcher.reset(); |
|
||||||
matcher.append(target); |
|
||||||
if (matcher.isMatch()) |
|
||||||
return true; |
|
||||||
|
|
||||||
final String[] segments = target.split("/"); //$NON-NLS-1$
|
|
||||||
if (nameOnly) { |
|
||||||
for (int idx = 0; idx < segments.length; idx++) { |
|
||||||
final String segmentName = segments[idx]; |
|
||||||
// String.split("/") creates empty segment for leading slash
|
|
||||||
if (segmentName.length() == 0) |
|
||||||
continue; |
|
||||||
//Iterate through each sub-directory
|
|
||||||
matcher.reset(); |
|
||||||
matcher.append(segmentName); |
|
||||||
if (matcher.isMatch() && |
|
||||||
doesMatchDirectoryExpectations(isDirectory, idx, segments.length)) |
|
||||||
return true; |
|
||||||
} |
|
||||||
} else { |
|
||||||
//TODO: This is the slowest operation
|
|
||||||
//This matches e.g. "/src/ne?" to "/src/new/file.c"
|
|
||||||
matcher.reset(); |
|
||||||
|
|
||||||
for (int idx = 0; idx < segments.length; idx++) { |
|
||||||
final String segmentName = segments[idx]; |
|
||||||
// String.split("/") creates empty segment for leading slash
|
|
||||||
if (segmentName.length() == 0) |
|
||||||
continue; |
|
||||||
|
|
||||||
matcher.append("/" + segmentName); //$NON-NLS-1$
|
|
||||||
|
|
||||||
if (matcher.isMatch() |
|
||||||
&& doesMatchDirectoryExpectations(isDirectory, idx, |
|
||||||
segments.length)) |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* If a call to <code>isMatch(String, boolean)</code> was previously |
|
||||||
* made, this will return whether or not the target was ignored. Otherwise |
|
||||||
* this just indicates whether the rule is non-negation or negation. |
|
||||||
* |
|
||||||
* @return |
|
||||||
* True if the target is to be ignored, false otherwise. |
|
||||||
*/ |
|
||||||
public boolean getResult() { |
|
||||||
return !negation; |
|
||||||
} |
|
||||||
|
|
||||||
private boolean doesMatchDirectoryExpectations(boolean isDirectory, int segmentIdx, int segmentLength) { |
|
||||||
// The segment we are checking is a directory, expectations are met.
|
|
||||||
if (segmentIdx < segmentLength - 1) { |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
// We are checking the last part of the segment for which isDirectory has to be considered.
|
|
||||||
return !dirOnly || isDirectory; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public String toString() { |
|
||||||
return pattern; |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue