Mercurial > hg
comparison mercurial/match.py @ 39261:c9a3f7f5c023
match: make exactmatcher.visitchildrenset return file children as well
Previously, if we had an exactmatcher like ['foo.txt', 'a/bar.txt', 'a/b/c/baz.txt'], we'd
get back the following data:
'.': {'a'}
'a': {'b'}
'a/b': {'c'}
'a/b/c': 'this'
'a/b/c/d': set()
This was incorrect, since visitchildrenset explicitly says not to pay attention
to 'foo.txt' and 'a/bar.txt' by not returning them or 'this'. Given the near
impossibility of making visitchildrenset reliabbly produce only subdirectories,
a previous commit has made it documented and expected that visitchildrenset can
return a set containing both files and subdirectories to visit, instead of
implying/requiring that visitchildrenset() return 'this' if there are files to
visit. This makes the code for exactmatcher match this clarified documentation.
Differential Revision: https://phab.mercurial-scm.org/D4365
author | Kyle Lippincott <spectral@google.com> |
---|---|
date | Fri, 24 Aug 2018 10:19:31 -0700 |
parents | 27946fca8a05 |
children | 35ecaa999a12 |
comparison
equal
deleted
inserted
replaced
39260:27946fca8a05 | 39261:c9a3f7f5c023 |
---|---|
585 | 585 |
586 def visitdir(self, dir): | 586 def visitdir(self, dir): |
587 return dir in self._dirs | 587 return dir in self._dirs |
588 | 588 |
589 def visitchildrenset(self, dir): | 589 def visitchildrenset(self, dir): |
590 if dir in self._dirs: | 590 if not self._fileset or dir not in self._dirs: |
591 candidates = self._dirs - {'.'} | 591 return set() |
592 if dir != '.': | 592 |
593 d = dir + '/' | 593 candidates = self._fileset | self._dirs - {'.'} |
594 candidates = set(c[len(d):] for c in candidates if | 594 if dir != '.': |
595 c.startswith(d)) | 595 d = dir + '/' |
596 # self._dirs includes all of the directories, recursively, so if | 596 candidates = set(c[len(d):] for c in candidates if |
597 # we're attempting to match foo/bar/baz.txt, it'll have '.', 'foo', | 597 c.startswith(d)) |
598 # 'foo/bar' in it. Thus we can safely ignore a candidate that has a | 598 # self._dirs includes all of the directories, recursively, so if |
599 # '/' in it, indicating a it's for a subdir-of-a-subdir; the | 599 # we're attempting to match foo/bar/baz.txt, it'll have '.', 'foo', |
600 # immediate subdir will be in there without a slash. | 600 # 'foo/bar' in it. Thus we can safely ignore a candidate that has a |
601 ret = set(c for c in candidates if '/' not in c) | 601 # '/' in it, indicating a it's for a subdir-of-a-subdir; the |
602 # We need to emit 'this' for foo/bar, not set(), not {'baz.txt'}. | 602 # immediate subdir will be in there without a slash. |
603 if not ret: | 603 ret = {c for c in candidates if '/' not in c} |
604 return 'this' | 604 # We really do not expect ret to be empty, since that would imply that |
605 return ret | 605 # there's something in _dirs that didn't have a file in _fileset. |
606 return set() | 606 assert ret |
607 return ret | |
607 | 608 |
608 def isexact(self): | 609 def isexact(self): |
609 return True | 610 return True |
610 | 611 |
611 @encoding.strmethod | 612 @encoding.strmethod |