D7570: match: resolve filesets against the passed `cwd`, not the current one

mharbison72 (Matt Harbison) phabricator at mercurial-scm.org
Sat Dec 7 03:16:56 UTC 2019


mharbison72 created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This allows filesets to be resolved relative to `repo.root`, the same as other
  patterns are since f02d3c0eed18 <https://phab.mercurial-scm.org/rHGf02d3c0eed18be9a7a0790405e5de284d0727713>.  The current example in contrib/ wasn't working
  from the tests directory because of this.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D7570

AFFECTED FILES
  mercurial/context.py
  mercurial/fileset.py
  mercurial/match.py
  mercurial/subrepo.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -1333,24 +1333,20 @@
 Apparently fixing p1() and its descendants doesn't include wdir() unless
 explicitly stated.
 
-BROKEN: fileset matches aren't relative to repo.root for commits
-
   $ hg fix -r '.::'
   $ hg cat -r . ../quux
   quux
   $ hg cat -r tip ../quux
-  quux
+  fs: $TESTTMP/subprocesscwd
   $ cat ../quux
   quux
 
 Clean files are not fixed unless explicitly named
   $ echo 'dirty' > ../quux
 
-BROKEN: fileset matches aren't relative to repo.root for wdir
-
   $ hg fix --working-dir
   $ cat ../quux
-  dirty
+  fs: $TESTTMP/subprocesscwd
 
   $ cd ../..
 
diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py
--- a/mercurial/subrepo.py
+++ b/mercurial/subrepo.py
@@ -355,7 +355,7 @@
         """return file flags"""
         return b''
 
-    def matchfileset(self, expr, badfn=None):
+    def matchfileset(self, expr, badfn=None, cwd=None):
         """Resolve the fileset expression for this repo"""
         return matchmod.never(badfn=badfn)
 
@@ -894,20 +894,20 @@
         return cmdutil.files(ui, ctx, m, uipathfn, fm, fmt, subrepos)
 
     @annotatesubrepoerror
-    def matchfileset(self, expr, badfn=None):
+    def matchfileset(self, expr, badfn=None, cwd=None):
         if self._ctx.rev() is None:
             ctx = self._repo[None]
         else:
             rev = self._state[1]
             ctx = self._repo[rev]
 
-        matchers = [ctx.matchfileset(expr, badfn=badfn)]
+        matchers = [ctx.matchfileset(expr, badfn=badfn, cwd=cwd)]
 
         for subpath in ctx.substate:
             sub = ctx.sub(subpath)
 
             try:
-                sm = sub.matchfileset(expr, badfn=badfn)
+                sm = sub.matchfileset(expr, badfn=badfn, cwd=cwd)
                 pm = matchmod.prefixdirmatcher(subpath, sm, badfn=badfn)
                 matchers.append(pm)
             except error.LookupError:
diff --git a/mercurial/match.py b/mercurial/match.py
--- a/mercurial/match.py
+++ b/mercurial/match.py
@@ -57,7 +57,7 @@
         return m.match
 
 
-def _expandsets(kindpats, ctx=None, listsubrepos=False, badfn=None):
+def _expandsets(kindpats, ctx=None, listsubrepos=False, badfn=None, cwd=None):
     '''Returns the kindpats list with the 'set' patterns expanded to matchers'''
     matchers = []
     other = []
@@ -68,11 +68,13 @@
                 raise error.ProgrammingError(
                     b"fileset expression with no context"
                 )
-            matchers.append(ctx.matchfileset(pat, badfn=badfn))
+            matchers.append(ctx.matchfileset(pat, badfn=badfn, cwd=cwd))
 
             if listsubrepos:
                 for subpath in ctx.substate:
-                    sm = ctx.sub(subpath).matchfileset(pat, badfn=badfn)
+                    sm = ctx.sub(subpath).matchfileset(
+                        pat, badfn=badfn, cwd=cwd
+                    )
                     pm = prefixdirmatcher(subpath, sm, badfn=badfn)
                     matchers.append(pm)
 
