Patchwork [2,of,9,V2] match: add the anyfiles() method

mail settings
Submitter Matt Harbison
Date Nov. 30, 2014, 5:52 a.m.
Message ID <3a5b52b4667dc433edd5.1417326750@Envy>
Download mbox | patch
Permalink /patch/6897/
State Changes Requested
Headers show


Matt Harbison - Nov. 30, 2014, 5:52 a.m.
# HG changeset patch
# User Matt Harbison <>
# Date 1417285680 18000
#      Sat Nov 29 13:28:00 2014 -0500
# Node ID 3a5b52b4667dc433edd5570d4d9f30be356c69ab
# Parent  36938964dbce5fc575dce8d6c07d4aec4d3d8af3
match: add the anyfiles() method

This allows a narrowmatcher adapter to tell if the original matcher had a
pattern list provided to it, regardless of the depth of the patterns or layers
of narrowing.

The addremove command and a handful of others print out the repository paths
they list relative to the cwd if patterns are provided.  If no patterns are
given, the repository path is printed without regard to cwd.  While testing the
match.files() set works for the root matcher, this isn't always accurate for
narrowmatchers due to the way it narrows the set- by filtering out files that
don't start with the narrowed path.  A deep enough traversal into subrepos, or
starting in a directory other than the root of the top repo, will eventually
filter out all of the patterns.  Therefore, the effect of testing match.files()
is that the top repo files will be printed out relative to cwd, and deep subrepo
files will be printed out relative to the root repo.

Since addremove doesn't currently support subrepos, there is no test here.  A
suitable test case will be added later.


diff --git a/mercurial/ b/mercurial/
--- a/mercurial/
+++ b/mercurial/
@@ -65,6 +65,7 @@ 
         self._anypats = bool(include or exclude)
         self._ctx = ctx
         self._always = False
+        self._anyfiles = bool(patterns)
         matchfns = []
         if include:
@@ -140,6 +141,10 @@ 
         '''Returns True if f is in .files().'''
         return f in self._fmap
+    def anyfiles(self):
+        '''Root matcher uses patterns.'''
+        return self._anyfiles
     def anypats(self):
         '''Matcher uses patterns or include/exclude.'''
         return self._anypats
@@ -183,6 +188,9 @@ 
     >>> m1.bad = bad
     >>> m2.bad('x.txt', 'No such file')
     sub/x.txt: No such file
+    >>> m3 = narrowmatcher('sub2', m2)
+    >>> m3.anyfiles()
+    True
     def __init__(self, path, matcher):
@@ -194,6 +202,7 @@ 
         self._files = [f[len(path) + 1:] for f in matcher._files
                        if f.startswith(path + "/")]
+        self._anyfiles = matcher._anyfiles
         self._anypats = matcher._anypats
         self.matchfn = lambda fn: matcher.matchfn(self._path + "/" + fn)
         self._fmap = set(self._files)