Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/commands.py @ 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 | b7808443ed6a |
comparison
equal
deleted
inserted
replaced
44909:8d552701806d | 44910:708ad5cf5e5a |
---|---|
3576 found = False | 3576 found = False |
3577 follow = opts.get(b'follow') | 3577 follow = opts.get(b'follow') |
3578 | 3578 |
3579 getrenamed = scmutil.getrenamedfn(repo) | 3579 getrenamed = scmutil.getrenamedfn(repo) |
3580 | 3580 |
3581 def get_file_content(filename, filelog, filenode, context, revision): | 3581 def readfile(ctx, fn): |
3582 try: | 3582 rev = ctx.rev() |
3583 content = filelog.read(filenode) | 3583 if rev is None: |
3584 except error.WdirUnsupported: | 3584 fctx = ctx[fn] |
3585 content = context[filename].data() | 3585 try: |
3586 except error.CensoredNodeError: | 3586 return fctx.data() |
3587 content = None | 3587 except IOError as e: |
3588 ui.warn( | 3588 if e.errno != errno.ENOENT: |
3589 _(b'cannot search in censored file: %(filename)s:%(revnum)s\n') | 3589 raise |
3590 % {b'filename': filename, b'revnum': pycompat.bytestr(revision)} | 3590 else: |
3591 ) | 3591 flog = getfile(fn) |
3592 return content | 3592 fnode = ctx.filenode(fn) |
3593 try: | |
3594 return flog.read(fnode) | |
3595 except error.CensoredNodeError: | |
3596 ui.warn( | |
3597 _( | |
3598 b'cannot search in censored file: %(filename)s:%(revnum)s\n' | |
3599 ) | |
3600 % {b'filename': fn, b'revnum': pycompat.bytestr(rev),} | |
3601 ) | |
3593 | 3602 |
3594 def prep(ctx, fns): | 3603 def prep(ctx, fns): |
3595 rev = ctx.rev() | 3604 rev = ctx.rev() |
3596 pctx = ctx.p1() | 3605 pctx = ctx.p1() |
3597 matches.setdefault(rev, {}) | 3606 matches.setdefault(rev, {}) |
3598 if diff: | 3607 if diff: |
3599 parent = pctx.rev() | 3608 parent = pctx.rev() |
3600 matches.setdefault(parent, {}) | 3609 matches.setdefault(parent, {}) |
3601 files = revfiles.setdefault(rev, []) | 3610 files = revfiles.setdefault(rev, []) |
3602 for fn in fns: | 3611 for fn in fns: |
3603 flog = getfile(fn) | 3612 # fn might not exist in the revision (could be a file removed by the |
3604 try: | 3613 # revision). We could check `fn not in ctx` even when rev is None, |
3605 fnode = ctx.filenode(fn) | 3614 # but it's less racy to protect againt that in readfile. |
3606 except error.LookupError: | 3615 if rev is not None and fn not in ctx: |
3607 continue | 3616 continue |
3608 | 3617 |
3609 copy = None | 3618 copy = None |
3610 if follow: | 3619 if follow: |
3611 copy = getrenamed(fn, rev) | 3620 copy = getrenamed(fn, rev) |
3616 if fn in skip: | 3625 if fn in skip: |
3617 continue | 3626 continue |
3618 files.append(fn) | 3627 files.append(fn) |
3619 | 3628 |
3620 if fn not in matches[rev]: | 3629 if fn not in matches[rev]: |
3621 content = get_file_content(fn, flog, fnode, ctx, rev) | 3630 grepbody(fn, rev, readfile(ctx, fn)) |
3622 grepbody(fn, rev, content) | |
3623 | 3631 |
3624 if diff: | 3632 if diff: |
3625 pfn = copy or fn | 3633 pfn = copy or fn |
3626 if pfn not in matches[parent]: | 3634 if pfn not in matches[parent] and pfn in pctx: |
3627 try: | 3635 grepbody(pfn, parent, readfile(pctx, pfn)) |
3628 pfnode = pctx.filenode(pfn) | |
3629 pcontent = get_file_content( | |
3630 pfn, flog, pfnode, pctx, parent | |
3631 ) | |
3632 grepbody(pfn, parent, pcontent) | |
3633 except error.LookupError: | |
3634 pass | |
3635 | 3636 |
3636 ui.pager(b'grep') | 3637 ui.pager(b'grep') |
3637 fm = ui.formatter(b'grep', opts) | 3638 fm = ui.formatter(b'grep', opts) |
3638 for ctx in cmdutil.walkchangerevs(repo, match, opts, prep): | 3639 for ctx in cmdutil.walkchangerevs(repo, match, opts, prep): |
3639 rev = ctx.rev() | 3640 rev = ctx.rev() |