From 6b58e23b6038051fb2d690691912bca3dffcde97 Mon Sep 17 00:00:00 2001 From: tomruk <41700170+tomruk@users.noreply.github.com> Date: Mon, 24 Apr 2023 10:58:41 +0300 Subject: [PATCH 1/2] Negate with caret symbol as with the exclamation mark --- pathspec/patterns/gitwildmatch.py | 12 ++---------- tests/test_gitwildmatch.py | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/pathspec/patterns/gitwildmatch.py b/pathspec/patterns/gitwildmatch.py index 3f35f2d..8701762 100644 --- a/pathspec/patterns/gitwildmatch.py +++ b/pathspec/patterns/gitwildmatch.py @@ -312,18 +312,10 @@ def _translate_segment_glob(pattern: str) -> str: j += 1 expr = '[' - if pattern[i] == '!': - # Braket expression needs to be negated. + if pattern[i] == '!' or pattern[i] == '^': + # Bracket expression needs to be negated. expr += '^' i += 1 - elif pattern[i] == '^': - # POSIX declares that the regex bracket expression negation - # "[^...]" is undefined in a glob pattern. Python's - # `fnmatch.translate()` escapes the caret ('^') as a - # literal. To maintain consistency with undefined behavior, - # I am escaping the '^' as well. - expr += '\\^' - i += 1 # Build regex bracket expression. Escape slashes so they are # treated as literal slashes by regex as defined by POSIX. diff --git a/tests/test_gitwildmatch.py b/tests/test_gitwildmatch.py index 7dccaee..2eaab6a 100644 --- a/tests/test_gitwildmatch.py +++ b/tests/test_gitwildmatch.py @@ -773,3 +773,29 @@ def test_12_asterisk_4_descendant(self): self.assertEqual(results, { 'anydir/file.txt', }) + + def test_13_negate_with_caret(self): + """ + Test negation using the caret symbol (^) + """ + pattern = GitWildMatchPattern("a[^gy]c") + results = set(filter(pattern.match_file, [ + "agc", + "ayc", + "abc", + "adc", + ])) + self.assertEqual(results, {"abc", "adc"}) + + def test_13_negate_with_exclamation_mark(self): + """ + Test negation using the exclamation mark (!) + """ + pattern = GitWildMatchPattern("a[!gy]c") + results = set(filter(pattern.match_file, [ + "agc", + "ayc", + "abc", + "adc", + ])) + self.assertEqual(results, {"abc", "adc"}) From 57fbd3ed69597d35a50c56446d60e2c17ab04baf Mon Sep 17 00:00:00 2001 From: tomruk <41700170+tomruk@users.noreply.github.com> Date: Mon, 24 Apr 2023 11:22:18 +0300 Subject: [PATCH 2/2] Pass caret negation --- pathspec/patterns/gitwildmatch.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pathspec/patterns/gitwildmatch.py b/pathspec/patterns/gitwildmatch.py index 8701762..8276b00 100644 --- a/pathspec/patterns/gitwildmatch.py +++ b/pathspec/patterns/gitwildmatch.py @@ -290,8 +290,8 @@ def _translate_segment_glob(pattern: str) -> str: # - "[]-]" matches ']' and '-'. # - "[!]a-]" matches any character except ']', 'a' and '-'. j = i - # Pass brack expression negation. - if j < end and pattern[j] == '!': + # Pass bracket expression negation. + if j < end and (pattern[j] == '!' or pattern[j] == '^'): j += 1 # Pass first closing bracket if it is at the beginning of the # expression.