Skip to content

Commit

Permalink
Fix issue 62
Browse files Browse the repository at this point in the history
  • Loading branch information
cpburnz committed Sep 2, 2022
1 parent 0f5e50b commit 4608cee
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 9 deletions.
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ Bug fixes:
- Fix documentation on `pathspec.pattern.RegexPattern.match_file()`.
- `Issue #60`_: Remove redundant wheel dep from pyproject.toml.
- `Issue #61`_: Dist failure for Fedora, CentOS, EPEL.
- `Issue #62`_: Since version 0.10.0 pure wildcard does not work in some cases.


.. _`Issue #60`: https://github.com/cpburnz/python-pathspec/pull/60
.. _`Issue #61`: https://github.com/cpburnz/python-pathspec/issues/61
.. _`Issue #62`: https://github.com/cpburnz/python-pathspec/issues/62


0.10.0 (2022-08-30)
Expand Down
1 change: 1 addition & 0 deletions pathspec/_meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"ichard26 <https://github.com/ichard26>",
"jack1142 <https://github.com/jack1142>",
"mgorny <https://github.com/mgorny>",
"bzakdd <https://github.com/bzakdd>",
]
__license__ = "MPL 2.0"
__version__ = "0.10.1.dev1"
18 changes: 9 additions & 9 deletions pathspec/patterns/gitwildmatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class GitWildMatchPattern(RegexPattern):
def pattern_to_regex(
cls,
pattern: AnyStr,
) -> Tuple[Optional[AnyStr], Optional[bool]]: # TODO: Change to NamedTuple
) -> Tuple[Optional[AnyStr], Optional[bool]]:
"""
Convert the pattern into a regular expression.
Expand Down Expand Up @@ -143,14 +143,6 @@ def pattern_to_regex(
# all. This must be because the pattern is invalid.
raise GitWildMatchPatternError(f"Invalid git pattern: {original_pattern!r}")

if pattern_segs[-1] == '*' and len(pattern_segs) > 1:
# A pattern ending with "/*" should match all descendant paths
# of the directory, not just direct children. This is equivalent
# to "{pattern}/**". This behavior of git contradicts its
# documentation. So, set last segment to a double-asterisk to
# include all descendants.
pattern_segs[-1] = '**'

if not pattern_segs[-1] and len(pattern_segs) > 1:
# A pattern ending with a slash ('/') will match all descendant
# paths if it is a directory but not if it is a regular file.
Expand Down Expand Up @@ -188,7 +180,15 @@ def pattern_to_regex(
# Match single path segment.
if need_slash:
output.append('/')

output.append('[^/]+')

if i == end:
# A pattern ending without a slash ('/') will match a file
# or a directory (with paths underneath it). E.g., "foo"
# matches "foo", "foo/bar", "foo/bar/baz", etc.
output.append('(?:(?P<ps_d>/).*)?')

need_slash = True

else:
Expand Down
17 changes: 17 additions & 0 deletions tests/test_gitignore.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,3 +294,20 @@ def test_03_issue_19_c(self):
'dirD/fileE',
'dirD/fileF',
})

def test_04_issue_62(self):
"""
Test including all files and excluding a directory.
"""
spec = GitIgnoreSpec.from_lines([
'*',
'!product_dir/',
])
results = set(spec.match_files([
'anydir/file.txt',
'product_dir/file.txt',
]))
self.assertEqual(results, {
'anydir/file.txt',
'product_dir/file.txt',
})
45 changes: 45 additions & 0 deletions tests/test_gitwildmatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -705,3 +705,48 @@ def test_11_match_sub_directory_3(self):
'dirG/dirH/fileJ',
'dirG/fileO',
})

def test_12_asterisk_1_regex(self):
"""
Test a relative asterisk path pattern's regular expression.
"""
regex, include = GitWildMatchPattern.pattern_to_regex('*')
self.assertTrue(include)
self.assertEqual(regex, f'^(?:.+/)?[^/]+{RE_SUB}$')

def test_12_asterisk_2_regex_equivalent(self):
"""
Test a path pattern equivalent to the relative asterisk using double
asterisk.
"""
regex, include = GitWildMatchPattern.pattern_to_regex('*')
self.assertTrue(include)

equiv_regex, include = GitWildMatchPattern.pattern_to_regex('**/*')
self.assertTrue(include)

self.assertEqual(regex, equiv_regex)

def test_12_asterisk_3_child(self):
"""
Test a relative asterisk path pattern matching a direct child path.
"""
pattern = GitWildMatchPattern('*')
results = set(filter(pattern.match_file, [
'file.txt',
]))
self.assertEqual(results, {
'file.txt',
})

def test_12_asterisk_4_descendant(self):
"""
Test a relative asterisk path pattern matching a descendant path.
"""
pattern = GitWildMatchPattern('*')
results = set(filter(pattern.match_file, [
'anydir/file.txt',
]))
self.assertEqual(results, {
'anydir/file.txt',
})
16 changes: 16 additions & 0 deletions tests/test_pathspec.py
Original file line number Diff line number Diff line change
Expand Up @@ -521,3 +521,19 @@ def test_06_issue_41_c(self):
'dir/file.sql',
'dir/index.txt',
})

def test_07_issue_62(self):
"""
Test including all files and excluding a directory.
"""
spec = PathSpec.from_lines('gitwildmatch', [
'*',
'!product_dir/',
])
results = set(spec.match_files([
'anydir/file.txt',
'product_dir/file.txt'
]))
self.assertEqual(results, {
'anydir/file.txt',
})

0 comments on commit 4608cee

Please sign in to comment.