revset: don't recreate matcher for every revision
The matcher variable 'm' in checkstatus() is reset to None on each
call, so the caching of the matcher no longer happens as it was
intended. This seems to be a regression in
ed7b674824a3 (revset: added
lazyset implementation to checkstatus, 2014-01-03).
Fix by moving the cached matcher into the enclosing function so it's
actually cached across calls. This speeds up
hg log -r 'modifies(mercurial/context.py)' >/dev/null
from 7.5s to 4s.
Also see similar fix in
f2aeff8a87b6 (revset: avoid recalculating
filesets, 2014-10-22).
--- a/mercurial/revset.py Sat Nov 01 02:43:08 2014 +0900
+++ b/mercurial/revset.py Fri Oct 31 10:41:36 2014 -0700
@@ -526,14 +526,15 @@
def checkstatus(repo, subset, pat, field):
hasset = matchmod.patkind(pat) == 'set'
+ mcache = [None]
def matches(x):
- m = None
- fname = None
c = repo[x]
- if not m or hasset:
- m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c)
- if not m.anypats() and len(m.files()) == 1:
- fname = m.files()[0]
+ if not mcache[0] or hasset:
+ mcache[0] = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c)
+ m = mcache[0]
+ fname = None
+ if not m.anypats() and len(m.files()) == 1:
+ fname = m.files()[0]
if fname is not None:
if fname not in c.files():
return False