Mercurial > hg-stable
changeset 44910:708ad5cf5e5a
grep: grep the working copy faster
`hg grep qqqq` in the mercurial repo:
before: 0,859s
after: 0,233s
`hg grep somethingwithnomatch` in mozilla-central:
before: 51s
after: 19s
This is probably also a tiny bug fix, because the code was looking up
a node for filename `pfn` on a filelog for filename `fn`, which are
most of the time the same filename, but don't have to be.
Ignoring performance and the bug fix, the code should have the same
behavior.
Differential Revision: https://phab.mercurial-scm.org/D8545
author | Valentin Gatien-Baron <valentin.gatienbaron@gmail.com> |
---|---|
date | Sun, 17 May 2020 18:33:45 -0400 |
parents | 8d552701806d |
children | fd3b94f1712d |
files | mercurial/commands.py |
diffstat | 1 files changed, 28 insertions(+), 27 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/commands.py Sun May 17 13:10:54 2020 -0400 +++ b/mercurial/commands.py Sun May 17 18:33:45 2020 -0400 @@ -3578,18 +3578,27 @@ getrenamed = scmutil.getrenamedfn(repo) - def get_file_content(filename, filelog, filenode, context, revision): - try: - content = filelog.read(filenode) - except error.WdirUnsupported: - content = context[filename].data() - except error.CensoredNodeError: - content = None - ui.warn( - _(b'cannot search in censored file: %(filename)s:%(revnum)s\n') - % {b'filename': filename, b'revnum': pycompat.bytestr(revision)} - ) - return content + def readfile(ctx, fn): + rev = ctx.rev() + if rev is None: + fctx = ctx[fn] + try: + return fctx.data() + except IOError as e: + if e.errno != errno.ENOENT: + raise + else: + flog = getfile(fn) + fnode = ctx.filenode(fn) + try: + return flog.read(fnode) + except error.CensoredNodeError: + ui.warn( + _( + b'cannot search in censored file: %(filename)s:%(revnum)s\n' + ) + % {b'filename': fn, b'revnum': pycompat.bytestr(rev),} + ) def prep(ctx, fns): rev = ctx.rev() @@ -3600,10 +3609,10 @@ matches.setdefault(parent, {}) files = revfiles.setdefault(rev, []) for fn in fns: - flog = getfile(fn) - try: - fnode = ctx.filenode(fn) - except error.LookupError: + # fn might not exist in the revision (could be a file removed by the + # revision). We could check `fn not in ctx` even when rev is None, + # but it's less racy to protect againt that in readfile. + if rev is not None and fn not in ctx: continue copy = None @@ -3618,20 +3627,12 @@ files.append(fn) if fn not in matches[rev]: - content = get_file_content(fn, flog, fnode, ctx, rev) - grepbody(fn, rev, content) + grepbody(fn, rev, readfile(ctx, fn)) if diff: pfn = copy or fn - if pfn not in matches[parent]: - try: - pfnode = pctx.filenode(pfn) - pcontent = get_file_content( - pfn, flog, pfnode, pctx, parent - ) - grepbody(pfn, parent, pcontent) - except error.LookupError: - pass + if pfn not in matches[parent] and pfn in pctx: + grepbody(pfn, parent, readfile(pctx, pfn)) ui.pager(b'grep') fm = ui.formatter(b'grep', opts)