143 return kindpats |
143 return kindpats |
144 |
144 |
145 if exact: |
145 if exact: |
146 m = exactmatcher(root, cwd, patterns, badfn) |
146 m = exactmatcher(root, cwd, patterns, badfn) |
147 else: |
147 else: |
148 m = matcher(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 = matcher(root, cwd, normalize, [], include=include, default=default, |
152 im = includematcher(root, cwd, normalize, [], include=include, |
153 auditor=auditor, ctx=ctx, listsubrepos=listsubrepos, |
153 default=default, auditor=auditor, ctx=ctx, |
154 warn=warn, badfn=None) |
154 listsubrepos=listsubrepos, warn=warn, badfn=None) |
155 m = intersectmatchers(m, im) |
155 m = intersectmatchers(m, im) |
156 if exclude: |
156 if exclude: |
157 em = matcher(root, cwd, normalize, [], include=exclude, default=default, |
157 em = includematcher(root, cwd, normalize, [], include=exclude, |
158 auditor=auditor, ctx=ctx, listsubrepos=listsubrepos, |
158 default=default, auditor=auditor, ctx=ctx, |
159 warn=warn, badfn=None) |
159 listsubrepos=listsubrepos, warn=warn, 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) |
309 return False |
309 return False |
310 |
310 |
311 def prefix(self): |
311 def prefix(self): |
312 return not self.always() and not self.isexact() and not self.anypats() |
312 return not self.always() and not self.isexact() and not self.anypats() |
313 |
313 |
314 class matcher(basematcher): |
314 class patternmatcher(basematcher): |
315 |
315 |
316 def __init__(self, root, cwd, normalize, patterns, include=None, |
316 def __init__(self, root, cwd, normalize, patterns, include=None, |
317 default='glob', auditor=None, ctx=None, |
317 default='glob', auditor=None, ctx=None, |
318 listsubrepos=False, warn=None, badfn=None): |
318 listsubrepos=False, warn=None, badfn=None): |
319 super(matcher, self).__init__(root, cwd, badfn, |
319 super(patternmatcher, self).__init__(root, cwd, badfn, |
320 relativeuipath=bool(include or patterns)) |
320 relativeuipath=bool(include or |
|
321 patterns)) |
321 if include is None: |
322 if include is None: |
322 include = [] |
323 include = [] |
323 |
324 |
324 self._anypats = bool(include) |
325 self._anypats = bool(include) |
325 self._anyincludepats = False |
326 self._anyincludepats = False |
395 |
396 |
396 def always(self): |
397 def always(self): |
397 return self._always |
398 return self._always |
398 |
399 |
399 def __repr__(self): |
400 def __repr__(self): |
400 return ('<matcher patterns=%r, includes=%r>' % |
401 return ('<patternmatcher patterns=%r, includes=%r>' % |
|
402 (self.patternspat, self.includepat)) |
|
403 |
|
404 class includematcher(basematcher): |
|
405 |
|
406 def __init__(self, root, cwd, normalize, patterns, include=None, |
|
407 default='glob', auditor=None, ctx=None, |
|
408 listsubrepos=False, warn=None, badfn=None): |
|
409 super(includematcher, self).__init__(root, cwd, badfn, |
|
410 relativeuipath=bool(include or |
|
411 patterns)) |
|
412 if include is None: |
|
413 include = [] |
|
414 |
|
415 self._anypats = bool(include) |
|
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. |
|
422 self._includeroots = set() |
|
423 # dirs are directories which are non-recursively included. |
|
424 self._includedirs = set() |
|
425 |
|
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 |
|
463 def visitdir(self, dir): |
|
464 if self.prefix() and dir in self._fileset: |
|
465 return 'all' |
|
466 if self._includeroots or self._includedirs: |
|
467 if (not self._anyincludepats and |
|
468 dir in self._includeroots): |
|
469 # The condition above is essentially self.prefix() for includes |
|
470 return 'all' |
|
471 if ('.' not in self._includeroots and |
|
472 dir not in self._includeroots and |
|
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 |
|
484 def anypats(self): |
|
485 return self._anypats |
|
486 |
|
487 def always(self): |
|
488 return self._always |
|
489 |
|
490 def __repr__(self): |
|
491 return ('<includematcher patterns=%r, includes=%r>' % |
401 (self.patternspat, self.includepat)) |
492 (self.patternspat, self.includepat)) |
402 |
493 |
403 class exactmatcher(basematcher): |
494 class exactmatcher(basematcher): |
404 '''Matches the input files exactly. They are interpreted as paths, not |
495 '''Matches the input files exactly. They are interpreted as paths, not |
405 patterns (so no kind-prefixes). |
496 patterns (so no kind-prefixes). |