Mercurial > hg
changeset 51569:b32c3146ec34 stable
match: fix the "visitdir" method on "rootfilesin" matchers
This fixes just the Python side, the fix for the rust side will follow shortly.
author | Arseniy Alekseyev <aalekseyev@janestreet.com> |
---|---|
date | Fri, 12 Apr 2024 15:39:21 +0100 |
parents | 2a89d2f6336f |
children | b39057b713b1 |
files | mercurial/match.py tests/test-match.py tests/test-status.t |
diffstat | 3 files changed, 23 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/match.py Fri Apr 12 14:21:14 2024 +0100 +++ b/mercurial/match.py Fri Apr 12 15:39:21 2024 +0100 @@ -638,7 +638,10 @@ super(patternmatcher, self).__init__(badfn) kindpats.sort() + roots, dirs, parents = _rootsdirsandparents(kindpats) self._files = _explicitfiles(kindpats) + self._dirs_explicit = set(dirs) + self._dirs = parents self._prefix = _prefix(kindpats) self._pats, self._matchfn = _buildmatch(kindpats, b'$', root) @@ -647,14 +650,14 @@ return True return self._matchfn(fn) - @propertycache - def _dirs(self): - return set(pathutil.dirs(self._fileset)) - def visitdir(self, dir): if self._prefix and dir in self._fileset: return b'all' - return dir in self._dirs or path_or_parents_in_set(dir, self._fileset) + return ( + dir in self._dirs + or path_or_parents_in_set(dir, self._fileset) + or path_or_parents_in_set(dir, self._dirs_explicit) + ) def visitchildrenset(self, dir): ret = self.visitdir(dir) @@ -1461,7 +1464,7 @@ allgroups = [] regexps = [] exact = set() - for (kind, pattern, _source) in kindpats: + for kind, pattern, _source in kindpats: if kind == b'filepath': exact.add(pattern) continue
--- a/tests/test-match.py Fri Apr 12 14:21:14 2024 +0100 +++ b/tests/test-match.py Fri Apr 12 15:39:21 2024 +0100 @@ -94,12 +94,14 @@ patterns=[b'rootfilesin:dir/subdir'], ) assert isinstance(m, matchmod.patternmatcher) - self.assertFalse(m.visitdir(b'dir/subdir/x')) + # OPT: we shouldn't visit [x] as a directory, + # but we should still visit it as a file. + # Unfortunately, `visitdir` is used for both. + self.assertTrue(m.visitdir(b'dir/subdir/x')) self.assertFalse(m.visitdir(b'folder')) - # FIXME: These should probably be True. - self.assertFalse(m.visitdir(b'')) - self.assertFalse(m.visitdir(b'dir')) - self.assertFalse(m.visitdir(b'dir/subdir')) + self.assertTrue(m.visitdir(b'')) + self.assertTrue(m.visitdir(b'dir')) + self.assertTrue(m.visitdir(b'dir/subdir')) def testVisitchildrensetRootfilesin(self): m = matchmod.match( @@ -108,13 +110,13 @@ patterns=[b'rootfilesin:dir/subdir'], ) assert isinstance(m, matchmod.patternmatcher) - self.assertEqual(m.visitchildrenset(b'dir/subdir/x'), set()) + self.assertEqual(m.visitchildrenset(b'dir/subdir/x'), b'this') self.assertEqual(m.visitchildrenset(b'folder'), set()) - # FIXME: These should probably be {'dir'}, {'subdir'} and 'this', - # respectively, or at least 'this' for all three. - self.assertEqual(m.visitchildrenset(b''), set()) - self.assertEqual(m.visitchildrenset(b'dir'), set()) - self.assertEqual(m.visitchildrenset(b'dir/subdir'), set()) + # OPT: These should probably be {'dir'}, {'subdir'} and 'this', + # respectively + self.assertEqual(m.visitchildrenset(b''), b'this') + self.assertEqual(m.visitchildrenset(b'dir'), b'this') + self.assertEqual(m.visitchildrenset(b'dir/subdir'), b'this') def testVisitdirGlob(self): m = matchmod.match(
--- a/tests/test-status.t Fri Apr 12 14:21:14 2024 +0100 +++ b/tests/test-status.t Fri Apr 12 15:39:21 2024 +0100 @@ -863,6 +863,7 @@ M subdir/modified (no-rhg !) R subdir/removed (no-rhg !) ! subdir/deleted (no-rhg !) + ? subdir/unknown (no-rhg !) Note: `hg status some-name` creates a patternmatcher which is not supported yet by the Rust implementation of status, but includematcher is supported.