changeset 32501:7095dbc266e3

match: split up main matcher into patternmatcher and includematcher At this point the includematcher is an exact copy of the main matcher class. We will specialize and simplify both classes in the following patches. This initial unmodified copy is just to make the differences clearer. We also rename the main matcher to "patternmatcher" for consistency. I may eventually merge this new includematcher back into the main matcher, but I think doing it this way makes the intermediate steps clearer regardless.
author Martin von Zweigbergk <martinvonz@google.com>
date Fri, 19 May 2017 22:36:14 -0700
parents 369c2d5eeea3
children 3026f19b4b01
files mercurial/match.py tests/test-eolfilename.t tests/test-hgignore.t tests/test-walk.t
diffstat 4 files changed, 186 insertions(+), 95 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/match.py	Thu May 18 23:39:39 2017 -0700
+++ b/mercurial/match.py	Fri May 19 22:36:14 2017 -0700
@@ -145,18 +145,18 @@
     if exact:
         m = exactmatcher(root, cwd, patterns, badfn)
     else:
-        m = matcher(root, cwd, normalize, patterns, include=None,
-                    default=default, auditor=auditor, ctx=ctx,
-                    listsubrepos=listsubrepos, warn=warn, badfn=badfn)
+        m = patternmatcher(root, cwd, normalize, patterns, include=None,
+                           default=default, auditor=auditor, ctx=ctx,
+                           listsubrepos=listsubrepos, warn=warn, badfn=badfn)
     if include:
-        im = matcher(root, cwd, normalize, [], include=include, default=default,
-                     auditor=auditor, ctx=ctx, listsubrepos=listsubrepos,
-                     warn=warn, badfn=None)
+        im = includematcher(root, cwd, normalize, [], include=include,
+                            default=default, auditor=auditor, ctx=ctx,
+                            listsubrepos=listsubrepos, warn=warn, badfn=None)
         m = intersectmatchers(m, im)
     if exclude:
-        em = matcher(root, cwd, normalize, [], include=exclude, default=default,
-                     auditor=auditor, ctx=ctx, listsubrepos=listsubrepos,
-                     warn=warn, badfn=None)
+        em = includematcher(root, cwd, normalize, [], include=exclude,
+                            default=default, auditor=auditor, ctx=ctx,
+                            listsubrepos=listsubrepos, warn=warn, badfn=None)
         m = differencematcher(m, em)
     return m
 
@@ -311,13 +311,14 @@
     def prefix(self):
         return not self.always() and not self.isexact() and not self.anypats()
 
-class matcher(basematcher):
+class patternmatcher(basematcher):
 
     def __init__(self, root, cwd, normalize, patterns, include=None,
                  default='glob', auditor=None, ctx=None,
                  listsubrepos=False, warn=None, badfn=None):
-        super(matcher, self).__init__(root, cwd, badfn,
-                                      relativeuipath=bool(include or patterns))
+        super(patternmatcher, self).__init__(root, cwd, badfn,
+                                             relativeuipath=bool(include or
+                                                                 patterns))
         if include is None:
             include = []
 
@@ -397,7 +398,97 @@
         return self._always
 
     def __repr__(self):
