From 97ef1fe89369422ca430b47e0b53277b94bfbc29 Mon Sep 17 00:00:00 2001 From: Andrey Loskutov Date: Tue, 22 Sep 2015 16:42:14 +0200 Subject: [PATCH] Properly support special regex characters in ignore rules Ignore rules should escape $^(){}+| chars if using regular expressions, because they should be treated literally if they aren't part of a character group. Bug: 478055 Change-Id: Ic7276442d7f8f02594b85eae1ef697362e62d3bd Signed-off-by: Andrey Loskutov --- .../ignore/IgnoreRuleSpecialCasesTest.java | 78 +++++++++++++++++++ .../eclipse/jgit/ignore/internal/Strings.java | 16 +++- 2 files changed, 93 insertions(+), 1 deletion(-) 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 index 05443d60c..ec4a1f1c6 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreRuleSpecialCasesTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreRuleSpecialCasesTest.java @@ -868,6 +868,84 @@ public class IgnoreRuleSpecialCasesTest { assertMatch("\\]a?c\\*\\[d\\?\\]", "]abc*[d?]", true); } + @Test + public void testDollar() throws Exception { + assertMatch("$", "$", true); + assertMatch("$x", "$x", true); + assertMatch("$x", "x$", false); + assertMatch("$x", "$", false); + + assertMatch("$x.*", "$x.a", true); + assertMatch("*$", "x$", true); + assertMatch("*.$", "x.$", true); + + assertMatch("$*x", "$ax", true); + assertMatch("x*$", "xa$", true); + assertMatch("x*$", "xa", false); + assertMatch("[a$b]", "$", true); + } + + @Test + public void testCaret() throws Exception { + assertMatch("^", "^", true); + assertMatch("^x", "^x", true); + assertMatch("^x", "x^", false); + assertMatch("^x", "^", false); + + assertMatch("^x.*", "^x.a", true); + assertMatch("*^", "x^", true); + assertMatch("*.^", "x.^", true); + + assertMatch("x*^", "xa^", true); + assertMatch("^*x", "^ax", true); + assertMatch("^*x", "ax", false); + assertMatch("[a^b]", "^", true); + } + + @Test + public void testPlus() throws Exception { + assertMatch("+", "+", true); + assertMatch("+x", "+x", true); + assertMatch("+x", "x+", false); + assertMatch("+x", "+", false); + assertMatch("x+", "xx", false); + + assertMatch("+x.*", "+x.a", true); + assertMatch("*+", "x+", true); + assertMatch("*.+", "x.+", true); + + assertMatch("x*+", "xa+", true); + assertMatch("+*x", "+ax", true); + assertMatch("+*x", "ax", false); + assertMatch("[a+b]", "+", true); + } + + @Test + public void testPipe() throws Exception { + assertMatch("|", "|", true); + assertMatch("|x", "|x", true); + assertMatch("|x", "x|", false); + assertMatch("|x", "|", false); + assertMatch("x|x", "xx", false); + + assertMatch("x|x.*", "x|x.a", true); + assertMatch("*|", "x|", true); + assertMatch("*.|", "x.|", true); + + assertMatch("x*|a", "xb|a", true); + assertMatch("b|*x", "b|ax", true); + assertMatch("b|*x", "ax", false); + assertMatch("[a|b]", "|", true); + } + + @Test + public void testBrackets() throws Exception { + assertMatch("{}*()", "{}x()", true); + assertMatch("[a{}()b][a{}()b]?[a{}()b][a{}()b]", "{}x()", true); + assertMatch("x*{x}3", "xa{x}3", true); + assertMatch("a*{x}3", "axxx", false); + } + @Test public void testFilePathSimpleCase() throws Exception { assertFileNameMatch("a/b", "a/b", true); 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 921339a3f..7452d293d 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 @@ -247,7 +247,7 @@ public class Strings { char[] charClass = new char[6]; for (int i = 0; i < pattern.length(); i++) { - char c = pattern.charAt(i); + final char c = pattern.charAt(i); switch (c) { case '*': @@ -257,6 +257,20 @@ public class Strings { sb.append('.').append(c); break; + case '(': // fall-through + case ')': // fall-through + case '{': // fall-through + case '}': // fall-through + case '+': // fall-through + case '$': // fall-through + case '^': // fall-through + case '|': + if (seenEscape || in_brackets > 0) + sb.append(c); + else + sb.append('\\').append(c); + break; + case '.': if (seenEscape) sb.append(c);