From 08641ea413d64baed4ae8d017988fa15e52179ad Mon Sep 17 00:00:00 2001 From: Andrey Loskutov Date: Tue, 14 Jul 2015 00:05:49 +0200 Subject: [PATCH] Allow leading literal '#' and '!' in ignore rules if they are escaped According to [1] backslash can escape leading special characters '#' and '!' in ignore rules, so that they are treated literally. [1] https://www.kernel.org/pub/software/scm/git/docs/gitignore.html Bug: 463581 Change-Id: I4c02927413a9c63ea5dbf2954877080d902ec1b2 Signed-off-by: Andrey Loskutov --- .../ignore/IgnoreRuleSpecialCasesTest.java | 12 ++++++ .../eclipse/jgit/ignore/FastIgnoreRule.java | 41 +++++++++++-------- 2 files changed, 36 insertions(+), 17 deletions(-) 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 4916d4054..05443d60c 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 @@ -835,6 +835,18 @@ public void testEscapedBackslash() throws Exception { assertMatch("a\\\\b", "a\\b", true); } + @Test + public void testEscapedExclamationMark() throws Exception { + assertMatch("\\!b!.txt", "!b!.txt", true); + assertMatch("a\\!b!.txt", "a\\!b!.txt", true); + } + + @Test + public void testEscapedHash() throws Exception { + assertMatch("\\#b", "#b", true); + assertMatch("a\\#", "a\\#", true); + } + @Test public void testEscapedTrailingSpaces() throws Exception { assertMatch("\\ ", " ", true); 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 2303ffd6d..16a36baf0 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/ignore/FastIgnoreRule.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/ignore/FastIgnoreRule.java @@ -98,24 +98,31 @@ public FastIgnoreRule(String pattern) { if (pattern.charAt(0) == '#') { this.matcher = NO_MATCH; dirOnly = false; - } else { - dirOnly = pattern.charAt(pattern.length() - 1) == PATH_SEPARATOR; - if (dirOnly) { - pattern = stripTrailing(pattern, PATH_SEPARATOR); - if (pattern.length() == 0) { - this.matcher = NO_MATCH; - return; - } - } - IMatcher m; - try { - m = PathMatcher.createPathMatcher(pattern, - Character.valueOf(PATH_SEPARATOR), dirOnly); - } catch (InvalidPatternException e) { - m = NO_MATCH; - } - this.matcher = m; + return; } + if (pattern.charAt(0) == '\\' && pattern.length() > 1) { + char next = pattern.charAt(1); + if (next == '!' || next == '#') { + // remove backslash escaping first special characters + pattern = pattern.substring(1); + } + } + dirOnly = pattern.charAt(pattern.length() - 1) == PATH_SEPARATOR; + if (dirOnly) { + pattern = stripTrailing(pattern, PATH_SEPARATOR); + if (pattern.length() == 0) { + this.matcher = NO_MATCH; + return; + } + } + IMatcher m; + try { + m = PathMatcher.createPathMatcher(pattern, + Character.valueOf(PATH_SEPARATOR), dirOnly); + } catch (InvalidPatternException e) { + m = NO_MATCH; + } + this.matcher = m; } /**