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

martinvonz (Martin von Zweigbergk) phabricator at mercurial-scm.org
Fri Dec 13 17:15:16 EST 2019


martinvonz updated this revision to Diff 18707.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D7570?vs=18696&id=18707

BRANCH
  default

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D7570/new/

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

AFFECTED FILES
  hgext/highlight/__init__.py
  mercurial/context.py
  mercurial/debugcommands.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, cwd, expr, badfn=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, cwd, expr, badfn=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(cwd, expr, badfn=badfn)]
 
         for subpath in ctx.substate:
             sub = ctx.sub(subpath)
 
             try:
-                sm = sub.matchfileset(expr, badfn=badfn)
+                sm = sub.matchfileset(cwd, expr, badfn=badfn)
                 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(cwd, kindpats, ctx=None, listsubrepos=False, badfn=None):
     '''Returns the kindpats list with the 'set' patterns expanded to matchers'''
     matchers = []
     other = []
@@ -68,11 +68,11 @@
                 raise error.ProgrammingError(
                     b"fileset expression with no context"
                 )
-            matchers.append(ctx.matchfileset(pat, badfn=badfn))
+            matchers.append(ctx.matchfileset(cwd, pat, badfn=badfn))
 
             if listsubrepos:
                 for subpath in ctx.substate:
-                    sm = ctx.sub(subpath).matchfileset(pat, badfn=badfn)
+                    sm = ctx.sub(subpath).matchfileset(cwd, pat, badfn=badfn)
                     pm = prefixdirmatcher(subpath, sm, badfn=badfn)
                     matchers.append(pm)
 
@@ -117,11 +117,11 @@
 
 
 def _buildkindpatsmatcher(
-    matchercls, root, kindpats, ctx=None, listsubrepos=False, badfn=None
+    matchercls, root, cwd, kindpats, ctx=None, listsubrepos=False, badfn=None,
 ):
     matchers = []
     fms, kindpats = _expandsets(
-        kindpats, ctx=ctx, listsubrepos=listsubrepos, badfn=badfn
+        cwd, kindpats, ctx=ctx, listsubrepos=listsubrepos, badfn=badfn,
     )
     if kindpats:
         m = matchercls(root, kindpats, badfn=badfn)
@@ -258,6 +258,7 @@
             m = _buildkindpatsmatcher(
                 patternmatcher,
                 root,
+                cwd,
                 kindpats,
                 ctx=ctx,
                 listsubrepos=listsubrepos,
@@ -273,6 +274,7 @@
         im = _buildkindpatsmatcher(
             includematcher,
             root,
+            cwd,
             kindpats,
             ctx=ctx,
             listsubrepos=listsubrepos,
@@ -284,6 +286,7 @@
         em = _buildkindpatsmatcher(
             includematcher,
             root,
+            cwd,
             kindpats,
             ctx=ctx,
             listsubrepos=listsubrepos,
diff --git a/mercurial/fileset.py b/mercurial/fileset.py
--- a/mercurial/fileset.py
+++ b/mercurial/fileset.py
@@ -520,29 +520,30 @@
 
 
 class matchctx(object):
-    def __init__(self, basectx, ctx, badfn=None):
+    def __init__(self, basectx, ctx, cwd, badfn=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"""
-        mctx = matchctx(self._basectx, self.ctx, self._badfn)
+        mctx = matchctx(self._basectx, self.ctx, self.cwd, self._badfn)
         mctx._match = match
         # leave wider status which we don't have to care
         mctx._status = self._status
         return mctx
 
     def switch(self, basectx, ctx):
-        mctx = matchctx(basectx, ctx, self._badfn)
+        mctx = matchctx(basectx, ctx, self.cwd, self._badfn)
         mctx._match = self._match
         return mctx
 
     def withstatus(self, keys):
         """Create matchctx which has precomputed status specified by the keys"""
-        mctx = matchctx(self._basectx, self.ctx, self._badfn)
+        mctx = matchctx(self._basectx, self.ctx, self.cwd, self._badfn)
         mctx._match = self._match
         mctx._buildstatus(keys)
         return mctx
@@ -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, cwd, expr, badfn=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, cwd, badfn=badfn)
     return getmatch(mctx, tree)
 
 
diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py
--- a/mercurial/debugcommands.py
+++ b/mercurial/debugcommands.py
@@ -1171,7 +1171,7 @@
         files.update(ctx.files())
         files.update(ctx.substate)
 
-    m = ctx.matchfileset(expr)
+    m = ctx.matchfileset(repo.getcwd(), expr)
     if opts[b'show_matcher'] or (opts[b'show_matcher'] is None and ui.verbose):
         ui.writenoi18n(b'* matcher:\n', stringutil.prettyrepr(m), b'\n')
     for f in sorted(files):
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, cwd, expr, badfn=None):
+        return fileset.match(self, cwd, expr, badfn=badfn)
 
     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,
diff --git a/hgext/highlight/__init__.py b/hgext/highlight/__init__.py
--- a/hgext/highlight/__init__.py
+++ b/hgext/highlight/__init__.py
@@ -52,7 +52,7 @@
     filenameonly = web.configbool(b'web', b'highlightonlymatchfilename', False)
 
     ctx = fctx.changectx()
-    m = ctx.matchfileset(expr)
+    m = ctx.matchfileset(fctx.repo().root, expr)
     if m(fctx.path()):
         highlight.pygmentize(
             field, fctx, style, tmpl, guessfilenameonly=filenameonly



To: mharbison72, #hg-reviewers, durin42
Cc: durin42, hooper, yuja, martinvonz, mercurial-devel


More information about the Mercurial-devel mailing list