mercurial/match.py
changeset 32501 7095dbc266e3
parent 32500 369c2d5eeea3
child 32502 3026f19b4b01
equal deleted inserted replaced
32500:369c2d5eeea3 32501:7095dbc266e3
   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).