Show More
@@ -142,10 +142,15 b' def match(root, cwd, patterns, include=N' | |||
|
142 | 142 | kindpats.append((kind, pats, source)) |
|
143 | 143 | return kindpats |
|
144 | 144 | |
|
145 |
|
|
|
146 |
|
|
|
147 |
|
|
|
148 | warn=warn, badfn=badfn) | |
|
145 | m = matcher(root, cwd, normalize, patterns, include=include, exclude=None, | |
|
146 | default=default, exact=exact, auditor=auditor, ctx=ctx, | |
|
147 | listsubrepos=listsubrepos, 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 | 155 | def exact(root, cwd, files, badfn=None): |
|
151 | 156 | return match(root, cwd, files, exact=True, badfn=badfn) |
@@ -418,6 +423,62 b' class matcher(basematcher):' | |||
|
418 | 423 | (self._files, self.patternspat, self.includepat, |
|
419 | 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 | 482 | class subdirmatcher(basematcher): |
|
422 | 483 | """Adapt a matcher to work on a subdirectory only. |
|
423 | 484 |
@@ -76,7 +76,7 b'' | |||
|
76 | 76 | f mammals/Procyonidae/raccoon Procyonidae/raccoon |
|
77 | 77 | f mammals/skunk skunk |
|
78 | 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 | 80 | f fennel ../fennel |
|
81 | 81 | f fenugreek ../fenugreek |
|
82 | 82 | f fiddlehead ../fiddlehead |
@@ -146,7 +146,7 b'' | |||
|
146 | 146 | f fenugreek ../fenugreek |
|
147 | 147 | f fiddlehead ../fiddlehead |
|
148 | 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 | 150 | f beans/black ../beans/black |
|
151 | 151 | f beans/borlotti ../beans/borlotti |
|
152 | 152 | f beans/kidney ../beans/kidney |
@@ -194,7 +194,7 b'' | |||
|
194 | 194 | matcher: <matcher files=[], patterns=None, includes='(?:^mammals/[^/]+$)', excludes=None> |
|
195 | 195 | f mammals/skunk skunk |
|
196 | 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 | 198 | f beans/black ../beans/black |
|
199 | 199 | f beans/borlotti ../beans/borlotti |
|
200 | 200 | f beans/kidney ../beans/kidney |
@@ -289,35 +289,35 b'' | |||
|
289 | 289 | matcher: <matcher files=['beans'], patterns='(?:beans(?:/|$))', includes='(?:beans\\/black(?:/|$))', excludes=None> |
|
290 | 290 | f beans/black beans/black |
|
291 | 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 | 293 | f beans/borlotti beans/borlotti |
|
294 | 294 | f beans/kidney beans/kidney |
|
295 | 295 | f beans/navy beans/navy |
|
296 | 296 | f beans/pinto beans/pinto |
|
297 | 297 | f beans/turtle beans/turtle |
|
298 | 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 | 300 | f beans/borlotti beans/borlotti |
|
301 | 301 | f beans/kidney beans/kidney |
|
302 | 302 | f beans/navy beans/navy |
|
303 | 303 | f beans/pinto beans/pinto |
|
304 | 304 | f beans/turtle beans/turtle |
|
305 | 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 | 307 | f beans/black beans/black exact |
|
308 | 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 | 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 | 312 | f beans/black beans/black exact |
|
313 | 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 | 315 | $ hg debugwalk 'glob:mammals/../beans/b*' |
|
316 | 316 | matcher: <matcher files=['beans'], patterns='(?:beans\\/b[^/]*$)', includes=None, excludes=None> |
|
317 | 317 | f beans/black beans/black |
|
318 | 318 | f beans/borlotti beans/borlotti |
|
319 | 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 | 321 | f mammals/skunk mammals/skunk |
|
322 | 322 | $ hg debugwalk path:mammals |
|
323 | 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