[PATCH 1 of 2] grep: introduce a manifest search method
Steve Borho
steve at borho.org
Sat May 15 12:55:00 CDT 2010
# HG changeset patch
# User Steve Borho <steve at borho.org>
# Date 1273812860 18000
# Node ID c97ae1a76ea01b46425099ddcf3c7cb9320b8d70
# Parent ba78a1bfbfd9fbe0fa48a05b8d94e6dcf431f635
grep: introduce a manifest search method
If no annotate information is requested by the user, perform a
fast scan using a context manifest.
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -1265,18 +1265,21 @@
def grep(ui, repo, pattern, *pats, **opts):
"""search for a pattern in specified files and revisions
- Search revisions of files for a regular expression.
+ Search files or revisions for a regular expression.
This command behaves differently than Unix grep. It only accepts
- Python/Perl regexps. It searches repository history, not the
- working directory. It always prints the revision number in which a
- match appears.
-
- By default, grep only prints output for the first revision of a
- file in which it finds a match. To get it to print every revision
- that contains a change in match status ("-" for a match that
- becomes a non-match, or "+" for a non-match that becomes a match),
- use the --all flag.
+ Python/Perl regexps.
+
+ If no annotation arguments (user, rev, follow, etc) are specified,
+ grep directly searches the working directory.
+
+ When annotation is required, it searches repository history and
+ always prints the revision number in which a match appears.
+ By default when searching history, grep only prints output for the
+ first revision of a file in which it finds a match. To get it to
+ print every revision that contains a change in match status ("-" for
+ a match that becomes a non-match, or "+" for a non-match that
+ becomes a match), use the --all flag.
"""
reflags = 0
if opts.get('ignore_case'):
@@ -1292,6 +1295,37 @@
getfile = util.lrucachefunc(repo.file)
+ def manifestgrep(ui, ctx, matchfn):
+ total = len(ctx.manifest())
+ for count, fn in enumerate(ctx):
+ ui.progress(_('searching'), count, fn, _('files'), total)
+ if not matchfn(fn):
+ continue
+ data = ctx[fn].data()
+ if '\0' in data:
+ continue
+ for i, line in enumerate(data.splitlines()):
+ if opts.get('files_with_matches'):
+ if regexp.search(line):
+ ui.write(fn + eol)
+ break
+ continue
+ pos = 0
+ t = []
+ for m in regexp.finditer(line):
+ s, e = m.span()
+ t.append(line[pos:s])
+ t.append(ui.label(line[s:e], label='grep.match'))
+ pos = e
+ if pos:
+ t.append(line[pos:])
+ cols = [fn]
+ if opts.get('line_number'):
+ cols.append(str(i))
+ cols.append(''.join(t))
+ ui.write(sep.join(cols) + eol)
+ ui.progress(_('searching'), None)
+
def matchlines(body):
begin = 0
linenum = 0
@@ -1387,6 +1421,15 @@
found = False
follow = opts.get('follow')
+ for o in ('user', 'date', 'follow', 'all', 'rev'):
+ if opts.get(o):
+ break
+ else:
+ # no annotation required, do fast grep
+ ctx = repo[None]
+ manifestgrep(ui, ctx, matchfn)
+ return
+
def prep(ctx, fns):
rev = ctx.rev()
pctx = ctx.parents()[0]
More information about the Mercurial-devel
mailing list