147 else: |
147 else: |
148 m = patternmatcher(root, cwd, normalize, patterns, include=None, |
148 m = patternmatcher(root, cwd, normalize, patterns, include=None, |
149 default=default, auditor=auditor, ctx=ctx, |
149 default=default, auditor=auditor, ctx=ctx, |
150 listsubrepos=listsubrepos, warn=warn, badfn=badfn) |
150 listsubrepos=listsubrepos, warn=warn, badfn=badfn) |
151 if include: |
151 if include: |
152 im = includematcher(root, cwd, normalize, [], include=include, |
152 im = includematcher(root, cwd, normalize, include, auditor=auditor, |
153 default=default, auditor=auditor, ctx=ctx, |
153 ctx=ctx, listsubrepos=listsubrepos, warn=warn, |
154 listsubrepos=listsubrepos, warn=warn, badfn=None) |
154 badfn=None) |
155 m = intersectmatchers(m, im) |
155 m = intersectmatchers(m, im) |
156 if exclude: |
156 if exclude: |
157 em = includematcher(root, cwd, normalize, [], include=exclude, |
157 em = includematcher(root, cwd, normalize, exclude, auditor=auditor, |
158 default=default, auditor=auditor, ctx=ctx, |
158 ctx=ctx, listsubrepos=listsubrepos, warn=warn, |
159 listsubrepos=listsubrepos, warn=warn, badfn=None) |
159 badfn=None) |
160 m = differencematcher(m, em) |
160 m = differencematcher(m, em) |
161 return m |
161 return m |
162 |
162 |
163 def exact(root, cwd, files, badfn=None): |
163 def exact(root, cwd, files, badfn=None): |
164 return exactmatcher(root, cwd, files, badfn=badfn) |
164 return exactmatcher(root, cwd, files, badfn=badfn) |
401 return ('<patternmatcher patterns=%r, includes=%r>' % |
401 return ('<patternmatcher patterns=%r, includes=%r>' % |
402 (self.patternspat, self.includepat)) |
402 (self.patternspat, self.includepat)) |
403 |
403 |
404 class includematcher(basematcher): |
404 class includematcher(basematcher): |
405 |
405 |
406 def __init__(self, root, cwd, normalize, patterns, include=None, |
406 def __init__(self, root, cwd, normalize, include, auditor=None, ctx=None, |
407 default='glob', auditor=None, ctx=None, |
|
408 listsubrepos=False, warn=None, badfn=None): |
407 listsubrepos=False, warn=None, badfn=None): |
409 super(includematcher, self).__init__(root, cwd, badfn, |
408 super(includematcher, self).__init__(root, cwd, badfn) |
410 relativeuipath=bool(include or |
409 |
411 patterns)) |
410 kindpats = normalize(include, 'glob', root, cwd, auditor, warn) |
412 if include is None: |
411 self.includepat, im = _buildmatch(ctx, kindpats, '(?:/|$)', |
413 include = [] |
412 listsubrepos, root) |
414 |
413 self._anyincludepats = _anypats(kindpats) |
415 self._anypats = bool(include) |
414 roots, dirs = _rootsanddirs(kindpats) |
416 self._anyincludepats = False |
|
417 self._always = False |
|
418 self.patternspat = None |
|
419 self.includepat = None |
|
420 |
|
421 # roots are directories which are recursively included. |
415 # roots are directories which are recursively included. |
422 self._includeroots = set() |
416 self._includeroots = set(roots) |
423 # dirs are directories which are non-recursively included. |
417 # dirs are directories which are non-recursively included. |
424 self._includedirs = set() |
418 self._includedirs = set(dirs) |
425 |
419 self.matchfn = im |
426 matchfns = [] |
|
427 if include: |
|
428 kindpats = normalize(include, 'glob', root, cwd, auditor, warn) |
|
429 self.includepat, im = _buildmatch(ctx, kindpats, '(?:/|$)', |
|
430 listsubrepos, root) |
|
431 self._anyincludepats = _anypats(kindpats) |
|
432 roots, dirs = _rootsanddirs(kindpats) |
|
433 self._includeroots.update(roots) |
|
434 self._includedirs.update(dirs) |
|
435 matchfns.append(im) |
|
436 if patterns: |
|
437 kindpats = normalize(patterns, default, root, cwd, auditor, warn) |
|
438 if not _kindpatsalwaysmatch(kindpats): |
|
439 self._files = _explicitfiles(kindpats) |
|
440 self._anypats = self._anypats or _anypats(kindpats) |
|
441 self.patternspat, pm = _buildmatch(ctx, kindpats, '$', |
|
442 listsubrepos, root) |
|
443 matchfns.append(pm) |
|
444 |
|
445 if not matchfns: |
|
446 m = util.always |
|
447 self._always = True |
|
448 elif len(matchfns) == 1: |
|
449 m = matchfns[0] |
|
450 else: |
|
451 def m(f): |
|
452 for matchfn in matchfns: |
|
453 if not matchfn(f): |
|
454 return False |
|
455 return True |
|
456 |
|
457 self.matchfn = m |
|
458 |
|
459 @propertycache |
|
460 def _dirs(self): |
|
461 return set(util.dirs(self._fileset)) | {'.'} |
|
462 |
420 |
463 def visitdir(self, dir): |
421 def visitdir(self, dir): |
464 if self.prefix() and dir in self._fileset: |
422 if not self._anyincludepats and dir in self._includeroots: |
|
423 # The condition above is essentially self.prefix() for includes |
465 return 'all' |
424 return 'all' |
466 if self._includeroots or self._includedirs: |
425 if ('.' not in self._includeroots and |
467 if (not self._anyincludepats and |
426 dir not in self._includeroots and |
468 dir in self._includeroots): |
427 dir not in self._includedirs and |
469 # The condition above is essentially self.prefix() for includes |
428 not any(parent in self._includeroots |
470 return 'all' |
429 for parent in util.finddirs(dir))): |
471 if ('.' not in self._includeroots and |
430 return False |
472 dir not in self._includeroots and |
431 return True |
473 dir not in self._includedirs and |
|
474 not any(parent in self._includeroots |
|
475 for parent in util.finddirs(dir))): |
|
476 return False |
|
477 return (not self._fileset or |
|
478 '.' in self._fileset or |
|
479 dir in self._fileset or |
|
480 dir in self._dirs or |
|
481 any(parentdir in self._fileset |
|
482 for parentdir in util.finddirs(dir))) |
|
483 |
432 |
484 def anypats(self): |
433 def anypats(self): |
485 return self._anypats |
434 return True |
486 |
|
487 def always(self): |
|
488 return self._always |
|
489 |
435 |
490 def __repr__(self): |
436 def __repr__(self): |
491 return ('<includematcher patterns=%r, includes=%r>' % |
437 return ('<includematcher includes=%r>' % self.includepat) |
492 (self.patternspat, self.includepat)) |
|
493 |
438 |
494 class exactmatcher(basematcher): |
439 class exactmatcher(basematcher): |
495 '''Matches the input files exactly. They are interpreted as paths, not |
440 '''Matches the input files exactly. They are interpreted as paths, not |
496 patterns (so no kind-prefixes). |
441 patterns (so no kind-prefixes). |
497 ''' |
442 ''' |