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 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/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/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/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, @@ -942,7 +945,7 @@ The paths are remapped to remove/insert the path as needed: >>> from . import pycompat - >>> m1 = match(b'/root', b'', [b'a.txt', b'sub/b.txt']) + >>> m1 = match(b'/root', b'', [b'a.txt', b'sub/b.txt'], auditor=lambda name: None) >>> m2 = subdirmatcher(b'sub', m1) >>> m2(b'a.txt') False 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) @@ -896,20 +896,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/tests/test-fix.t b/tests/test-fix.t --- a/tests/test-fix.t +++ b/tests/test-fix.t @@ -1335,24 +1335,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 ../..