Show More
@@ -142,10 +142,15 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 |
|
|
145 | m = matcher(root, cwd, normalize, patterns, include=include, exclude=None, | |
146 |
|
|
146 | default=default, exact=exact, auditor=auditor, ctx=ctx, | |
147 |
|
|
147 | listsubrepos=listsubrepos, warn=warn, badfn=badfn) | |
148 | warn=warn, badfn=badfn) |
|
148 | if exclude: | |
|
149 | em = matcher(root, cwd, normalize, [], include=exclude, exclude=None, | |||
|
150 | default=default, exact=False, auditor=auditor, ctx=ctx, | |||
|
151 | listsubrepos=listsubrepos, warn=warn, badfn=None) | |||
|
152 | m = differencematcher(m, em) | |||
|
153 | return m | |||
149 |
|
154 | |||
150 | def exact(root, cwd, files, badfn=None): |
|
155 | def exact(root, cwd, files, badfn=None): | |
151 | return match(root, cwd, files, exact=True, badfn=badfn) |
|
156 | return match(root, cwd, files, exact=True, badfn=badfn) | |
@@ -418,6 +423,62 b' class matcher(basematcher):' | |||||
418 | (self._files, self.patternspat, self.includepat, |
|
423 | (self._files, self.patternspat, self.includepat, | |
419 | self.excludepat)) |
|
424 | self.excludepat)) | |
420 |
|
425 | |||
|
426 | class differencematcher(basematcher): | |||
|
427 | '''Composes two matchers by matching if the first matches and the second | |||
|
428 | does not. Well, almost... If the user provides a pattern like "-X foo foo", | |||
|
429 | Mercurial actually does match "foo" against that. That's because exact | |||
|
430 | matches are treated specially. So, since this differencematcher is used for | |||
|
431 | excludes, it needs to special-case exact matching. | |||
|
432 | ||||
|
433 | The second matcher's non-matching-attributes (root, cwd, bad, explicitdir, | |||
|
434 | traversedir) are ignored. | |||
|
435 | ||||
|
436 | TODO: If we want to keep the behavior described above for exact matches, we | |||
|
437 | should consider instead treating the above case something like this: | |||
|
438 | union(exact(foo), difference(pattern(foo), include(foo))) | |||
|
439 | ''' | |||
|
440 | def __init__(self, m1, m2): | |||
|
441 | super(differencematcher, self).__init__(m1._root, m1._cwd) | |||
|
442 | self._m1 = m1 | |||
|
443 | self._m2 = m2 | |||
|
444 | self.bad = m1.bad | |||
|
445 | self.explicitdir = m1.explicitdir | |||
|
446 | self.traversedir = m1.traversedir | |||
|
447 | ||||
|
448 | def matchfn(self, f): | |||
|
449 | return self._m1(f) and (not self._m2(f) or self._m1.exact(f)) | |||
|
450 | ||||
|
451 | @propertycache | |||
|
452 | def _files(self): | |||
|
453 | if self.isexact(): | |||
|
454 | return [f for f in self._m1.files() if self(f)] | |||
|
455 | # If m1 is not an exact matcher, we can't easily figure out the set of | |||
|
456 | # files, because its files() are not always files. For example, if | |||
|
457 | # m1 is "path:dir" and m2 is "rootfileins:.", we don't | |||
|
458 | # want to remove "dir" from the set even though it would match m2, | |||
|
459 | # because the "dir" in m1 may not be a file. | |||
|
460 | return self._m1.files() | |||
|
461 | ||||
|
462 | def visitdir(self, dir): | |||
|
463 | if self._m2.visitdir(dir) == 'all': | |||
|
464 | # There's a bug here: If m1 matches file 'dir/file' and m2 excludes | |||
|
465 | # 'dir' (recursively), we should still visit 'dir' due to the | |||
|
466 | # exception we have for exact matches. | |||
|
467 | return False | |||
|
468 | return bool(self._m1.visitdir(dir)) | |||
|
469 | ||||
|
470 | def isexact(self): | |||
|
471 | return self._m1.isexact() | |||
|
472 | ||||
|
473 | def anypats(self): | |||
|
474 | return self._m1.anypats() or self._m2.anypats() | |||
|
475 | ||||
|
476 | def prefix(self): | |||
|
477 | return not self.always() and not self.isexact() and not self.anypats() | |||
|
478 | ||||
|
479 | def __repr__(self): | |||
|
480 | return ('<differencematcher m1=%r, m2=%r>' % (self._m1, self._m2)) | |||
|
481 | ||||
421 | class subdirmatcher(basematcher): |
|
482 | class subdirmatcher(basematcher): | |
422 | """Adapt a matcher to work on a subdirectory only. |
|
483 | """Adapt a matcher to work on a subdirectory only. | |
423 |
|
484 |
@@ -76,7 +76,7 b'' | |||||
76 | f mammals/Procyonidae/raccoon Procyonidae/raccoon |
|
76 | f mammals/Procyonidae/raccoon Procyonidae/raccoon | |
77 | f mammals/skunk skunk |
|
77 | f mammals/skunk skunk | |
78 | $ hg debugwalk -X ../beans |
|
78 | $ hg debugwalk -X ../beans | |
79 | matcher: <matcher files=[], patterns=None, includes=None, excludes='(?:beans(?:/|$))'> |
|
79 | matcher: <differencematcher m1=<matcher files=[], patterns=None, includes=None, excludes=None>, m2=<matcher files=[], patterns=None, includes='(?:beans(?:/|$))', excludes=None>> | |
80 | f fennel ../fennel |
|
80 | f fennel ../fennel | |
81 | f fenugreek ../fenugreek |
|
81 | f fenugreek ../fenugreek | |
82 | f fiddlehead ../fiddlehead |
|
82 | f fiddlehead ../fiddlehead | |
@@ -146,7 +146,7 b'' | |||||
146 | f fenugreek ../fenugreek |
|
146 | f fenugreek ../fenugreek | |
147 | f fiddlehead ../fiddlehead |
|
147 | f fiddlehead ../fiddlehead | |
148 | $ hg debugwalk -X 'rootfilesin:' |
|
148 | $ hg debugwalk -X 'rootfilesin:' | |
149 | matcher: <matcher files=[], patterns=None, includes=None, excludes='(?:^[^/]+$)'> |
|
149 | matcher: <differencematcher m1=<matcher files=[], patterns=None, includes=None, excludes=None>, m2=<matcher files=[], patterns=None, includes='(?:^[^/]+$)', excludes=None>> | |
150 | f beans/black ../beans/black |
|
150 | f beans/black ../beans/black | |
151 | f beans/borlotti ../beans/borlotti |
|
151 | f beans/borlotti ../beans/borlotti | |
152 | f beans/kidney ../beans/kidney |
|
152 | f beans/kidney ../beans/kidney | |
@@ -194,7 +194,7 b'' | |||||
194 | matcher: <matcher files=[], patterns=None, includes='(?:^mammals/[^/]+$)', excludes=None> |
|
194 | matcher: <matcher files=[], patterns=None, includes='(?:^mammals/[^/]+$)', excludes=None> | |
195 | f mammals/skunk skunk |
|
195 | f mammals/skunk skunk | |
196 | $ hg debugwalk -X 'rootfilesin:mammals' |
|
196 | $ hg debugwalk -X 'rootfilesin:mammals' | |
197 | matcher: <matcher files=[], patterns=None, includes=None, excludes='(?:^mammals/[^/]+$)'> |
|
197 | matcher: <differencematcher m1=<matcher files=[], patterns=None, includes=None, excludes=None>, m2=<matcher files=[], patterns=None, includes='(?:^mammals/[^/]+$)', excludes=None>> | |
198 | f beans/black ../beans/black |
|
198 | f beans/black ../beans/black | |
199 | f beans/borlotti ../beans/borlotti |
|
199 | f beans/borlotti ../beans/borlotti | |
200 | f beans/kidney ../beans/kidney |
|
200 | f beans/kidney ../beans/kidney | |
@@ -289,35 +289,35 b'' | |||||
289 | matcher: <matcher files=['beans'], patterns='(?:beans(?:/|$))', includes='(?:beans\\/black(?:/|$))', excludes=None> |
|
289 | matcher: <matcher files=['beans'], patterns='(?:beans(?:/|$))', includes='(?:beans\\/black(?:/|$))', excludes=None> | |
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: <matcher files=['beans'], patterns='(?:beans(?:/|$))', includes=None, excludes='(?:beans\\/black(?:/|$))'> |
|
292 | matcher: <differencematcher m1=<matcher files=['beans'], patterns='(?:beans(?:/|$))', includes=None, excludes=None>, m2=<matcher files=[], patterns=None, includes='(?:beans\\/black(?:/|$))', excludes=None>> | |
293 | f beans/borlotti beans/borlotti |
|
293 | f beans/borlotti beans/borlotti | |
294 | f beans/kidney beans/kidney |
|
294 | f beans/kidney beans/kidney | |
295 | f beans/navy beans/navy |
|
295 | f beans/navy beans/navy | |
296 | f beans/pinto beans/pinto |
|
296 | f beans/pinto beans/pinto | |
297 | f beans/turtle beans/turtle |
|
297 | f beans/turtle beans/turtle | |
298 | $ hg debugwalk -Xbeans/black -Ibeans |
|
298 | $ hg debugwalk -Xbeans/black -Ibeans | |
299 | matcher: <matcher files=[], patterns=None, includes='(?:beans(?:/|$))', excludes='(?:beans\\/black(?:/|$))'> |
|
299 | matcher: <differencematcher m1=<matcher files=[], patterns=None, includes='(?:beans(?:/|$))', excludes=None>, m2=<matcher files=[], patterns=None, includes='(?:beans\\/black(?:/|$))', excludes=None>> | |
300 | f beans/borlotti beans/borlotti |
|
300 | f beans/borlotti beans/borlotti | |
301 | f beans/kidney beans/kidney |
|
301 | f beans/kidney beans/kidney | |
302 | f beans/navy beans/navy |
|
302 | f beans/navy beans/navy | |
303 | f beans/pinto beans/pinto |
|
303 | f beans/pinto beans/pinto | |
304 | f beans/turtle beans/turtle |
|
304 | f beans/turtle beans/turtle | |
305 | $ hg debugwalk -Xbeans/black beans/black |
|
305 | $ hg debugwalk -Xbeans/black beans/black | |
306 | matcher: <matcher files=['beans/black'], patterns='(?:beans\\/black(?:/|$))', includes=None, excludes='(?:beans\\/black(?:/|$))'> |
|
306 | matcher: <differencematcher m1=<matcher files=['beans/black'], patterns='(?:beans\\/black(?:/|$))', includes=None, excludes=None>, m2=<matcher files=[], patterns=None, includes='(?:beans\\/black(?:/|$))', excludes=None>> | |
307 | f beans/black beans/black exact |
|
307 | f beans/black beans/black exact | |
308 | $ hg debugwalk -Xbeans/black -Ibeans/black |
|
308 | $ hg debugwalk -Xbeans/black -Ibeans/black | |
309 | matcher: <matcher files=[], patterns=None, includes='(?:beans\\/black(?:/|$))', excludes='(?:beans\\/black(?:/|$))'> |
|
309 | matcher: <differencematcher m1=<matcher files=[], patterns=None, includes='(?:beans\\/black(?:/|$))', excludes=None>, m2=<matcher files=[], patterns=None, includes='(?:beans\\/black(?:/|$))', excludes=None>> | |
310 | $ hg debugwalk -Xbeans beans/black |
|
310 | $ hg debugwalk -Xbeans beans/black | |
311 | matcher: <matcher files=['beans/black'], patterns='(?:beans\\/black(?:/|$))', includes=None, excludes='(?:beans(?:/|$))'> |
|
311 | matcher: <differencematcher m1=<matcher files=['beans/black'], patterns='(?:beans\\/black(?:/|$))', includes=None, excludes=None>, m2=<matcher files=[], patterns=None, includes='(?:beans(?:/|$))', excludes=None>> | |
312 | f beans/black beans/black exact |
|
312 | f beans/black beans/black exact | |
313 | $ hg debugwalk -Xbeans -Ibeans/black |
|
313 | $ hg debugwalk -Xbeans -Ibeans/black | |
314 | matcher: <matcher files=[], patterns=None, includes='(?:beans\\/black(?:/|$))', excludes='(?:beans(?:/|$))'> |
|
314 | matcher: <differencematcher m1=<matcher files=[], patterns=None, includes='(?:beans\\/black(?:/|$))', excludes=None>, m2=<matcher files=[], patterns=None, includes='(?:beans(?:/|$))', excludes=None>> | |
315 | $ hg debugwalk 'glob:mammals/../beans/b*' |
|
315 | $ hg debugwalk 'glob:mammals/../beans/b*' | |
316 | matcher: <matcher files=['beans'], patterns='(?:beans\\/b[^/]*$)', includes=None, excludes=None> |
|
316 | matcher: <matcher files=['beans'], patterns='(?:beans\\/b[^/]*$)', includes=None, excludes=None> | |
317 | f beans/black beans/black |
|
317 | f beans/black beans/black | |
318 | f beans/borlotti beans/borlotti |
|
318 | f beans/borlotti beans/borlotti | |
319 | $ hg debugwalk '-X*/Procyonidae' mammals |
|
319 | $ hg debugwalk '-X*/Procyonidae' mammals | |
320 | matcher: <matcher files=['mammals'], patterns='(?:mammals(?:/|$))', includes=None, excludes='(?:[^/]*\\/Procyonidae(?:/|$))'> |
|
320 | matcher: <differencematcher m1=<matcher files=['mammals'], patterns='(?:mammals(?:/|$))', includes=None, excludes=None>, m2=<matcher files=[], patterns=None, includes='(?:[^/]*\\/Procyonidae(?:/|$))', excludes=None>> | |
321 | f mammals/skunk mammals/skunk |
|
321 | f mammals/skunk mammals/skunk | |
322 | $ hg debugwalk path:mammals |
|
322 | $ hg debugwalk path:mammals | |
323 | matcher: <matcher files=['mammals'], patterns='(?:^mammals(?:/|$))', includes=None, excludes=None> |
|
323 | matcher: <matcher files=['mammals'], patterns='(?:^mammals(?:/|$))', includes=None, excludes=None> |
General Comments 0
You need to be logged in to leave comments.
Login now