Browse Source

Added characters to be escaped in file name patterns

Originally, characters could not be escaped in FileNameMatcher patterns.
This breaks file name matching when escaped brackets "\[" and "\]" are
used in the pattern. A fix has been implemented to allow for any
character to be escaped by prepending it with a '\'

Bug: 340715
Change-Id: Ie46fd211931fa09ef3a6a712bd1da3d7fb64c5e3
Signed-off-by: Gustav Karlsson <gustav.karlsson@tieto.com>
stable-3.1
Gustav Karlsson 12 years ago
parent
commit
b3e9626743
  1. 40
      org.eclipse.jgit.test/tst/org/eclipse/jgit/fnmatch/FileNameMatcherTest.java
  2. 64
      org.eclipse.jgit/src/org/eclipse/jgit/fnmatch/FileNameMatcher.java

40
org.eclipse.jgit.test/tst/org/eclipse/jgit/fnmatch/FileNameMatcherTest.java

@ -801,6 +801,46 @@ public class FileNameMatcherTest {
} }
} }
@Test
public void testEscapedBracket1() throws Exception {
assertMatch("\\[", "[", true, false);
}
@Test
public void testEscapedBracket2() throws Exception {
assertMatch("\\[[a]", "[", false, true);
}
@Test
public void testEscapedBracket3() throws Exception {
assertMatch("\\[[a]", "a", false, false);
}
@Test
public void testEscapedBracket4() throws Exception {
assertMatch("\\[[a]", "[a", true, false);
}
@Test
public void testEscapedBracket5() throws Exception {
assertMatch("[a\\]]", "]", true, false);
}
@Test
public void testEscapedBracket6() throws Exception {
assertMatch("[a\\]]", "a", true, false);
}
@Test
public void testEscapedBackslash() throws Exception {
assertMatch("a\\\\b", "a\\b", true, false);
}
@Test
public void testMultipleEscapedCharacters1() throws Exception {
assertMatch("\\]a?c\\*\\[d\\?\\]", "]abc*[d?]", true, false);
}
@Test @Test
public void testFilePathSimpleCase() throws Exception { public void testFilePathSimpleCase() throws Exception {
assertFileNameMatch("a/b", "a/b", '/', true, false); assertFileNameMatch("a/b", "a/b", '/', true, false);

64
org.eclipse.jgit/src/org/eclipse/jgit/fnmatch/FileNameMatcher.java

@ -60,9 +60,9 @@ import org.eclipse.jgit.errors.NoClosingBracketException;
* <p> * <p>
* Supported are the wildcard characters * and ? and groups with: * Supported are the wildcard characters * and ? and groups with:
* <ul> * <ul>
* <li> characters e.g. [abc]</li> * <li>characters e.g. [abc]</li>
* <li> ranges e.g. [a-z]</li> * <li>ranges e.g. [a-z]</li>
* <li> the following character classes * <li>the following character classes
* <ul> * <ul>
* <li>[:alnum:]</li> * <li>[:alnum:]</li>
* <li>[:alpha:]</li> * <li>[:alpha:]</li>
@ -78,9 +78,10 @@ import org.eclipse.jgit.errors.NoClosingBracketException;
* <li>[:word:]</li> * <li>[:word:]</li>
* <li>[:xdigit:]</li> * <li>[:xdigit:]</li>
* </ul> * </ul>
* e. g. [[:xdigit:]] </li> * e. g. [[:xdigit:]]</li>
* </ul> * </ul>
* </p> * </p>
* Any character can be escaped by prepending it with a \
*/ */
public class FileNameMatcher { public class FileNameMatcher {
static final List<Head> EMPTY_HEAD_LIST = Collections.emptyList(); static final List<Head> EMPTY_HEAD_LIST = Collections.emptyList();
@ -199,7 +200,7 @@ public class FileNameMatcher {
int groupEnd = -1; int groupEnd = -1;
while (groupEnd == -1) { while (groupEnd == -1) {
final int possibleGroupEnd = pattern.indexOf(']', final int possibleGroupEnd = indexOfUnescaped(pattern, ']',
firstValidEndBracketIndex); firstValidEndBracketIndex);
if (possibleGroupEnd == -1) if (possibleGroupEnd == -1)
throw new NoClosingBracketException(indexOfStartBracket, "[", //$NON-NLS-1$ throw new NoClosingBracketException(indexOfStartBracket, "[", //$NON-NLS-1$
@ -238,7 +239,7 @@ public class FileNameMatcher {
int currentIndex = 0; int currentIndex = 0;
List<AbstractHead> heads = new ArrayList<AbstractHead>(); List<AbstractHead> heads = new ArrayList<AbstractHead>();
while (currentIndex < pattern.length()) { while (currentIndex < pattern.length()) {
final int groupStart = pattern.indexOf('[', currentIndex); final int groupStart = indexOfUnescaped(pattern, '[', currentIndex);
if (groupStart == -1) { if (groupStart == -1) {
final String patternPart = pattern.substring(currentIndex); final String patternPart = pattern.substring(currentIndex);
heads.addAll(createSimpleHeads(patternPart, heads.addAll(createSimpleHeads(patternPart,
@ -264,24 +265,35 @@ public class FileNameMatcher {
final String patternPart, final Character invalidWildgetCharacter) { final String patternPart, final Character invalidWildgetCharacter) {
final List<AbstractHead> heads = new ArrayList<AbstractHead>( final List<AbstractHead> heads = new ArrayList<AbstractHead>(
patternPart.length()); patternPart.length());
boolean escaped = false;
for (int i = 0; i < patternPart.length(); i++) { for (int i = 0; i < patternPart.length(); i++) {
final char c = patternPart.charAt(i); final char c = patternPart.charAt(i);
switch (c) { if (escaped) {
case '*': {
final AbstractHead head = createWildCardHead(
invalidWildgetCharacter, true);
heads.add(head);
break;
}
case '?': {
final AbstractHead head = createWildCardHead(
invalidWildgetCharacter, false);
heads.add(head);
break;
}
default:
final CharacterHead head = new CharacterHead(c); final CharacterHead head = new CharacterHead(c);
heads.add(head); heads.add(head);
escaped = false;
} else {
switch (c) {
case '*': {
final AbstractHead head = createWildCardHead(
invalidWildgetCharacter, true);
heads.add(head);
break;
}
case '?': {
final AbstractHead head = createWildCardHead(
invalidWildgetCharacter, false);
heads.add(head);
break;
}
case '\\':
escaped = true;
break;
default:
final CharacterHead head = new CharacterHead(c);
heads.add(head);
}
} }
} }
return heads; return heads;
@ -317,6 +329,18 @@ public class FileNameMatcher {
heads = newHeads; heads = newHeads;
} }
private static int indexOfUnescaped(final String searchString,
final char ch, final int fromIndex) {
for (int i = fromIndex; i < searchString.length(); i++) {
char current = searchString.charAt(i);
if (current == ch)
return i;
if (current == '\\')
i++; // Skip the next char as it is escaped }
}
return -1;
}
/** /**
* *
* @param stringToMatch * @param stringToMatch

Loading…
Cancel
Save