Patchwork [5,of,6] fileset: restrict getfileset() to not return a computed set (API)

login
register
mail settings
Submitter Yuya Nishihara
Date July 7, 2018, 8:38 a.m.
Message ID <1c6906029b9d434f1249.1530952729@mimosa>
Download mbox | patch
Permalink /patch/32680/
State New
Headers show

Comments

Yuya Nishihara - July 7, 2018, 8:38 a.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1528545192 -32400
#      Sat Jun 09 20:53:12 2018 +0900
# Node ID 1c6906029b9d434f12496c440934379f2689dc0a
# Parent  609c30cc3b87da9523988402ad0a1ba8899411cc
fileset: restrict getfileset() to not return a computed set (API)

And rename the functions accordingly. fileset.match() will be changed to
not compute the initial subset.

test-glog*.t get back to the state before 9f9ffe5f687c "match: compose
'set:' pattern as matcher."

Patch

diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -181,8 +181,8 @@  class basectx(object):
     def mutable(self):
         return self.phase() > phases.public
 
-    def getfileset(self, expr):
-        return fileset.getfileset(self, expr)
+    def matchfileset(self, expr, badfn=None):
+        return fileset.match(self, expr, badfn=badfn)
 
     def obsolete(self):
         """True if the changeset is obsolete"""
diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py
--- a/mercurial/debugcommands.py
+++ b/mercurial/debugcommands.py
@@ -903,7 +903,7 @@  def debugfileset(ui, repo, expr, **opts)
         files.update(ctx.files())
         files.update(ctx.substate)
 
-    m = scmutil.matchfiles(repo, ctx.getfileset(expr))
+    m = ctx.matchfileset(expr)
     for f in sorted(files):
         if not m(f):
             continue
diff --git a/mercurial/fileset.py b/mercurial/fileset.py
--- a/mercurial/fileset.py
+++ b/mercurial/fileset.py
@@ -620,9 +620,14 @@  def _buildsubset(ctx, status):
     else:
         return list(ctx.walk(ctx.match([])))
 
-def getfileset(ctx, expr):
+def match(ctx, expr, badfn=None):
+    """Create a matcher for a single fileset expression"""
+    repo = ctx.repo()
     tree = parse(expr)
-    return getset(fullmatchctx(ctx, _buildstatus(ctx, tree)), tree)
+    fset = getset(fullmatchctx(ctx, _buildstatus(ctx, tree)), tree)
+    return matchmod.predicatematcher(repo.root, repo.getcwd(),
+                                     fset.__contains__,
+                                     predrepr='fileset', badfn=badfn)
 
 def _buildstatus(ctx, tree, basectx=None):
     # do we need status info?
diff --git a/mercurial/match.py b/mercurial/match.py
--- a/mercurial/match.py
+++ b/mercurial/match.py
@@ -40,9 +40,9 @@  def _rematcher(regex):
     except AttributeError:
         return m.match
 
-def _expandsets(kindpats, ctx, listsubrepos):
-    '''Returns the kindpats list with the 'set' patterns expanded.'''
-    fset = set()
+def _expandsets(root, cwd, kindpats, ctx, listsubrepos, badfn):
+    '''Returns the kindpats list with the 'set' patterns expanded to matchers'''
+    matchers = []
     other = []
 
     for kind, pat, source in kindpats:
