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: