Mercurial > hg
comparison mercurial/match.py @ 32497:9eccd559c592
match: handle includes using new intersectionmatcher
author | Martin von Zweigbergk <martinvonz@google.com> |
---|---|
date | Fri, 12 May 2017 23:12:05 -0700 |
parents | ca77a243ffa7 |
children | a3583852861a |
comparison
equal
deleted
inserted
replaced
32496:ca77a243ffa7 | 32497:9eccd559c592 |
---|---|
140 kindpats.append((kind, p, source)) | 140 kindpats.append((kind, p, source)) |
141 | 141 |
142 kindpats.append((kind, pats, source)) | 142 kindpats.append((kind, pats, source)) |
143 return kindpats | 143 return kindpats |
144 | 144 |
145 m = matcher(root, cwd, normalize, patterns, include=include, | 145 m = matcher(root, cwd, normalize, patterns, include=None, |
146 default=default, exact=exact, auditor=auditor, ctx=ctx, | 146 default=default, exact=exact, auditor=auditor, ctx=ctx, |
147 listsubrepos=listsubrepos, warn=warn, badfn=badfn) | 147 listsubrepos=listsubrepos, warn=warn, badfn=badfn) |
148 if include: | |
149 im = matcher(root, cwd, normalize, [], include=include, default=default, | |
150 exact=False, auditor=auditor, ctx=ctx, | |
151 listsubrepos=listsubrepos, warn=warn, badfn=None) | |
152 m = intersectmatchers(m, im) | |
148 if exclude: | 153 if exclude: |
149 em = matcher(root, cwd, normalize, [], include=exclude, default=default, | 154 em = matcher(root, cwd, normalize, [], include=exclude, default=default, |
150 exact=False, auditor=auditor, ctx=ctx, | 155 exact=False, auditor=auditor, ctx=ctx, |
151 listsubrepos=listsubrepos, warn=warn, badfn=None) | 156 listsubrepos=listsubrepos, warn=warn, badfn=None) |
152 m = differencematcher(m, em) | 157 m = differencematcher(m, em) |
454 def prefix(self): | 459 def prefix(self): |
455 return not self.always() and not self.isexact() and not self.anypats() | 460 return not self.always() and not self.isexact() and not self.anypats() |
456 | 461 |
457 def __repr__(self): | 462 def __repr__(self): |
458 return ('<differencematcher m1=%r, m2=%r>' % (self._m1, self._m2)) | 463 return ('<differencematcher m1=%r, m2=%r>' % (self._m1, self._m2)) |
464 | |
465 def intersectmatchers(m1, m2): | |
466 '''Composes two matchers by matching if both of them match. | |
467 | |
468 The second matcher's non-matching-attributes (root, cwd, bad, explicitdir, | |
469 traversedir) are ignored. | |
470 ''' | |
471 if m1 is None or m2 is None: | |
472 return m1 or m2 | |
473 if m1.always(): | |
474 m = copy.copy(m2) | |
475 # TODO: Consider encapsulating these things in a class so there's only | |
476 # one thing to copy from m1. | |
477 m.bad = m1.bad | |
478 m.explicitdir = m1.explicitdir | |
479 m.traversedir = m1.traversedir | |
480 m.abs = m1.abs | |
481 m.rel = m1.rel | |
482 m._relativeuipath |= m1._relativeuipath | |
483 return m | |
484 if m2.always(): | |
485 m = copy.copy(m1) | |
486 m._relativeuipath |= m2._relativeuipath | |
487 return m | |
488 return intersectionmatcher(m1, m2) | |
489 | |
490 class intersectionmatcher(basematcher): | |
491 def __init__(self, m1, m2): | |
492 super(intersectionmatcher, self).__init__(m1._root, m1._cwd) | |
493 self._m1 = m1 | |
494 self._m2 = m2 | |
495 self.bad = m1.bad | |
496 self.explicitdir = m1.explicitdir | |
497 self.traversedir = m1.traversedir | |
498 | |
499 @propertycache | |
500 def _files(self): | |
501 if self.isexact(): | |
502 m1, m2 = self._m1, self._m2 | |
503 if not m1.isexact(): | |
504 m1, m2 = m2, m1 | |
505 return [f for f in m1.files() if m2(f)] | |
506 # It neither m1 nor m2 is an exact matcher, we can't easily intersect | |
507 # the set of files, because their files() are not always files. For | |
508 # example, if intersecting a matcher "-I glob:foo.txt" with matcher of | |
509 # "path:dir2", we don't want to remove "dir2" from the set. | |
510 return self._m1.files() + self._m2.files() | |
511 | |
512 def matchfn(self, f): | |
513 return self._m1(f) and self._m2(f) | |
514 | |
515 def visitdir(self, dir): | |
516 visit1 = self._m1.visitdir(dir) | |
517 if visit1 == 'all': | |
518 return self._m2.visitdir(dir) | |
519 # bool() because visit1=True + visit2='all' should not be 'all' | |
520 return bool(visit1 and self._m2.visitdir(dir)) | |
521 | |
522 def always(self): | |
523 return self._m1.always() and self._m2.always() | |
524 | |
525 def isexact(self): | |
526 return self._m1.isexact() or self._m2.isexact() | |
527 | |
528 def anypats(self): | |
529 return self._m1.anypats() or self._m2.anypats() | |
530 | |
531 def __repr__(self): | |
532 return ('<intersectionmatcher m1=%r, m2=%r>' % (self._m1, self._m2)) | |
459 | 533 |
460 class subdirmatcher(basematcher): | 534 class subdirmatcher(basematcher): |
461 """Adapt a matcher to work on a subdirectory only. | 535 """Adapt a matcher to work on a subdirectory only. |
462 | 536 |
463 The paths are remapped to remove/insert the path as needed: | 537 The paths are remapped to remove/insert the path as needed: |