Show More
@@ -142,9 +142,14 b' def match(root, cwd, patterns, include=N' | |||||
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= |
|
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, | |
@@ -457,6 +462,75 b' class differencematcher(basematcher):' | |||||
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)) | |
459 |
|
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)) | |||
|
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 |
@@ -96,7 +96,7 b'' | |||||
96 | f fenugreek ../fenugreek |
|
96 | f fenugreek ../fenugreek | |
97 | f mammals/skunk skunk |
|
97 | f mammals/skunk skunk | |
98 | $ hg debugwalk -I 'relglob:*k' . |
|
98 | $ hg debugwalk -I 'relglob:*k' . | |
99 | matcher: <matcher files=['mammals'], patterns='(?:mammals(?:/|$))', includes='(?:(?:|.*/)[^/]*k(?:/|$))'> |
|
99 | matcher: <intersectionmatcher m1=<matcher files=['mammals'], patterns='(?:mammals(?:/|$))', includes=None>, m2=<matcher files=[], patterns=None, includes='(?:(?:|.*/)[^/]*k(?:/|$))'>> | |
100 | f mammals/skunk skunk |
|
100 | f mammals/skunk skunk | |
101 | $ hg debugwalk -I 're:.*k$' |
|
101 | $ hg debugwalk -I 're:.*k$' | |
102 | matcher: <matcher files=[], patterns=None, includes='(?:.*k$)'> |
|
102 | matcher: <matcher files=[], patterns=None, includes='(?:.*k$)'> | |
@@ -276,17 +276,17 b'' | |||||
276 | f fenugreek fenugreek |
|
276 | f fenugreek fenugreek | |
277 | f mammals/skunk mammals/skunk |
|
277 | f mammals/skunk mammals/skunk | |
278 | $ hg debugwalk -Ibeans mammals |
|
278 | $ hg debugwalk -Ibeans mammals | |
279 | matcher: <matcher files=['mammals'], patterns='(?:mammals(?:/|$))', includes='(?:beans(?:/|$))'> |
|
279 | matcher: <intersectionmatcher m1=<matcher files=['mammals'], patterns='(?:mammals(?:/|$))', includes=None>, m2=<matcher files=[], patterns=None, includes='(?:beans(?:/|$))'>> | |
280 | $ hg debugwalk -Inon-existent |
|
280 | $ hg debugwalk -Inon-existent | |
281 | matcher: <matcher files=[], patterns=None, includes='(?:non\\-existent(?:/|$))'> |
|
281 | matcher: <matcher files=[], patterns=None, includes='(?:non\\-existent(?:/|$))'> | |
282 | $ hg debugwalk -Inon-existent -Ibeans/black |
|
282 | $ hg debugwalk -Inon-existent -Ibeans/black | |
283 | matcher: <matcher files=[], patterns=None, includes='(?:non\\-existent(?:/|$)|beans\\/black(?:/|$))'> |
|
283 | matcher: <matcher files=[], patterns=None, includes='(?:non\\-existent(?:/|$)|beans\\/black(?:/|$))'> | |
284 | f beans/black beans/black |
|
284 | f beans/black beans/black | |
285 | $ hg debugwalk -Ibeans beans/black |
|
285 | $ hg debugwalk -Ibeans beans/black | |
286 | matcher: <matcher files=['beans/black'], patterns='(?:beans\\/black(?:/|$))', includes='(?:beans(?:/|$))'> |
|
286 | matcher: <intersectionmatcher m1=<matcher files=['beans/black'], patterns='(?:beans\\/black(?:/|$))', includes=None>, m2=<matcher files=[], patterns=None, includes='(?:beans(?:/|$))'>> | |
287 | f beans/black beans/black exact |
|
287 | f beans/black beans/black exact | |
288 | $ hg debugwalk -Ibeans/black beans |
|
288 | $ hg debugwalk -Ibeans/black beans | |
289 | matcher: <matcher files=['beans'], patterns='(?:beans(?:/|$))', includes='(?:beans\\/black(?:/|$))'> |
|
289 | matcher: <intersectionmatcher m1=<matcher files=['beans'], patterns='(?:beans(?:/|$))', includes=None>, m2=<matcher files=[], patterns=None, includes='(?:beans\\/black(?:/|$))'>> | |
290 | f beans/black beans/black |
|
290 | f beans/black beans/black | |
291 | $ hg debugwalk -Xbeans/black beans |
|
291 | $ hg debugwalk -Xbeans/black beans | |
292 | matcher: <differencematcher m1=<matcher files=['beans'], patterns='(?:beans(?:/|$))', includes=None>, m2=<matcher files=[], patterns=None, includes='(?:beans\\/black(?:/|$))'>> |
|
292 | matcher: <differencematcher m1=<matcher files=['beans'], patterns='(?:beans(?:/|$))', includes=None>, m2=<matcher files=[], patterns=None, includes='(?:beans\\/black(?:/|$))'>> |
General Comments 0
You need to be logged in to leave comments.
Login now