-        return ('<matcher patterns=%r, includes=%r>' %
+        return ('<patternmatcher patterns=%r, includes=%r>' %
+                (self.patternspat, self.includepat))
+
+class includematcher(basematcher):
+
+    def __init__(self, root, cwd, normalize, patterns, include=None,
+                 default='glob', auditor=None, ctx=None,
+                 listsubrepos=False, warn=None, badfn=None):
+        super(includematcher, self).__init__(root, cwd, badfn,
+                                             relativeuipath=bool(include or
+                                                                 patterns))
+        if include is None:
+            include = []
+
+        self._anypats = bool(include)
+        self._anyincludepats = False
+        self._always = False
+        self.patternspat = None
+        self.includepat = None
+
+        # roots are directories which are recursively included.
+        self._includeroots = set()
+        # dirs are directories which are non-recursively included.
+        self._includedirs = set()
+
+        matchfns = []
+        if include:
+            kindpats = normalize(include, 'glob', root, cwd, auditor, warn)
+            self.includepat, im = _buildmatch(ctx, kindpats, '(?:/|$)',
+                                              listsubrepos, root)
+            self._anyincludepats = _anypats(kindpats)
+            roots, dirs = _rootsanddirs(kindpats)
+            self._includeroots.update(roots)
+            self._includedirs.update(dirs)
+            matchfns.append(im)
+        if patterns:
+            kindpats = normalize(patterns, default, root, cwd, auditor, warn)
+            if not _kindpatsalwaysmatch(kindpats):
+                self._files = _explicitfiles(kindpats)
+                self._anypats = self._anypats or _anypats(kindpats)
+                self.patternspat, pm = _buildmatch(ctx, kindpats, '$',
+                                                   listsubrepos, root)
+                matchfns.append(pm)
+
+        if not matchfns:
+            m = util.always
+            self._always = True
+        elif len(matchfns) == 1:
+            m = matchfns[0]
+        else:
+            def m(f):
+                for matchfn in matchfns:
+                    if not matchfn(f):
+                        return False
+                return True
+
+        self.matchfn = m
+
+    @propertycache
+    def _dirs(self):
+        return set(util.dirs(self._fileset)) | {'.'}
+
+    def visitdir(self, dir):
+        if self.prefix() and dir in self._fileset:
+            return 'all'
+        if self._includeroots or self._includedirs:
+            if (not self._anyincludepats and
+                dir in self._includeroots):
+                # The condition above is essentially self.prefix() for includes
+                return 'all'
+            if ('.' not in self._includeroots and
+                dir not in self._includeroots and
+                dir not in self._includedirs and
+                not any(parent in self._includeroots
+                        for parent in util.finddirs(dir))):
+                return False
+        return (not self._fileset or
+                '.' 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 ('<includematcher patterns=%r, includes=%r>' %
                 (self.patternspat, self.includepat))
 
 class exactmatcher(basematcher):
--- a/tests/test-eolfilename.t	Thu May 18 23:39:39 2017 -0700
+++ b/tests/test-eolfilename.t	Fri May 19 22:36:14 2017 -0700
@@ -33,7 +33,7 @@
   [255]
   $ echo foo > "$A"
   $ hg debugwalk
-  matcher: <matcher patterns=None, includes=None>
+  matcher: <patternmatcher patterns=None, includes=None>
   f  he\r (no-eol) (esc)
   llo  he\r (no-eol) (esc)
   llo
--- a/tests/test-hgignore.t	Thu May 18 23:39:39 2017 -0700
+++ b/tests/test-hgignore.t	Fri May 19 22:36:14 2017 -0700
@@ -164,7 +164,7 @@
   A b.o
 
   $ hg debugignore
-  <matcher patterns=None, includes='(?:(?:|.*/)[^/]*(?:/|$))'>
+  <includematcher patterns=None, includes='(?:(?:|.*/)[^/]*(?:/|$))'>
 
   $ hg debugignore b.o
   b.o is ignored
--- a/tests/test-walk.t	Thu May 18 23:39:39 2017 -0700
+++ b/tests/test-walk.t	Fri May 19 22:36:14 2017 -0700
@@ -29,7 +29,7 @@
   $ hg commit -m "commit #0"
 
   $ hg debugwalk
-  matcher: <matcher patterns=None, includes=None>
+  matcher: <patternmatcher patterns=None, includes=None>
   f  beans/black                     beans/black
   f  beans/borlotti                  beans/borlotti
   f  beans/kidney                    beans/kidney
@@ -44,7 +44,7 @@
   f  mammals/Procyonidae/raccoon     mammals/Procyonidae/raccoon
   f  mammals/skunk                   mammals/skunk
   $ hg debugwalk -I.
-  matcher: <matcher patterns=None, includes='(?:)'>
+  matcher: <includematcher patterns=None, includes='(?:)'>
   f  beans/black                     beans/black
   f  beans/borlotti                  beans/borlotti
   f  beans/kidney                    beans/kidney
@@ -61,7 +61,7 @@
 
   $ cd mammals
   $ hg debugwalk
-  matcher: <matcher patterns=None, includes=None>
+  matcher: <patternmatcher patterns=None, includes=None>
   f  beans/black                     ../beans/black
   f  beans/borlotti                  ../beans/borlotti
   f  beans/kidney                    ../beans/kidney
@@ -76,7 +76,7 @@
   f  mammals/Procyonidae/raccoon     Procyonidae/raccoon
   f  mammals/skunk                   skunk
   $ hg debugwalk -X ../beans
-  matcher: <differencematcher m1=<matcher patterns=None, includes=None>, m2=<matcher patterns=None, includes='(?:beans(?:/|$))'>>
+  matcher: <differencematcher m1=<patternmatcher patterns=None, includes=None>, m2=<includematcher patterns=None, includes='(?:beans(?:/|$))'>>
   f  fennel                          ../fennel
   f  fenugreek                       ../fenugreek
   f  fiddlehead                      ../fiddlehead
@@ -85,31 +85,31 @@
   f  mammals/Procyonidae/raccoon     Procyonidae/raccoon
   f  mammals/skunk                   skunk
   $ hg debugwalk -I '*k'
-  matcher: <matcher patterns=None, includes='(?:mammals\\/[^/]*k(?:/|$))'>
+  matcher: <includematcher patterns=None, includes='(?:mammals\\/[^/]*k(?:/|$))'>
   f  mammals/skunk  skunk
   $ hg debugwalk -I 'glob:*k'
-  matcher: <matcher patterns=None, includes='(?:mammals\\/[^/]*k(?:/|$))'>
+  matcher: <includematcher patterns=None, includes='(?:mammals\\/[^/]*k(?:/|$))'>
   f  mammals/skunk  skunk
   $ hg debugwalk -I 'relglob:*k'
-  matcher: <matcher patterns=None, includes='(?:(?:|.*/)[^/]*k(?:/|$))'>
+  matcher: <includematcher patterns=None, includes='(?:(?:|.*/)[^/]*k(?:/|$))'>
   f  beans/black    ../beans/black
   f  fenugreek      ../fenugreek
   f  mammals/skunk  skunk
   $ hg debugwalk -I 'relglob:*k' .
-  matcher: <intersectionmatcher m1=<matcher patterns='(?:mammals(?:/|$))', includes=None>, m2=<matcher patterns=None, includes='(?:(?:|.*/)[^/]*k(?:/|$))'>>
+  matcher: <intersectionmatcher m1=<patternmatcher patterns='(?:mammals(?:/|$))', includes=None>, m2=<includematcher patterns=None, includes='(?:(?:|.*/)[^/]*k(?:/|$))'>>
   f  mammals/skunk  skunk
   $ hg debugwalk -I 're:.*k$'
-  matcher: <matcher patterns=None, includes='(?:.*k$)'>
+  matcher: <includematcher patterns=None, includes='(?:.*k$)'>
   f  beans/black    ../beans/black
   f  fenugreek      ../fenugreek
   f  mammals/skunk  skunk
   $ hg debugwalk -I 'relre:.*k$'
-  matcher: <matcher patterns=None, includes='(?:.*.*k$)'>
+  matcher: <includematcher patterns=None, includes='(?:.*.*k$)'>
   f  beans/black    ../beans/black
   f  fenugreek      ../fenugreek
   f  mammals/skunk  skunk
   $ hg debugwalk -I 'path:beans'
-  matcher: <matcher patterns=None, includes='(?:^beans(?:/|$))'>
+  matcher: <includematcher patterns=None, includes='(?:^beans(?:/|$))'>
   f  beans/black     ../beans/black
   f  beans/borlotti  ../beans/borlotti
   f  beans/kidney    ../beans/kidney
@@ -117,7 +117,7 @@
   f  beans/pinto     ../beans/pinto
   f  beans/turtle    ../beans/turtle
   $ hg debugwalk -I 'relpath:detour/../../beans'
-  matcher: <matcher patterns=None, includes='(?:beans(?:/|$))'>
+  matcher: <includematcher patterns=None, includes='(?:beans(?:/|$))'>
   f  beans/black     ../beans/black
   f  beans/borlotti  ../beans/borlotti
   f  beans/kidney    ../beans/kidney
@@ -126,27 +126,27 @@
   f  beans/turtle    ../beans/turtle
 
   $ hg debugwalk 'rootfilesin:'
-  matcher: <matcher patterns='(?:^[^/]+$)', includes=None>
+  matcher: <patternmatcher patterns='(?:^[^/]+$)', includes=None>
   f  fennel      ../fennel
   f  fenugreek   ../fenugreek
   f  fiddlehead  ../fiddlehead
   $ hg debugwalk -I 'rootfilesin:'
-  matcher: <matcher patterns=None, includes='(?:^[^/]+$)'>
+  matcher: <includematcher patterns=None, includes='(?:^[^/]+$)'>
   f  fennel      ../fennel
   f  fenugreek   ../fenugreek
   f  fiddlehead  ../fiddlehead
   $ hg debugwalk 'rootfilesin:.'
-  matcher: <matcher patterns='(?:^[^/]+$)', includes=None>
+  matcher: <patternmatcher patterns='(?:^[^/]+$)', includes=None>
   f  fennel      ../fennel
   f  fenugreek   ../fenugreek
   f  fiddlehead  ../fiddlehead
   $ hg debugwalk -I 'rootfilesin:.'
-  matcher: <matcher patterns=None, includes='(?:^[^/]+$)'>
+  matcher: <includematcher patterns=None, includes='(?:^[^/]+$)'>
   f  fennel      ../fennel
   f  fenugreek   ../fenugreek
   f  fiddlehead  ../fiddlehead
   $ hg debugwalk -X 'rootfilesin:'
-  matcher: <differencematcher m1=<matcher patterns=None, includes=None>, m2=<matcher patterns=None, includes='(?:^[^/]+$)'>>
+  matcher: <differencematcher m1=<patternmatcher patterns=None, includes=None>, m2=<includematcher patterns=None, includes='(?:^[^/]+$)'>>
   f  beans/black                     ../beans/black
   f  beans/borlotti                  ../beans/borlotti
   f  beans/kidney                    ../beans/kidney
@@ -158,15 +158,15 @@
   f  mammals/Procyonidae/raccoon     Procyonidae/raccoon
   f  mammals/skunk                   skunk
   $ hg debugwalk 'rootfilesin:fennel'
-  matcher: <matcher patterns='(?:^fennel/[^/]+$)', includes=None>
+  matcher: <patternmatcher patterns='(?:^fennel/[^/]+$)', includes=None>
   $ hg debugwalk -I 'rootfilesin:fennel'
-  matcher: <matcher patterns=None, includes='(?:^fennel/[^/]+$)'>
+  matcher: <includematcher patterns=None, includes='(?:^fennel/[^/]+$)'>
   $ hg debugwalk 'rootfilesin:skunk'
-  matcher: <matcher patterns='(?:^skunk/[^/]+$)', includes=None>
+  matcher: <patternmatcher patterns='(?:^skunk/[^/]+$)', includes=None>
   $ hg debugwalk -I 'rootfilesin:skunk'
-  matcher: <matcher patterns=None, includes='(?:^skunk/[^/]+$)'>
+  matcher: <includematcher patterns=None, includes='(?:^skunk/[^/]+$)'>
   $ hg debugwalk 'rootfilesin:beans'
-  matcher: <matcher patterns='(?:^beans/[^/]+$)', includes=None>
+  matcher: <patternmatcher patterns='(?:^beans/[^/]+$)', includes=None>
   f  beans/black     ../beans/black
   f  beans/borlotti  ../beans/borlotti
   f  beans/kidney    ../beans/kidney
@@ -174,7 +174,7 @@
   f  beans/pinto     ../beans/pinto
   f  beans/turtle    ../beans/turtle
   $ hg debugwalk -I 'rootfilesin:beans'
-  matcher: <matcher patterns=None, includes='(?:^beans/[^/]+$)'>
+  matcher: <includematcher patterns=None, includes='(?:^beans/[^/]+$)'>
   f  beans/black     ../beans/black
   f  beans/borlotti  ../beans/borlotti
   f  beans/kidney    ../beans/kidney
@@ -182,19 +182,19 @@
   f  beans/pinto     ../beans/pinto
   f  beans/turtle    ../beans/turtle
   $ hg debugwalk 'rootfilesin:mammals'
-  matcher: <matcher patterns='(?:^mammals/[^/]+$)', includes=None>
+  matcher: <patternmatcher patterns='(?:^mammals/[^/]+$)', includes=None>
   f  mammals/skunk  skunk
   $ hg debugwalk -I 'rootfilesin:mammals'
-  matcher: <matcher patterns=None, includes='(?:^mammals/[^/]+$)'>
+  matcher: <includematcher patterns=None, includes='(?:^mammals/[^/]+$)'>
   f  mammals/skunk  skunk
   $ hg debugwalk 'rootfilesin:mammals/'
-  matcher: <matcher patterns='(?:^mammals/[^/]+$)', includes=None>
+  matcher: <patternmatcher patterns='(?:^mammals/[^/]+$)', includes=None>
   f  mammals/skunk  skunk
   $ hg debugwalk -I 'rootfilesin:mammals/'
-  matcher: <matcher patterns=None, includes='(?:^mammals/[^/]+$)'>
+  matcher: <includematcher patterns=None, includes='(?:^mammals/[^/]+$)'>
   f  mammals/skunk  skunk
   $ hg debugwalk -X 'rootfilesin:mammals'
-  matcher: <differencematcher m1=<matcher patterns=None, includes=None>, m2=<matcher patterns=None, includes='(?:^mammals/[^/]+$)'>>
+  matcher: <differencematcher m1=<patternmatcher patterns=None, includes=None>, m2=<includematcher patterns=None, includes='(?:^mammals/[^/]+$)'>>
   f  beans/black                     ../beans/black
   f  beans/borlotti                  ../beans/borlotti
   f  beans/kidney                    ../beans/kidney
@@ -209,31 +209,31 @@
   f  mammals/Procyonidae/raccoon     Procyonidae/raccoon
 
   $ hg debugwalk .
-  matcher: <matcher patterns='(?:mammals(?:/|$))', includes=None>
+  matcher: <patternmatcher patterns='(?:mammals(?:/|$))', includes=None>
   f  mammals/Procyonidae/cacomistle  Procyonidae/cacomistle
   f  mammals/Procyonidae/coatimundi  Procyonidae/coatimundi
   f  mammals/Procyonidae/raccoon     Procyonidae/raccoon
   f  mammals/skunk                   skunk
   $ hg debugwalk -I.
-  matcher: <matcher patterns=None, includes='(?:mammals(?:/|$))'>
+  matcher: <includematcher patterns=None, includes='(?:mammals(?:/|$))'>
   f  mammals/Procyonidae/cacomistle  Procyonidae/cacomistle
   f  mammals/Procyonidae/coatimundi  Procyonidae/coatimundi
   f  mammals/Procyonidae/raccoon     Procyonidae/raccoon
   f  mammals/skunk                   skunk
   $ hg debugwalk Procyonidae
-  matcher: <matcher patterns='(?:mammals\\/Procyonidae(?:/|$))', includes=None>
+  matcher: <patternmatcher patterns='(?:mammals\\/Procyonidae(?:/|$))', includes=None>
   f  mammals/Procyonidae/cacomistle  Procyonidae/cacomistle
   f  mammals/Procyonidae/coatimundi  Procyonidae/coatimundi
   f  mammals/Procyonidae/raccoon     Procyonidae/raccoon
 
   $ cd Procyonidae
   $ hg debugwalk .
-  matcher: <matcher patterns='(?:mammals\\/Procyonidae(?:/|$))', includes=None>
+  matcher: <patternmatcher patterns='(?:mammals\\/Procyonidae(?:/|$))', includes=None>
   f  mammals/Procyonidae/cacomistle  cacomistle
   f  mammals/Procyonidae/coatimundi  coatimundi
   f  mammals/Procyonidae/raccoon     raccoon
   $ hg debugwalk ..
-  matcher: <matcher patterns='(?:mammals(?:/|$))', includes=None>
+  matcher: <patternmatcher patterns='(?:mammals(?:/|$))', includes=None>
   f  mammals/Procyonidae/cacomistle  cacomistle
   f  mammals/Procyonidae/coatimundi  coatimundi
   f  mammals/Procyonidae/raccoon     raccoon
@@ -241,7 +241,7 @@
   $ cd ..
 
   $ hg debugwalk ../beans
-  matcher: <matcher patterns='(?:beans(?:/|$))', includes=None>
+  matcher: <patternmatcher patterns='(?:beans(?:/|$))', includes=None>
   f  beans/black     ../beans/black
   f  beans/borlotti  ../beans/borlotti
   f  beans/kidney    ../beans/kidney
@@ -249,7 +249,7 @@
   f  beans/pinto     ../beans/pinto
   f  beans/turtle    ../beans/turtle
   $ hg debugwalk .
-  matcher: <matcher patterns='(?:mammals(?:/|$))', includes=None>
+  matcher: <patternmatcher patterns='(?:mammals(?:/|$))', includes=None>
   f  mammals/Procyonidae/cacomistle  Procyonidae/cacomistle
   f  mammals/Procyonidae/coatimundi  Procyonidae/coatimundi
   f  mammals/Procyonidae/raccoon     Procyonidae/raccoon
@@ -263,7 +263,7 @@
   $ cd ..
 
   $ hg debugwalk -Ibeans
-  matcher: <matcher patterns=None, includes='(?:beans(?:/|$))'>
+  matcher: <includematcher patterns=None, includes='(?:beans(?:/|$))'>
   f  beans/black     beans/black
   f  beans/borlotti  beans/borlotti
   f  beans/kidney    beans/kidney
@@ -271,56 +271,56 @@
   f  beans/pinto     beans/pinto
   f  beans/turtle    beans/turtle
   $ hg debugwalk -I '{*,{b,m}*/*}k'
-  matcher: <matcher patterns=None, includes='(?:(?:[^/]*|(?:b|m)[^/]*\\/[^/]*)k(?:/|$))'>
+  matcher: <includematcher patterns=None, includes='(?:(?:[^/]*|(?:b|m)[^/]*\\/[^/]*)k(?:/|$))'>
   f  beans/black    beans/black
   f  fenugreek      fenugreek
   f  mammals/skunk  mammals/skunk
   $ hg debugwalk -Ibeans mammals
-  matcher: <intersectionmatcher m1=<matcher patterns='(?:mammals(?:/|$))', includes=None>, m2=<matcher patterns=None, includes='(?:beans(?:/|$))'>>
+  matcher: <intersectionmatcher m1=<patternmatcher patterns='(?:mammals(?:/|$))', includes=None>, m2=<includematcher patterns=None, includes='(?:beans(?:/|$))'>>
   $ hg debugwalk -Inon-existent
-  matcher: <matcher patterns=None, includes='(?:non\\-existent(?:/|$))'>
+  matcher: <includematcher patterns=None, includes='(?:non\\-existent(?:/|$))'>
   $ hg debugwalk -Inon-existent -Ibeans/black
-  matcher: <matcher patterns=None, includes='(?:non\\-existent(?:/|$)|beans\\/black(?:/|$))'>
+  matcher: <includematcher patterns=None, includes='(?:non\\-existent(?:/|$)|beans\\/black(?:/|$))'>
   f  beans/black  beans/black
   $ hg debugwalk -Ibeans beans/black
-  matcher: <intersectionmatcher m1=<matcher patterns='(?:beans\\/black(?:/|$))', includes=None>, m2=<matcher patterns=None, includes='(?:beans(?:/|$))'>>
+  matcher: <intersectionmatcher m1=<patternmatcher patterns='(?:beans\\/black(?:/|$))', includes=None>, m2=<includematcher patterns=None, includes='(?:beans(?:/|$))'>>
   f  beans/black  beans/black  exact
   $ hg debugwalk -Ibeans/black beans
-  matcher: <intersectionmatcher m1=<matcher patterns='(?:beans(?:/|$))', includes=None>, m2=<matcher patterns=None, includes='(?:beans\\/black(?:/|$))'>>
+  matcher: <intersectionmatcher m1=<patternmatcher patterns='(?:beans(?:/|$))', includes=None>, m2=<includematcher patterns=None, includes='(?:beans\\/black(?:/|$))'>>
   f  beans/black  beans/black
   $ hg debugwalk -Xbeans/black beans
-  matcher: <differencematcher m1=<matcher patterns='(?:beans(?:/|$))', includes=None>, m2=<matcher patterns=None, includes='(?:beans\\/black(?:/|$))'>>
+  matcher: <differencematcher m1=<patternmatcher patterns='(?:beans(?:/|$))', includes=None>, m2=<includematcher patterns=None, includes='(?:beans\\/black(?:/|$))'>>
   f  beans/borlotti  beans/borlotti
   f  beans/kidney    beans/kidney
   f  beans/navy      beans/navy
   f  beans/pinto     beans/pinto
   f  beans/turtle    beans/turtle
   $ hg debugwalk -Xbeans/black -Ibeans
-  matcher: <differencematcher m1=<matcher patterns=None, includes='(?:beans(?:/|$))'>, m2=<matcher patterns=None, includes='(?:beans\\/black(?:/|$))'>>
+  matcher: <differencematcher m1=<includematcher patterns=None, includes='(?:beans(?:/|$))'>, m2=<includematcher patterns=None, includes='(?:beans\\/black(?:/|$))'>>
   f  beans/borlotti  beans/borlotti
   f  beans/kidney    beans/kidney
   f  beans/navy      beans/navy
   f  beans/pinto     beans/pinto
   f  beans/turtle    beans/turtle
   $ hg debugwalk -Xbeans/black beans/black
-  matcher: <differencematcher m1=<matcher patterns='(?:beans\\/black(?:/|$))', includes=None>, m2=<matcher patterns=None, includes='(?:beans\\/black(?:/|$))'>>
+  matcher: <differencematcher m1=<patternmatcher patterns='(?:beans\\/black(?:/|$))', includes=None>, m2=<includematcher patterns=None, includes='(?:beans\\/black(?:/|$))'>>
   f  beans/black  beans/black  exact
   $ hg debugwalk -Xbeans/black -Ibeans/black
-  matcher: <differencematcher m1=<matcher patterns=None, includes='(?:beans\\/black(?:/|$))'>, m2=<matcher patterns=None, includes='(?:beans\\/black(?:/|$))'>>
+  matcher: <differencematcher m1=<includematcher patterns=None, includes='(?:beans\\/black(?:/|$))'>, m2=<includematcher patterns=None, includes='(?:beans\\/black(?:/|$))'>>
   $ hg debugwalk -Xbeans beans/black
-  matcher: <differencematcher m1=<matcher patterns='(?:beans\\/black(?:/|$))', includes=None>, m2=<matcher patterns=None, includes='(?:beans(?:/|$))'>>
+  matcher: <differencematcher m1=<patternmatcher patterns='(?:beans\\/black(?:/|$))', includes=None>, m2=<includematcher patterns=None, includes='(?:beans(?:/|$))'>>
   f  beans/black  beans/black  exact
   $ hg debugwalk -Xbeans -Ibeans/black
-  matcher: <differencematcher m1=<matcher patterns=None, includes='(?:beans\\/black(?:/|$))'>, m2=<matcher patterns=None, includes='(?:beans(?:/|$))'>>
+  matcher: <differencematcher m1=<includematcher patterns=None, includes='(?:beans\\/black(?:/|$))'>, m2=<includematcher patterns=None, includes='(?:beans(?:/|$))'>>
   $ hg debugwalk 'glob:mammals/../beans/b*'
-  matcher: <matcher patterns='(?:beans\\/b[^/]*$)', includes=None>
+  matcher: <patternmatcher patterns='(?:beans\\/b[^/]*$)', includes=None>
   f  beans/black     beans/black
   f  beans/borlotti  beans/borlotti
   $ hg debugwalk '-X*/Procyonidae' mammals
-  matcher: <differencematcher m1=<matcher patterns='(?:mammals(?:/|$))', includes=None>, m2=<matcher patterns=None, includes='(?:[^/]*\\/Procyonidae(?:/|$))'>>
+  matcher: <differencematcher m1=<patternmatcher patterns='(?:mammals(?:/|$))', includes=None>, m2=<includematcher patterns=None, includes='(?:[^/]*\\/Procyonidae(?:/|$))'>>
   f  mammals/skunk  mammals/skunk
   $ hg debugwalk path:mammals
-  matcher: <matcher patterns='(?:^mammals(?:/|$))', includes=None>
+  matcher: <patternmatcher patterns='(?:^mammals(?:/|$))', includes=None>
   f  mammals/Procyonidae/cacomistle  mammals/Procyonidae/cacomistle
   f  mammals/Procyonidae/coatimundi  mammals/Procyonidae/coatimundi
   f  mammals/Procyonidae/raccoon     mammals/Procyonidae/raccoon
@@ -347,7 +347,7 @@
 Test absolute paths:
 
   $ hg debugwalk `pwd`/beans
-  matcher: <matcher patterns='(?:beans(?:/|$))', includes=None>
+  matcher: <patternmatcher patterns='(?:beans(?:/|$))', includes=None>
   f  beans/black     beans/black
   f  beans/borlotti  beans/borlotti
   f  beans/kidney    beans/kidney
@@ -361,7 +361,7 @@
 Test patterns:
 
   $ hg debugwalk glob:\*
-  matcher: <matcher patterns='(?:[^/]*$)', includes=None>
+  matcher: <patternmatcher patterns='(?:[^/]*$)', includes=None>
   f  fennel      fennel
   f  fenugreek   fenugreek
   f  fiddlehead  fiddlehead
@@ -371,19 +371,19 @@
   adding glob:glob
   warning: filename contains ':', which is reserved on Windows: 'glob:glob'
   $ hg debugwalk glob:\*
-  matcher: <matcher patterns='(?:[^/]*$)', includes=None>
+  matcher: <patternmatcher patterns='(?:[^/]*$)', includes=None>
   f  fennel      fennel
   f  fenugreek   fenugreek
   f  fiddlehead  fiddlehead
   f  glob:glob   glob:glob
   $ hg debugwalk glob:glob
-  matcher: <matcher patterns='(?:glob$)', includes=None>
+  matcher: <patternmatcher patterns='(?:glob$)', includes=None>
   glob: No such file or directory
   $ hg debugwalk glob:glob:glob
-  matcher: <matcher patterns='(?:glob\\:glob$)', includes=None>
+  matcher: <patternmatcher patterns='(?:glob\\:glob$)', includes=None>
   f  glob:glob  glob:glob  exact
   $ hg debugwalk path:glob:glob
-  matcher: <matcher patterns='(?:^glob\\:glob(?:/|$))', includes=None>
+  matcher: <patternmatcher patterns='(?:^glob\\:glob(?:/|$))', includes=None>
   f  glob:glob  glob:glob  exact
   $ rm glob:glob
   $ hg addremove
@@ -391,38 +391,38 @@
 #endif
 
   $ hg debugwalk 'glob:**e'
-  matcher: <matcher patterns='(?:.*e$)', includes=None>
+  matcher: <patternmatcher patterns='(?:.*e$)', includes=None>
   f  beans/turtle                    beans/turtle
   f  mammals/Procyonidae/cacomistle  mammals/Procyonidae/cacomistle
 
   $ hg debugwalk 're:.*[kb]$'
-  matcher: <matcher patterns='(?:.*[kb]$)', includes=None>
+  matcher: <patternmatcher patterns='(?:.*[kb]$)', includes=None>
   f  beans/black    beans/black
   f  fenugreek      fenugreek
   f  mammals/skunk  mammals/skunk
 
   $ hg debugwalk path:beans/black
-  matcher: <matcher patterns='(?:^beans\\/black(?:/|$))', includes=None>
+  matcher: <patternmatcher patterns='(?:^beans\\/black(?:/|$))', includes=None>
   f  beans/black  beans/black  exact
   $ hg debugwalk path:beans//black
-  matcher: <matcher patterns='(?:^beans\\/black(?:/|$))', includes=None>
+  matcher: <patternmatcher patterns='(?:^beans\\/black(?:/|$))', includes=None>
   f  beans/black  beans/black  exact
 
   $ hg debugwalk relglob:Procyonidae
-  matcher: <matcher patterns='(?:(?:|.*/)Procyonidae$)', includes=None>
+  matcher: <patternmatcher patterns='(?:(?:|.*/)Procyonidae$)', includes=None>
   $ hg debugwalk 'relglob:Procyonidae/**'
-  matcher: <matcher patterns='(?:(?:|.*/)Procyonidae\\/.*$)', includes=None>
+  matcher: <patternmatcher patterns='(?:(?:|.*/)Procyonidae\\/.*$)', includes=None>
   f  mammals/Procyonidae/cacomistle  mammals/Procyonidae/cacomistle
   f  mammals/Procyonidae/coatimundi  mammals/Procyonidae/coatimundi
   f  mammals/Procyonidae/raccoon     mammals/Procyonidae/raccoon
   $ hg debugwalk 'relglob:Procyonidae/**' fennel
-  matcher: <matcher patterns='(?:(?:|.*/)Procyonidae\\/.*$|fennel(?:/|$))', includes=None>
+  matcher: <patternmatcher patterns='(?:(?:|.*/)Procyonidae\\/.*$|fennel(?:/|$))', includes=None>
   f  fennel                          fennel                          exact
   f  mammals/Procyonidae/cacomistle  mammals/Procyonidae/cacomistle
   f  mammals/Procyonidae/coatimundi  mammals/Procyonidae/coatimundi
   f  mammals/Procyonidae/raccoon     mammals/Procyonidae/raccoon
   $ hg debugwalk beans 'glob:beans/*'
-  matcher: <matcher patterns='(?:beans(?:/|$)|beans\\/[^/]*$)', includes=None>
+  matcher: <patternmatcher patterns='(?:beans(?:/|$)|beans\\/[^/]*$)', includes=None>
   f  beans/black     beans/black
   f  beans/borlotti  beans/borlotti
   f  beans/kidney    beans/kidney
@@ -430,78 +430,78 @@
   f  beans/pinto     beans/pinto
   f  beans/turtle    beans/turtle
   $ hg debugwalk 'glob:mamm**'
-  matcher: <matcher patterns='(?:mamm.*$)', includes=None>
+  matcher: <patternmatcher patterns='(?:mamm.*$)', includes=None>
   f  mammals/Procyonidae/cacomistle  mammals/Procyonidae/cacomistle
   f  mammals/Procyonidae/coatimundi  mammals/Procyonidae/coatimundi
   f  mammals/Procyonidae/raccoon     mammals/Procyonidae/raccoon
   f  mammals/skunk                   mammals/skunk
   $ hg debugwalk 'glob:mamm**' fennel
-  matcher: <matcher patterns='(?:mamm.*$|fennel(?:/|$))', includes=None>
+  matcher: <patternmatcher patterns='(?:mamm.*$|fennel(?:/|$))', includes=None>
   f  fennel                          fennel                          exact
   f  mammals/Procyonidae/cacomistle  mammals/Procyonidae/cacomistle
   f  mammals/Procyonidae/coatimundi  mammals/Procyonidae/coatimundi
   f  mammals/Procyonidae/raccoon     mammals/Procyonidae/raccoon
   f  mammals/skunk                   mammals/skunk
   $ hg debugwalk 'glob:j*'
-  matcher: <matcher patterns='(?:j[^/]*$)', includes=None>
+  matcher: <patternmatcher patterns='(?:j[^/]*$)', includes=None>
   $ hg debugwalk NOEXIST
-  matcher: <matcher patterns='(?:NOEXIST(?:/|$))', includes=None>
+  matcher: <patternmatcher patterns='(?:NOEXIST(?:/|$))', includes=None>
   NOEXIST: * (glob)
 
 #if fifo
   $ mkfifo fifo
   $ hg debugwalk fifo
-  matcher: <matcher patterns='(?:fifo(?:/|$))', includes=None>
+  matcher: <patternmatcher patterns='(?:fifo(?:/|$))', includes=None>
   fifo: unsupported file type (type is fifo)
 #endif
 
   $ rm fenugreek
   $ hg debugwalk fenugreek
-  matcher: <matcher patterns='(?:fenugreek(?:/|$))', includes=None>
+  matcher: <patternmatcher patterns='(?:fenugreek(?:/|$))', includes=None>
   f  fenugreek  fenugreek  exact
   $ hg rm fenugreek
   $ hg debugwalk fenugreek
-  matcher: <matcher patterns='(?:fenugreek(?:/|$))', includes=None>
+  matcher: <patternmatcher patterns='(?:fenugreek(?:/|$))', includes=None>
   f  fenugreek  fenugreek  exact
   $ touch new
   $ hg debugwalk new
-  matcher: <matcher patterns='(?:new(?:/|$))', includes=None>
+  matcher: <patternmatcher patterns='(?:new(?:/|$))', includes=None>
   f  new  new  exact
 
   $ mkdir ignored
   $ touch ignored/file
   $ echo '^ignored$' > .hgignore
   $ hg debugwalk ignored
-  matcher: <matcher patterns='(?:ignored(?:/|$))', includes=None>
+  matcher: <patternmatcher patterns='(?:ignored(?:/|$))', includes=None>
   $ hg debugwalk ignored/file
-  matcher: <matcher patterns='(?:ignored\\/file(?:/|$))', includes=None>
+  matcher: <patternmatcher patterns='(?:ignored\\/file(?:/|$))', includes=None>
   f  ignored/file  ignored/file  exact
 
 Test listfile and listfile0
 
   $ $PYTHON -c "file('listfile0', 'wb').write('fenugreek\0new\0')"
   $ hg debugwalk -I 'listfile0:listfile0'
-  matcher: <matcher patterns=None, includes='(?:fenugreek(?:/|$)|new(?:/|$))'>
+  matcher: <includematcher patterns=None, includes='(?:fenugreek(?:/|$)|new(?:/|$))'>
   f  fenugreek  fenugreek
   f  new        new
   $ $PYTHON -c "file('listfile', 'wb').write('fenugreek\nnew\r\nmammals/skunk\n')"
   $ hg debugwalk -I 'listfile:listfile'
-  matcher: <matcher patterns=None, includes='(?:fenugreek(?:/|$)|new(?:/|$)|mammals\\/skunk(?:/|$))'>
+  matcher: <includematcher patterns=None, includes='(?:fenugreek(?:/|$)|new(?:/|$)|mammals\\/skunk(?:/|$))'>
   f  fenugreek      fenugreek
   f  mammals/skunk  mammals/skunk
   f  new            new
 
   $ cd ..
   $ hg debugwalk -R t t/mammals/skunk
-  matcher: <matcher patterns='(?:mammals\\/skunk(?:/|$))', includes=None>
+  matcher: <patternmatcher patterns='(?:mammals\\/skunk(?:/|$))', includes=None>
   f  mammals/skunk  t/mammals/skunk  exact
   $ mkdir t2
   $ cd t2
   $ hg debugwalk -R ../t ../t/mammals/skunk
-  matcher: <matcher patterns='(?:mammals\\/skunk(?:/|$))', includes=None>
+  matcher: <patternmatcher patterns='(?:mammals\\/skunk(?:/|$))', includes=None>
   f  mammals/skunk  ../t/mammals/skunk  exact
   $ hg debugwalk --cwd ../t mammals/skunk
-  matcher: <matcher patterns='(?:mammals\\/skunk(?:/|$))', includes=None>
+  matcher: <patternmatcher patterns='(?:mammals\\/skunk(?:/|$))', includes=None>
   f  mammals/skunk  mammals/skunk  exact
 
   $ cd ..