changeset 2870:8eaaf1321bfe

grep: add --follow support.
author Brendan Cully <brendan@kublai.com>
date Sat, 12 Aug 2006 15:01:46 -0700
parents 81f351c5264d
children ffa2be02c4e5
files mercurial/commands.py tests/test-grep tests/test-grep.out
diffstat 3 files changed, 39 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/commands.py	Sat Aug 12 13:51:14 2006 -0700
+++ b/mercurial/commands.py	Sat Aug 12 15:01:46 2006 -0700
@@ -1649,6 +1649,7 @@
             return self.line == other.line
 
     matches = {}
+    copies = {}
     def grepbody(fn, rev, body):
         matches[rev].setdefault(fn, [])
         m = matches[rev][fn]
@@ -1709,10 +1710,12 @@
     changeiter, getchange, matchfn = walkchangerevs(ui, repo, pats, opts)
     count = 0
     incrementing = False
+    follow = opts.get('follow')
     for st, rev, fns in changeiter:
         if st == 'window':
             incrementing = rev
             matches.clear()
+            copies.clear()
         elif st == 'add':
             change = repo.changelog.read(repo.lookup(str(rev)))
             mf = repo.manifest.read(change[0])
@@ -1721,22 +1724,34 @@
                 if fn in skip:
                     continue
                 fstate.setdefault(fn, {})
+                copies.setdefault(rev, {})
                 try:
                     grepbody(fn, rev, getfile(fn).read(mf[fn]))
+                    if follow:
+                        copied = getfile(fn).renamed(mf[fn])
+                        if copied:
+                            copies[rev][fn] = copied[0]
                 except KeyError:
                     pass
         elif st == 'iter':
             states = matches[rev].items()
             states.sort()
             for fn, m in states:
+                copy = copies[rev].get(fn)
                 if fn in skip:
+                    if copy:
+                        skip[copy] = True
                     continue
                 if incrementing or not opts['all'] or fstate[fn]:
                     pos, neg = display(fn, rev, m, fstate[fn])
                     count += pos + neg
                     if pos and not opts['all']:
                         skip[fn] = True
+                        if copy:
+                            skip[copy] = True
                 fstate[fn] = m
+                if copy:
+                    fstate[copy] = m
                 prev[fn] = rev
 
     if not incrementing:
@@ -1745,7 +1760,8 @@
         for fn, state in fstate:
             if fn in skip:
                 continue
-            display(fn, rev, {}, state)
+            if fn not in copies[prev[fn]]:
+                display(fn, rev, {}, state)
     return (count == 0 and 1) or 0
 
 def heads(ui, repo, **opts):
@@ -3107,6 +3123,8 @@
         (grep,
          [('0', 'print0', None, _('end fields with NUL')),
           ('', 'all', None, _('print all revisions that match')),
+          ('f', 'follow', None,
+           _('follow changeset history, or file history across copies and renames')),
           ('i', 'ignore-case', None, _('ignore case when matching')),
           ('l', 'files-with-matches', None,
            _('print only filenames and revs that match')),
--- a/tests/test-grep	Sat Aug 12 13:51:14 2006 -0700
+++ b/tests/test-grep	Sat Aug 12 15:01:46 2006 -0700
@@ -20,3 +20,11 @@
 hg grep port port
 hg grep --all -nu port port
 hg grep import port
+
+hg cp port port2
+hg commit -m 4 -u spam -d '5 0'
+echo '% follow'
+hg grep -f 'import$' port2
+echo deport >> port2
+hg commit -m 5 -u eggs -d '6 0'
+hg grep -f --all -nu port port2
--- a/tests/test-grep.out	Sat Aug 12 13:51:14 2006 -0700
+++ b/tests/test-grep.out	Sat Aug 12 15:01:46 2006 -0700
@@ -11,3 +11,15 @@
 port:1:2:+:eggs:export
 port:0:1:+:eggs:import
 port:4:import/export
+% follow
+port:0:import
+port2:6:4:+:eggs:deport
+port:4:4:-:spam:import/export
+port:3:4:+:eggs:import/export
+port:2:1:-:spam:import
+port:2:2:-:spam:export
+port:2:1:+:spam:export
+port:2:2:+:spam:vaportight
+port:2:3:+:spam:import/export
+port:1:2:+:eggs:export
+port:0:1:+:eggs:import