diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -3398,9 +3398,11 @@ def grep(ui, repo, pattern, *pats, **opt if opts.get(b'print0'): sep = eol = b'\0' - getfile = util.lrucachefunc(repo.file) - matches = {} - copies = {} + searcher = grepmod.grepsearcher(ui, repo, regexp) + + getfile = searcher._getfile + matches = searcher._matches + copies = searcher._copies def grepbody(fn, rev, body): matches[rev].setdefault(fn, []) @@ -3520,12 +3522,12 @@ def grep(ui, repo, pattern, *pats, **opt fm.data(matched=False) fm.end() - skip = set() - revfiles = {} + skip = searcher._skip + revfiles = searcher._revfiles found = False follow = opts.get(b'follow') - getrenamed = scmutil.getrenamedfn(repo) + getrenamed = searcher._getrenamed def readfile(ctx, fn): rev = ctx.rev() diff --git a/mercurial/grep.py b/mercurial/grep.py --- a/mercurial/grep.py +++ b/mercurial/grep.py @@ -9,7 +9,11 @@ from __future__ import absolute_import import difflib -from . import pycompat +from . import ( + pycompat, + scmutil, + util, +) def matchlines(body, regexp): @@ -69,3 +73,20 @@ def difflinestates(a, b): yield (b'-', a[i]) for i in pycompat.xrange(blo, bhi): yield (b'+', b[i]) + + +class grepsearcher(object): + """Search files and revisions for lines matching the given pattern""" + + def __init__(self, ui, repo, regexp): + self._ui = ui + self._repo = repo + self._regexp = regexp + + self._getfile = util.lrucachefunc(repo.file) + self._getrenamed = scmutil.getrenamedfn(repo) + + self._matches = {} + self._copies = {} + self._skip = set() + self._revfiles = {}