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 index d8a617447..a6e48feea 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/BasicRuleTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/BasicRuleTest.java @@ -47,6 +47,7 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; +import org.eclipse.jgit.ignore.internal.Strings; import org.junit.Test; public class BasicRuleTest { @@ -73,4 +74,31 @@ public void test() { assertNotEquals(rule1.toString(), rule3.toString()); } + @Test + public void testDirectoryPattern() { + assertTrue(Strings.isDirectoryPattern("/")); + assertTrue(Strings.isDirectoryPattern("/ ")); + assertTrue(Strings.isDirectoryPattern("/ ")); + assertFalse(Strings.isDirectoryPattern(" ")); + assertFalse(Strings.isDirectoryPattern("")); + } + + @Test + public void testStripTrailingChar() { + assertEquals("", Strings.stripTrailing("/", '/')); + assertEquals("", Strings.stripTrailing("///", '/')); + assertEquals("a", Strings.stripTrailing("a/", '/')); + assertEquals("a", Strings.stripTrailing("a///", '/')); + assertEquals("a/ ", Strings.stripTrailing("a/ ", '/')); + } + + @Test + public void testStripTrailingWhitespace() { + assertEquals("", Strings.stripTrailingWhitespace("")); + assertEquals("", Strings.stripTrailingWhitespace(" ")); + assertEquals("a", Strings.stripTrailingWhitespace("a")); + assertEquals("a", Strings.stripTrailingWhitespace("a ")); + assertEquals("a", Strings.stripTrailingWhitespace("a ")); + assertEquals("a", Strings.stripTrailingWhitespace("a \t")); + } } 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 index 480e32650..1863b8032 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/FastIgnoreRuleTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/FastIgnoreRuleTest.java @@ -122,6 +122,17 @@ public void testCharClass() { 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"); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreNodeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreNodeTest.java index c026efcde..4a7dcd535 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreNodeTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreNodeTest.java @@ -480,8 +480,9 @@ public void testTrailingSpaces() throws IOException { writeTrashFile("a/a", ""); writeTrashFile("a/a ", ""); writeTrashFile("a/a ", ""); + writeTrashFile("b/c", ""); - writeIgnoreFile(".gitignore", "a\\ ", "a \\ "); + writeIgnoreFile(".gitignore", "a\\ ", "a \\ ", "b/ "); beginWalk(); assertEntry(F, tracked, ".gitignore"); @@ -497,6 +498,8 @@ public void testTrailingSpaces() throws IOException { assertEntry(F, tracked, "a/a"); assertEntry(F, ignored, "a/a "); assertEntry(F, ignored, "a/a "); + assertEntry(D, ignored, "b"); + assertEntry(F, ignored, "b/c"); endWalk(); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/ignore/FastIgnoreRule.java b/org.eclipse.jgit/src/org/eclipse/jgit/ignore/FastIgnoreRule.java index e376cbba5..eb081adb1 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/ignore/FastIgnoreRule.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/ignore/FastIgnoreRule.java @@ -43,6 +43,8 @@ package org.eclipse.jgit.ignore; import static org.eclipse.jgit.ignore.internal.Strings.stripTrailing; +import static org.eclipse.jgit.ignore.internal.Strings.stripTrailingWhitespace; +import static org.eclipse.jgit.ignore.internal.Strings.isDirectoryPattern; import static org.eclipse.jgit.ignore.internal.IMatcher.NO_MATCH; import org.eclipse.jgit.errors.InvalidPatternException; import org.eclipse.jgit.ignore.internal.IMatcher; @@ -111,8 +113,9 @@ public FastIgnoreRule(String pattern) { pattern = pattern.substring(1); } } - dirOnly = pattern.charAt(pattern.length() - 1) == PATH_SEPARATOR; + dirOnly = isDirectoryPattern(pattern); if (dirOnly) { + pattern = stripTrailingWhitespace(pattern); pattern = stripTrailing(pattern, PATH_SEPARATOR); if (pattern.length() == 0) { this.matcher = NO_MATCH; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/ignore/internal/Strings.java b/org.eclipse.jgit/src/org/eclipse/jgit/ignore/internal/Strings.java index e354c7114..70c519903 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/ignore/internal/Strings.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/ignore/internal/Strings.java @@ -76,10 +76,50 @@ static char getPathSeparator(Character pathSeparator) { * @return new string with all trailing characters removed */ public static String stripTrailing(String pattern, char c) { - while (pattern.length() > 0 - && pattern.charAt(pattern.length() - 1) == c) - pattern = pattern.substring(0, pattern.length() - 1); - return pattern; + for (int i = pattern.length() - 1; i >= 0; i--) { + char charAt = pattern.charAt(i); + if (charAt != c) { + if (i == pattern.length() - 1) { + return pattern; + } + return pattern.substring(0, i + 1); + } + } + return ""; //$NON-NLS-1$ + } + + /** + * @param pattern + * non null + * @return new string with all trailing whitespace removed + */ + public static String stripTrailingWhitespace(String pattern) { + for (int i = pattern.length() - 1; i >= 0; i--) { + char charAt = pattern.charAt(i); + if (!Character.isWhitespace(charAt)) { + if (i == pattern.length() - 1) { + return pattern; + } + return pattern.substring(0, i + 1); + } + } + return ""; //$NON-NLS-1$ + } + + /** + * @param pattern + * non null + * @return true if the last character, which is not whitespace, is a path + * separator + */ + public static boolean isDirectoryPattern(String pattern) { + for (int i = pattern.length() - 1; i >= 0; i--) { + char charAt = pattern.charAt(i); + if (!Character.isWhitespace(charAt)) { + return charAt == FastIgnoreRule.PATH_SEPARATOR; + } + } + return false; } static int count(String s, char c, boolean ignoreFirstLast) {