match: remove special-casing of always-matching patterns in patternmatcher
authorMartin von Zweigbergk <martinvonz@google.com>
Fri, 19 May 2017 13:16:15 -0700
changeset 37770 3fdcc34c0aba6b2110440aa601532993f0954d54
parent 37769 5f08eca8f8d3a103b6b9c08cec5d4b5a06cec4bb
child 37771 aa91085cadf32c86a1731fae3fd15bce3b5ca21a
push id525
push usergszorc@mozilla.com
push dateFri, 09 Jun 2017 06:37:32 +0000
match: remove special-casing of always-matching patterns in patternmatcher This moves the optimization for patterns that match everything to the caller, so we can remove it from patternmatcher. Note that we need to teach alwaysmatcher to use relative paths now in cases like "hg files .." from inside mercurial/, because while it still matches everything, paths should be printed relative to the working directory.
mercurial/match.py
--- a/mercurial/match.py
+++ b/mercurial/match.py
@@ -141,18 +141,21 @@ def match(root, cwd, patterns, include=N
 
                 kindpats.append((kind, pats, source))
             return kindpats
 
     if exact:
         m = exactmatcher(root, cwd, patterns, badfn)
     elif patterns:
         kindpats = normalize(patterns, default, root, cwd, auditor, warn)
-        m = patternmatcher(root, cwd, kindpats, ctx=ctx,
-                           listsubrepos=listsubrepos, badfn=badfn)
+        if _kindpatsalwaysmatch(kindpats):
+            m = alwaysmatcher(root, cwd, badfn, relativeuipath=True)
+        else:
+            m = patternmatcher(root, cwd, kindpats, ctx=ctx,
+                               listsubrepos=listsubrepos, badfn=badfn)
     else:
         # It's a little strange that no patterns means to match everything.
         # Consider changing this to match nothing (probably adding a
         # "nevermatcher").
         m = alwaysmatcher(root, cwd, badfn)
 
     if include:
         kindpats = normalize(include, 'glob', root, cwd, auditor, warn)
@@ -315,19 +318,19 @@ class basematcher(object):
         return False
 
     def prefix(self):
         return not self.always() and not self.isexact() and not self.anypats()
 
 class alwaysmatcher(basematcher):
     '''Matches everything.'''
 
-    def __init__(self, root, cwd, badfn=None):
+    def __init__(self, root, cwd, badfn=None, relativeuipath=False):
         super(alwaysmatcher, self).__init__(root, cwd, badfn,
-                                            relativeuipath=False)
+                                            relativeuipath=relativeuipath)
 
     def always(self):
         return True
 
     def matchfn(self, f):
         return True
 
     def visitdir(self, dir):
@@ -337,50 +340,38 @@ class alwaysmatcher(basematcher):
         return '<alwaysmatcher>'
 
 class patternmatcher(basematcher):
 
     def __init__(self, root, cwd, kindpats, ctx=None, listsubrepos=False,
                  badfn=None):
         super(patternmatcher, self).__init__(root, cwd, badfn)
 
-        if not _kindpatsalwaysmatch(kindpats):
-            self._files = _explicitfiles(kindpats)
-            self._anypats = _anypats(kindpats)
-            self.patternspat, pm = _buildmatch(ctx, kindpats, '$',
-                                               listsubrepos, root)
-            self._always = False
-            self.matchfn = pm
-        else:
-            self._anypats = False
-            self.patternspat = None
-            self._always = True
-            self.matchfn = lambda f: True
+        self._files = _explicitfiles(kindpats)
+        self._anypats = _anypats(kindpats)
+        self.patternspat, pm = _buildmatch(ctx, kindpats, '$', listsubrepos,
+                                           root)
+        self.matchfn = pm
 
     @propertycache
     def _dirs(self):
         return set(util.dirs(self._fileset)) | {'.'}
 
     def visitdir(self, dir):
-        if self.always():
-            return 'all'
         if self.prefix() and dir in self._fileset:
             return 'all'
         return ('.' in self._fileset or
                 dir in self._fileset or
                 dir in self._dirs or
                 any(parentdir in self._fileset
                     for parentdir in util.finddirs(dir)))
 
     def anypats(self):
         return self._anypats
 
-    def always(self):
-        return self._always
-
     def __repr__(self):
         return ('<patternmatcher patterns=%r>' % self.patternspat)
 
 class includematcher(basematcher):
 
     def __init__(self, root, cwd, kindpats, ctx=None, listsubrepos=False,
                  badfn=None):
         super(includematcher, self).__init__(root, cwd, badfn)