@@ -117,11 +119,17 @@
 
 
 def _buildkindpatsmatcher(
-    matchercls, root, kindpats, ctx=None, listsubrepos=False, badfn=None
+    matchercls,
+    root,
+    kindpats,
+    ctx=None,
+    listsubrepos=False,
+    badfn=None,
+    cwd=None,
 ):
     matchers = []
     fms, kindpats = _expandsets(
-        kindpats, ctx=ctx, listsubrepos=listsubrepos, badfn=badfn
+        kindpats, ctx=ctx, listsubrepos=listsubrepos, badfn=badfn, cwd=cwd,
     )
     if kindpats:
         m = matchercls(root, kindpats, badfn=badfn)
@@ -260,6 +268,7 @@
                 ctx=ctx,
                 listsubrepos=listsubrepos,
                 badfn=badfn,
+                cwd=cwd,
             )
     else:
         # It's a little strange that no patterns means to match everything.
@@ -275,6 +284,7 @@
             ctx=ctx,
             listsubrepos=listsubrepos,
             badfn=None,
+            cwd=cwd,
         )
         m = intersectmatchers(m, im)
     if exclude:
@@ -286,6 +296,7 @@
             ctx=ctx,
             listsubrepos=listsubrepos,
             badfn=None,
+            cwd=cwd,
         )
         m = differencematcher(m, em)
     return m
diff --git a/mercurial/fileset.py b/mercurial/fileset.py
--- a/mercurial/fileset.py
+++ b/mercurial/fileset.py
@@ -520,12 +520,13 @@
 
 
 class matchctx(object):
-    def __init__(self, basectx, ctx, badfn=None):
+    def __init__(self, basectx, ctx, badfn=None, cwd=None):
         self._basectx = basectx
         self.ctx = ctx
         self._badfn = badfn
         self._match = None
         self._status = None
+        self.cwd = cwd
 
     def narrowed(self, match):
         """Create matchctx for a sub-tree narrowed by the given matcher"""
@@ -560,7 +561,7 @@
         return self._status
 
     def matcher(self, patterns):
-        return self.ctx.match(patterns, badfn=self._badfn)
+        return self.ctx.match(patterns, badfn=self._badfn, cwd=self.cwd)
 
     def predicate(self, predfn, predrepr=None, cache=False):
         """Create a matcher to select files by predfn(filename)"""
@@ -617,12 +618,12 @@
         return matchmod.never(badfn=self._badfn)
 
 
-def match(ctx, expr, badfn=None):
+def match(ctx, expr, badfn=None, cwd=None):
     """Create a matcher for a single fileset expression"""
     tree = filesetlang.parse(expr)
     tree = filesetlang.analyze(tree)
     tree = filesetlang.optimize(tree)
-    mctx = matchctx(ctx.p1(), ctx, badfn=badfn)
+    mctx = matchctx(ctx.p1(), ctx, badfn=badfn, cwd=cwd)
     return getmatch(mctx, tree)
 
 
diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -200,8 +200,8 @@
     def mutable(self):
         return self.phase() > phases.public
 
-    def matchfileset(self, expr, badfn=None):
-        return fileset.match(self, expr, badfn=badfn)
+    def matchfileset(self, expr, badfn=None, cwd=None):
+        return fileset.match(self, expr, badfn=badfn, cwd=cwd)
 
     def obsolete(self):
         """True if the changeset is obsolete"""
@@ -328,11 +328,14 @@
         default=b'glob',
         listsubrepos=False,
         badfn=None,
+        cwd=None,
     ):
         r = self._repo
+        if not cwd:
+            cwd = r.getcwd()
         return matchmod.match(
             r.root,
-            r.getcwd(),
+            cwd,
             pats,
             include,
             exclude,
@@ -1694,15 +1697,18 @@
         default=b'glob',
         listsubrepos=False,
         badfn=None,
+        cwd=None,
     ):
         r = self._repo
+        if not cwd:
+            cwd = r.getcwd()
 
         # Only a case insensitive filesystem needs magic to translate user input
         # to actual case in the filesystem.
         icasefs = not util.fscasesensitive(r.root)
         return matchmod.match(
             r.root,
-            r.getcwd(),
+            cwd,
             pats,
             include,
             exclude,



To: mharbison72, #hg-reviewers
Cc: mercurial-devel


More information about the Mercurial-devel mailing list