Mercurial > hg
comparison mercurial/match.py @ 38611:0ba4cf3f088f
match: add prefixdirmatcher to adapt subrepo matcher back
This serves as an inverse function to the subdirmatcher, and will be used
to wrap a fileset matcher of subrepositories. One of the root/prefix paths
could be deduced from the matcher attributes to be wrapped, but we don't
since the callers of this class know the root/prefix paths and can simply
pass them in.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sat, 09 Jun 2018 22:04:07 +0900 |
parents | 6467286b829c |
children | 760cc5dc01e8 |
comparison
equal
deleted
inserted
replaced
38610:3d8ef60569d8 | 38611:0ba4cf3f088f |
---|---|
681 | 681 |
682 @encoding.strmethod | 682 @encoding.strmethod |
683 def __repr__(self): | 683 def __repr__(self): |
684 return ('<subdirmatcher path=%r, matcher=%r>' % | 684 return ('<subdirmatcher path=%r, matcher=%r>' % |
685 (self._path, self._matcher)) | 685 (self._path, self._matcher)) |
686 | |
687 class prefixdirmatcher(basematcher): | |
688 """Adapt a matcher to work on a parent directory. | |
689 | |
690 The matcher's non-matching-attributes (root, cwd, bad, explicitdir, | |
691 traversedir) are ignored. | |
692 | |
693 The prefix path should usually be the relative path from the root of | |
694 this matcher to the root of the wrapped matcher. | |
695 | |
696 >>> m1 = match(b'root/d/e', b'f', [b'../a.txt', b'b.txt']) | |
697 >>> m2 = prefixdirmatcher(b'root', b'd/e/f', b'd/e', m1) | |
698 >>> bool(m2(b'a.txt'),) | |
699 False | |
700 >>> bool(m2(b'd/e/a.txt')) | |
701 True | |
702 >>> bool(m2(b'd/e/b.txt')) | |
703 False | |
704 >>> m2.files() | |
705 ['d/e/a.txt', 'd/e/f/b.txt'] | |
706 >>> m2.exact(b'd/e/a.txt') | |
707 True | |
708 >>> m2.visitdir(b'd') | |
709 True | |
710 >>> m2.visitdir(b'd/e') | |
711 True | |
712 >>> m2.visitdir(b'd/e/f') | |
713 True | |
714 >>> m2.visitdir(b'd/e/g') | |
715 False | |
716 >>> m2.visitdir(b'd/ef') | |
717 False | |
718 """ | |
719 | |
720 def __init__(self, root, cwd, path, matcher, badfn=None): | |
721 super(prefixdirmatcher, self).__init__(root, cwd, badfn) | |
722 if not path: | |
723 raise error.ProgrammingError('prefix path must not be empty') | |
724 self._path = path | |
725 self._pathprefix = path + '/' | |
726 self._matcher = matcher | |
727 | |
728 @propertycache | |
729 def _files(self): | |
730 return [self._pathprefix + f for f in self._matcher._files] | |
731 | |
732 def matchfn(self, f): | |
733 if not f.startswith(self._pathprefix): | |
734 return False | |
735 return self._matcher.matchfn(f[len(self._pathprefix):]) | |
736 | |
737 @propertycache | |
738 def _pathdirs(self): | |
739 return set(util.finddirs(self._path)) | {'.'} | |
740 | |
741 def visitdir(self, dir): | |
742 if dir == self._path: | |
743 return self._matcher.visitdir('.') | |
744 if dir.startswith(self._pathprefix): | |
745 return self._matcher.visitdir(dir[len(self._pathprefix):]) | |
746 return dir in self._pathdirs | |
747 | |
748 def isexact(self): | |
749 return self._matcher.isexact() | |
750 | |
751 def prefix(self): | |
752 return self._matcher.prefix() | |
753 | |
754 @encoding.strmethod | |
755 def __repr__(self): | |
756 return ('<prefixdirmatcher path=%r, matcher=%r>' | |
757 % (pycompat.bytestr(self._path), self._matcher)) | |
686 | 758 |
687 class unionmatcher(basematcher): | 759 class unionmatcher(basematcher): |
688 """A matcher that is the union of several matchers. | 760 """A matcher that is the union of several matchers. |
689 | 761 |
690 The non-matching-attributes (root, cwd, bad, explicitdir, traversedir) are | 762 The non-matching-attributes (root, cwd, bad, explicitdir, traversedir) are |