D2938: grep: make grep search on working directory by default

sangeet259 (Sangeet Kumar Mishra) phabricator at mercurial-scm.org
Fri Mar 23 20:05:47 UTC 2018


sangeet259 created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  The earlier behaviour of grep was quite counter intuitive as it searches
  history by default. It throws up matches from files which have been
  deleted and commited out. This patch handles only the default behaviour
  by iterating on the files being tracked by the workingctx are
  not marked for removal

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D2938

AFFECTED FILES
  mercurial/commands.py
  tests/test-grep.t

CHANGE DETAILS

diff --git a/tests/test-grep.t b/tests/test-grep.t
--- a/tests/test-grep.t
+++ b/tests/test-grep.t
@@ -340,4 +340,25 @@
   $ hg grep "MaCam" --all
   binfile.bin:0:+: Binary file matches
 
-  $ cd ..
+Test that grep searches only on working directory 
+  $ cd ..
+  $ hg init t5
+  $ cd t5
+  $ echo "mercurial revsets are awesome" > firstfile
+  $ hg add firstfile
+  $ hg commit -m  'adds firstfile'
+  $ hg rm firstfile
+  $ hg commit -m 'removes firstfile'
+  $ echo "mercurial revsets are awesome and makes life easier" > secondfile
+  $ echo "some generic text" > thirdfile
+  $ hg add secondfile thirdfile
+  $ hg commit -m 'adds two new files'
+  $ hg grep 'revsets'
+  secondfile:None:mercurial revsets are awesome and makes life easier
+  $ echo "another generic string" > fourthone
+
+Search on added but not commit i.e dirty working directory
+  $ hg add fourthone
+  $ hg grep "generic"
+  fourthone:None:another generic string
+  thirdfile:None:some generic text
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -2469,16 +2469,22 @@
         @util.cachefunc
         def binary():
             flog = getfile(fn)
-            return util.binary(flog.read(ctx.filenode(fn)))
+            try:
+                return util.binary(flog.read(ctx.filenode(fn)))
+            except AttributeError:
+                return util.binary(ctx.filectx(fn).data())
 
         fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
         if opts.get('all'):
             iter = difflinestates(pstates, states)
         else:
             iter = [('', l) for l in states]
         for change, l in iter:
             fm.startitem()
-            fm.data(node=fm.hexfunc(ctx.node()))
+            try:
+                fm.data(node=fm.hexfunc(ctx.node()))
+            except TypeError:
+                pass
             cols = [
                 ('filename', fn, True),
                 ('rev', rev, True),
@@ -2568,26 +2574,46 @@
 
     ui.pager('grep')
     fm = ui.formatter('grep', opts)
-    for ctx in cmdutil.walkchangerevs(repo, match, opts, prep):
-        rev = ctx.rev()
-        parent = ctx.p1().rev()
-        for fn in sorted(revfiles.get(rev, [])):
-            states = matches[rev][fn]
-            copy = copies.get(rev, {}).get(fn)
-            if fn in skip:
-                if copy:
-                    skip[copy] = True
+    # This if part handles the default situation,\
+    # when nothing is passed in -r or --all
+    if not bool(opts.get('rev')) and not bool(opts.get('all')):
+        rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
+        m = scmutil.match(repo[rev], pats, opts, default='relglob')
+        m.bad = lambda x, y: False
+        ctx = repo[rev]
+        ds = ctx.repo().dirstate
+
+        for fn in ctx.matches(m):
+            if rev is None and ds[fn] == 'r':
                 continue
-            pstates = matches.get(parent, {}).get(copy or fn, [])
-            if pstates or states:
-                r = display(fm, fn, ctx, pstates, states)
+            data = ctx.filectx(fn).data()
+            states = []
+            for lnum, cstart, cend, line in matchlines(data):
+                states.append(linestate(line, lnum, cstart, cend))
+            if states:
+                r = display(fm, fn, ctx, [], states)
                 found = found or r
-                if r and not opts.get('all'):
-                    skip[fn] = True
+    else :
+        for ctx in cmdutil.walkchangerevs(repo, match, opts, prep):
+            rev = ctx.rev()
+            parent = ctx.p1().rev()
+            for fn in sorted(revfiles.get(rev, [])):
+                states = matches[rev][fn]
+                copy = copies.get(rev, {}).get(fn)
+                if fn in skip:
                     if copy:
                         skip[copy] = True
-        del matches[rev]
-        del revfiles[rev]
+                    continue
+                pstates = matches.get(parent, {}).get(copy or fn, [])
+                if pstates or states:
+                    r = display(fm, fn, ctx, pstates, states)
+                    found = found or r
+                    if r and not opts.get('all'):
+                        skip[fn] = True
+                        if copy:
+                            skip[copy] = True
+            del matches[rev]
+            del revfiles[rev]
     fm.end()
 
     return not found



To: sangeet259, #hg-reviewers
Cc: mercurial-devel


More information about the Mercurial-devel mailing list