Patchwork [4,of,9] match: handle exact matching using new exactmatcher

login
register
mail settings
Submitter via Mercurial-devel
Date May 26, 2017, 11:32 p.m.
Message ID <9f2b73c1ac41cd17c19c.1495841570@martinvonz.svl.corp.google.com>
Download mbox | patch
Permalink /patch/20943/
State Accepted
Headers show

Comments

via Mercurial-devel - May 26, 2017, 11:32 p.m.
# HG changeset patch
# User Martin von Zweigbergk <martinvonz@google.com>
# Date 1495038375 25200
#      Wed May 17 09:26:15 2017 -0700
# Node ID 9f2b73c1ac41cd17c19cc7c3bf527816b4b72ab6
# Parent  83a81ef5b6282eae5e214c64273e0f6f80310716
match: handle exact matching using new exactmatcher

Patch

diff --git a/mercurial/match.py b/mercurial/match.py
--- a/mercurial/match.py
+++ b/mercurial/match.py
@@ -142,9 +142,12 @@ 
                 kindpats.append((kind, pats, source))
             return kindpats
 
-    m = matcher(root, cwd, normalize, patterns, include=None,
-                default=default, exact=exact, auditor=auditor, ctx=ctx,
-                listsubrepos=listsubrepos, warn=warn, badfn=badfn)
+    if exact:
+        m = exactmatcher(root, cwd, patterns, badfn)
+    else:
+        m = matcher(root, cwd, normalize, patterns, include=None,
+                    default=default, exact=exact, auditor=auditor, ctx=ctx,
+                    listsubrepos=listsubrepos, warn=warn, badfn=badfn)
     if include:
         im = matcher(root, cwd, normalize, [], include=include, default=default,
                      exact=False, auditor=auditor, ctx=ctx,
@@ -158,7 +161,7 @@ 
     return m
 
 def exact(root, cwd, files, badfn=None):
-    return match(root, cwd, files, exact=True, badfn=badfn)
+    return exactmatcher(root, cwd, files, badfn=badfn)
 
 def always(root, cwd):
     return match(root, cwd, [])
@@ -406,6 +409,33 @@ 
         return ('<matcher files=%r, patterns=%r, includes=%r>' %
                 (self._files, self.patternspat, self.includepat))
 
+class exactmatcher(basematcher):
+    '''Matches the input files exactly. They are interpreted as paths, not
+    patterns (so no kind-prefixes).
+    '''
+
+    def __init__(self, root, cwd, files, badfn=None):
+        super(exactmatcher, self).__init__(root, cwd, badfn)
+
+        if isinstance(files, list):
+            self._files = files
+        else:
+            self._files = list(files)
+        self.matchfn = self.exact
+
+    @propertycache
+    def _dirs(self):
+        return set(util.dirs(self._fileset)) | {'.'}
+
+    def visitdir(self, dir):
+        return dir in self._dirs
+
+    def isexact(self):
+        return True
+
+    def __repr__(self):
+        return ('<exactmatcher files=%r>' % self._files)
+
 class differencematcher(basematcher):
     '''Composes two matchers by matching if the first matches and the second
     does not. Well, almost... If the user provides a pattern like "-X foo foo",