Show More
@@ -45,7 +45,6 b' from . import (' | |||
|
45 | 45 | help, |
|
46 | 46 | hg, |
|
47 | 47 | logcmdutil, |
|
48 | match as matchmod, | |
|
49 | 48 | merge as mergemod, |
|
50 | 49 | mergestate as mergestatemod, |
|
51 | 50 | narrowspec, |
@@ -3371,6 +3370,7 b' def grep(ui, repo, pattern, *pats, **opt' | |||
|
3371 | 3370 | """ |
|
3372 | 3371 | opts = pycompat.byteskwargs(opts) |
|
3373 | 3372 | diff = opts.get(b'all') or opts.get(b'diff') |
|
3373 | follow = opts.get(b'follow') | |
|
3374 | 3374 | if diff and opts.get(b'all_files'): |
|
3375 | 3375 | raise error.Abort(_(b'--diff and --all-files are mutually exclusive')) |
|
3376 | 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 | 3398 | if opts.get(b'print0'): |
|
3399 | 3399 | sep = eol = b'\0' |
|
3400 | 3400 | |
|
3401 |
searcher = grepmod.grepsearcher( |
|
|
3401 | searcher = grepmod.grepsearcher( | |
|
3402 | ui, repo, regexp, all_files=all_files, diff=diff, follow=follow | |
|
3403 | ) | |
|
3402 | 3404 | |
|
3403 | 3405 | getfile = searcher._getfile |
|
3404 | 3406 | matches = searcher._matches |
@@ -3515,58 +3517,6 b' def grep(ui, repo, pattern, *pats, **opt' | |||
|
3515 | 3517 | skip = searcher._skip |
|
3516 | 3518 | revfiles = searcher._revfiles |
|
3517 | 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 | 3521 | wopts = logcmdutil.walkopts( |
|
3572 | 3522 | pats=pats, |
@@ -3582,7 +3532,9 b' def grep(ui, repo, pattern, *pats, **opt' | |||
|
3582 | 3532 | |
|
3583 | 3533 | ui.pager(b'grep') |
|
3584 | 3534 | fm = ui.formatter(b'grep', opts) |
|
3585 |
for ctx in cmdutil.walkchangerevs( |
|
|
3535 | for ctx in cmdutil.walkchangerevs( | |
|
3536 | repo, revs, makefilematcher, searcher._prep | |
|
3537 | ): | |
|
3586 | 3538 | rev = ctx.rev() |
|
3587 | 3539 | parent = ctx.p1().rev() |
|
3588 | 3540 | for fn in sorted(revfiles.get(rev, [])): |
@@ -14,6 +14,7 b' from .i18n import _' | |||
|
14 | 14 | |
|
15 | 15 | from . import ( |
|
16 | 16 | error, |
|
17 | match as matchmod, | |
|
17 | 18 | pycompat, |
|
18 | 19 | scmutil, |
|
19 | 20 | util, |
@@ -80,12 +81,23 b' def difflinestates(a, b):' | |||
|
80 | 81 | |
|
81 | 82 | |
|
82 | 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 | 95 | self._ui = ui |
|
87 | 96 | self._repo = repo |
|
88 | 97 | self._regexp = regexp |
|
98 | self._all_files = all_files | |
|
99 | self._diff = diff | |
|
100 | self._follow = follow | |
|
89 | 101 | |
|
90 | 102 | self._getfile = util.lrucachefunc(repo.file) |
|
91 | 103 | self._getrenamed = scmutil.getrenamedfn(repo) |
@@ -127,3 +139,50 b' class grepsearcher(object):' | |||
|
127 | 139 | ) |
|
128 | 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