@@ -50,17 +50,17 @@  def _expandsets(kindpats, ctx, listsubre
             if not ctx:
                 raise error.ProgrammingError("fileset expression with no "
                                              "context")
-            s = ctx.getfileset(pat)
-            fset.update(s)
+            matchers.append(ctx.matchfileset(pat, badfn=badfn))
 
             if listsubrepos:
                 for subpath in ctx.substate:
-                    s = ctx.sub(subpath).getfileset(pat)
-                    fset.update(subpath + '/' + f for f in s)
+                    sm = ctx.sub(subpath).matchfileset(pat, badfn=badfn)
+                    pm = prefixdirmatcher(root, cwd, subpath, sm, badfn=badfn)
+                    matchers.append(pm)
 
             continue
         other.append((kind, pat, source))
-    return fset, other
+    return matchers, other
 
 def _expandsubinclude(kindpats, root):
     '''Returns the list of subinclude matcher args and the kindpats without the
@@ -97,16 +97,15 @@  def _kindpatsalwaysmatch(kindpats):
 
 def _buildkindpatsmatcher(matchercls, root, cwd, kindpats, ctx=None,
                           listsubrepos=False, badfn=None):
-    fset, kindpats = _expandsets(kindpats, ctx, listsubrepos)
     matchers = []
+    fms, kindpats = _expandsets(root, cwd, kindpats, ctx=ctx,
+                                listsubrepos=listsubrepos, badfn=badfn)
     if kindpats:
         m = matchercls(root, cwd, kindpats, listsubrepos=listsubrepos,
                        badfn=badfn)
         matchers.append(m)
-    if fset:
-        m = predicatematcher(root, cwd, fset.__contains__,
-                             predrepr='fileset', badfn=badfn)
-        matchers.append(m)
+    if fms:
+        matchers.extend(fms)
     if not matchers:
         return nevermatcher(root, cwd, badfn=badfn)
     if len(matchers) == 1:
diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py
--- a/mercurial/subrepo.py
+++ b/mercurial/subrepo.py
@@ -318,9 +318,9 @@  class abstractsubrepo(object):
         """return file flags"""
         return ''
 
-    def getfileset(self, expr):
+    def matchfileset(self, expr, badfn=None):
         """Resolve the fileset expression for this repo"""
-        return set()
+        return matchmod.nevermatcher(self.wvfs.base, '', badfn=badfn)
 
     def printfiles(self, ui, m, fm, fmt, subrepos):
         """handle the files command for this subrepo"""
@@ -792,24 +792,30 @@  class hgsubrepo(abstractsubrepo):
         return cmdutil.files(ui, ctx, m, fm, fmt, subrepos)
 
     @annotatesubrepoerror
-    def getfileset(self, expr):
+    def matchfileset(self, expr, badfn=None):
+        repo = self._repo
         if self._ctx.rev() is None:
-            ctx = self._repo[None]
+            ctx = repo[None]
         else:
             rev = self._state[1]
-            ctx = self._repo[rev]
+            ctx = repo[rev]
 
-        files = ctx.getfileset(expr)
+        matchers = [ctx.matchfileset(expr, badfn=badfn)]
 
         for subpath in ctx.substate:
             sub = ctx.sub(subpath)
 
             try:
-                files.extend(subpath + '/' + f for f in sub.getfileset(expr))
+                sm = sub.matchfileset(expr, badfn=badfn)
+                pm = matchmod.prefixdirmatcher(repo.root, repo.getcwd(),
+                                               subpath, sm, badfn=badfn)
+                matchers.append(pm)
             except error.LookupError:
                 self.ui.status(_("skipping missing subrepository: %s\n")
                                % self.wvfs.reljoin(reporelpath(self), subpath))
-        return files
+        if len(matchers) == 1:
+            return matchers[0]
+        return matchmod.unionmatcher(matchers)
 
     def walk(self, match):
         ctx = self._repo[None]
diff --git a/tests/test-glog-beautifygraph.t b/tests/test-glog-beautifygraph.t
--- a/tests/test-glog-beautifygraph.t
+++ b/tests/test-glog-beautifygraph.t
@@ -2023,14 +2023,25 @@  Test "set:..." and parent revision
   $ testlog "set:copied()"
   []
   (func
-    (symbol 'filelog')
-    (string 'set:copied()'))
+    (symbol '_matchfiles')
+    (list
+      (string 'r:')
+      (string 'd:relpath')
+      (string 'p:set:copied()')))
   <filteredset
-    <spanset- 0:7>, set([])>
+    <spanset- 0:7>,
+    <matchfiles patterns=['set:copied()'], include=[] exclude=[], default='relpath', rev=2147483647>>
   $ testlog --include "set:copied()"
   []
-  []
-  <spanset- 0:7>
+  (func
+    (symbol '_matchfiles')
+    (list
+      (string 'r:')
+      (string 'd:relpath')
+      (string 'i:set:copied()')))
+  <filteredset
+    <spanset- 0:7>,
+    <matchfiles patterns=[], include=['set:copied()'] exclude=[], default='relpath', rev=2147483647>>
   $ testlog -r "sort(file('set:copied()'), -rev)"
   ["sort(file('set:copied()'), -rev)"]
   []
diff --git a/tests/test-glog.t b/tests/test-glog.t
--- a/tests/test-glog.t
+++ b/tests/test-glog.t
@@ -1870,14 +1870,25 @@  Test "set:..." and parent revision
   $ testlog "set:copied()"
   []
   (func
-    (symbol 'filelog')
-    (string 'set:copied()'))
+    (symbol '_matchfiles')
+    (list
+      (string 'r:')
+      (string 'd:relpath')
+      (string 'p:set:copied()')))
   <filteredset
-    <spanset- 0:7>, set([])>
+    <spanset- 0:7>,
+    <matchfiles patterns=['set:copied()'], include=[] exclude=[], default='relpath', rev=2147483647>>
   $ testlog --include "set:copied()"
   []
-  []
-  <spanset- 0:7>
+  (func
+    (symbol '_matchfiles')
+    (list
+      (string 'r:')
+      (string 'd:relpath')
+      (string 'i:set:copied()')))
+  <filteredset
+    <spanset- 0:7>,
+    <matchfiles patterns=[], include=['set:copied()'] exclude=[], default='relpath', rev=2147483647>>
   $ testlog -r "sort(file('set:copied()'), -rev)"
   ["sort(file('set:copied()'), -rev)"]
   []