##// END OF EJS Templates
grep: move prep() to grepsearcher class
Yuya Nishihara -
r46292:c694b184 default
parent child Browse files
Show More
@@ -45,7 +45,6 b' from . import ('
45 help,
45 help,
46 hg,
46 hg,
47 logcmdutil,
47 logcmdutil,
48 match as matchmod,
49 merge as mergemod,
48 merge as mergemod,
50 mergestate as mergestatemod,
49 mergestate as mergestatemod,
51 narrowspec,
50 narrowspec,
@@ -3371,6 +3370,7 b' def grep(ui, repo, pattern, *pats, **opt'
3371 """
3370 """
3372 opts = pycompat.byteskwargs(opts)
3371 opts = pycompat.byteskwargs(opts)
3373 diff = opts.get(b'all') or opts.get(b'diff')
3372 diff = opts.get(b'all') or opts.get(b'diff')
3373 follow = opts.get(b'follow')
3374 if diff and opts.get(b'all_files'):
3374 if diff and opts.get(b'all_files'):
3375 raise error.Abort(_(b'--diff and --all-files are mutually exclusive'))
3375 raise error.Abort(_(b'--diff and --all-files are mutually exclusive'))
3376 if opts.get(b'all_files') is None and not diff:
3376 if opts.get(b'all_files') is None and not diff:
@@ -3398,7 +3398,9 b' def grep(ui, repo, pattern, *pats, **opt'
3398 if opts.get(b'print0'):
3398 if opts.get(b'print0'):
3399 sep = eol = b'\0'
3399 sep = eol = b'\0'
3400
3400
3401 searcher = grepmod.grepsearcher(ui, repo, regexp)
3401 searcher = grepmod.grepsearcher(
3402 ui, repo, regexp, all_files=all_files, diff=diff, follow=follow
3403 )
3402
3404
3403 getfile = searcher._getfile
3405 getfile = searcher._getfile
3404 matches = searcher._matches
3406 matches = searcher._matches
@@ -3515,58 +3517,6 b' def grep(ui, repo, pattern, *pats, **opt'
3515 skip = searcher._skip
3517 skip = searcher._skip
3516 revfiles = searcher._revfiles
3518 revfiles = searcher._revfiles
3517 found = False
3519 found = False
3518 follow = opts.get(b'follow')
3519
3520 getrenamed = searcher._getrenamed
3521
3522 def prep(ctx, fmatch):
3523 rev = ctx.rev()
3524 pctx = ctx.p1()
3525 matches.setdefault(rev, {})
3526 if diff:
3527 parent = pctx.rev()
3528 matches.setdefault(parent, {})
3529 files = revfiles.setdefault(rev, [])
3530 if rev is None:
3531 # in `hg grep pattern`, 2/3 of the time is spent is spent in
3532 # pathauditor checks without this in mozilla-central
3533 contextmanager = repo.wvfs.audit.cached
3534 else:
3535 contextmanager = util.nullcontextmanager
3536 with contextmanager():
3537 # TODO: maybe better to warn missing files?
3538 if all_files:
3539 fmatch = matchmod.badmatch(fmatch, lambda f, msg: None)
3540 filenames = ctx.matches(fmatch)
3541 else:
3542 filenames = (f for f in ctx.files() if fmatch(f))
3543 for fn in filenames:
3544 # fn might not exist in the revision (could be a file removed by
3545 # the revision). We could check `fn not in ctx` even when rev is
3546 # None, but it's less racy to protect againt that in readfile.
3547 if rev is not None and fn not in ctx:
3548 continue
3549
3550 copy = None
3551 if follow:
3552 copy = getrenamed(fn, rev)
3553 if copy:
3554 copies.setdefault(rev, {})[fn] = copy
3555 if fn in skip:
3556 skip.add(copy)
3557 if fn in skip:
3558 continue
3559 files.append(fn)
3560
3561 if fn not in matches[rev]:
3562 searcher._grepbody(fn, rev, searcher._readfile(ctx, fn))
3563
3564 if diff:
3565 pfn = copy or fn
3566 if pfn not in matches[parent] and pfn in pctx:
3567 searcher._grepbody(
3568 pfn, parent, searcher._readfile(pctx, pfn)
3569 )
3570
3520
3571 wopts = logcmdutil.walkopts(
3521 wopts = logcmdutil.walkopts(
3572 pats=pats,
3522 pats=pats,
@@ -3582,7 +3532,9 b' def grep(ui, repo, pattern, *pats, **opt'
3582
3532
3583 ui.pager(b'grep')
3533 ui.pager(b'grep')
3584 fm = ui.formatter(b'grep', opts)
3534 fm = ui.formatter(b'grep', opts)
3585 for ctx in cmdutil.walkchangerevs(repo, revs, makefilematcher, prep):
3535 for ctx in cmdutil.walkchangerevs(
3536 repo, revs, makefilematcher, searcher._prep
3537 ):
3586 rev = ctx.rev()
3538 rev = ctx.rev()
3587 parent = ctx.p1().rev()
3539 parent = ctx.p1().rev()
3588 for fn in sorted(revfiles.get(rev, [])):
3540 for fn in sorted(revfiles.get(rev, [])):
@@ -14,6 +14,7 b' from .i18n import _'
14
14
15 from . import (
15 from . import (
16 error,
16 error,
17 match as matchmod,
17 pycompat,
18 pycompat,
18 scmutil,
19 scmutil,
19 util,
20 util,
@@ -80,12 +81,23 b' def difflinestates(a, b):'
80
81
81
82
82 class grepsearcher(object):
83 class grepsearcher(object):
83 """Search files and revisions for lines matching the given pattern"""
84 """Search files and revisions for lines matching the given pattern
84
85
85 def __init__(self, ui, repo, regexp):
86 Options:
87 - all_files to search unchanged files at that revision.
88 - diff to search files in the parent revision so diffs can be generated.
89 - follow to skip files across copies and renames.
90 """
91
92 def __init__(
93 self, ui, repo, regexp, all_files=False, diff=False, follow=False
94 ):
86 self._ui = ui
95 self._ui = ui
87 self._repo = repo
96 self._repo = repo
88 self._regexp = regexp
97 self._regexp = regexp
98 self._all_files = all_files
99 self._diff = diff
100 self._follow = follow
89
101
90 self._getfile = util.lrucachefunc(repo.file)
102 self._getfile = util.lrucachefunc(repo.file)
91 self._getrenamed = scmutil.getrenamedfn(repo)
103 self._getrenamed = scmutil.getrenamedfn(repo)
@@ -127,3 +139,50 b' class grepsearcher(object):'
127 )
139 )
128 % {b'filename': fn, b'revnum': pycompat.bytestr(rev)}
140 % {b'filename': fn, b'revnum': pycompat.bytestr(rev)}
129 )
141 )
142
143 def _prep(self, ctx, fmatch):
144 rev = ctx.rev()
145 pctx = ctx.p1()
146 self._matches.setdefault(rev, {})
147 if self._diff:
148 parent = pctx.rev()
149 self._matches.setdefault(parent, {})
150 files = self._revfiles.setdefault(rev, [])
151 if rev is None:
152 # in `hg grep pattern`, 2/3 of the time is spent is spent in
153 # pathauditor checks without this in mozilla-central
154 contextmanager = self._repo.wvfs.audit.cached
155 else:
156 contextmanager = util.nullcontextmanager
157 with contextmanager():
158 # TODO: maybe better to warn missing files?
159 if self._all_files:
160 fmatch = matchmod.badmatch(fmatch, lambda f, msg: None)
161 filenames = ctx.matches(fmatch)
162 else:
163 filenames = (f for f in ctx.files() if fmatch(f))
164 for fn in filenames:
165 # fn might not exist in the revision (could be a file removed by
166 # the revision). We could check `fn not in ctx` even when rev is
167 # None, but it's less racy to protect againt that in readfile.
168 if rev is not None and fn not in ctx:
169 continue
170
171 copy = None
172 if self._follow:
173 copy = self._getrenamed(fn, rev)
174 if copy:
175 self._copies.setdefault(rev, {})[fn] = copy
176 if fn in self._skip:
177 self._skip.add(copy)
178 if fn in self._skip:
179 continue
180 files.append(fn)
181
182 if fn not in self._matches[rev]:
183 self._grepbody(fn, rev, self._readfile(ctx, fn))
184
185 if self._diff:
186 pfn = copy or fn
187 if pfn not in self._matches[parent] and pfn in pctx:
188 self._grepbody(pfn, parent, self._readfile(pctx, pfn))
General Comments 0
You need to be logged in to leave comments. Login now