Patchwork (issue3253) 'hg cat -r [rev]' doesn't work with renamed files

login
register
mail settings
Submitter Iulian Stana
Date July 6, 2013, 4:10 p.m.
Message ID <5806bef2e589c2cdaf9b.1373127055@doppler>
Download mbox | patch
Permalink /patch/1801/
State Changes Requested, archived
Headers show

Comments

Iulian Stana - July 6, 2013, 4:10 p.m.
# HG changeset patch
# User Iulian Stana <julian.stana@gmail.com>
# Date 1373125686 -10800
#      Sat Jul 06 18:48:06 2013 +0300
# Node ID 5806bef2e589c2cdaf9bb885bc3548c6b86a760c
# Parent  648d1974b3f328947ee6cf2d00c66815a33cd208
(issue3253) 'hg cat -r [rev]' doesn't work with renamed files

Adding -f (follow) option to the cat command. Adding the possibility to 'cat' a
file that was renamed.
If you choose -f option you must specify a file from the parent revision.
Matt Mackall - July 8, 2013, 8:41 p.m.
On Sat, 2013-07-06 at 19:10 +0300, Iulian Stana wrote:
> (issue3253) 'hg cat -r [rev]' doesn't work with renamed files

This format is so, so wrong.
Iulian Stana - July 8, 2013, 8:50 p.m.
> This format is so, so wrong.
>
> Yeah.... probably it's match better with '(issue3252) cat: doesn't work
with renamed files'

What about the code?
Matt Mackall - July 8, 2013, 9:33 p.m.
On Mon, 2013-07-08 at 23:50 +0300, Iulian Stana wrote:
> 
>         This format is so, so wrong.
>         
> Yeah.... probably it's match better with '(issue3252) cat: doesn't
> work with renamed files'

First:

$ hg log --template '{desc|firstline}\n' | grep '^[(]' | wc
      0       0       0
$ hg log --template '{desc|firstline}\n' | grep '[)]$' | wc
   1546   12462   91687

We have a huge example corpus of commit summaries, and none of them have
the issue bit at the beginning.

Second: the actual text here is completely unhelpful. Are you saying it
doesn't work before or after this patch? Is that a good thing or a bad
thing? If it's a bad thing that you fixed, how did you fix it? Instead
-describe what you did-. For instance:

cat: added --follow flag (issue3253)

> What about the code?  

Insofar as I think getting the basics of patch submission down is much
more important for your GSoC project than this particular patch, I
skipped reading the actual code for now.

Patch

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -1008,7 +1008,7 @@ 
 class FileWalkError(Exception):
     pass
 
-def walkfilerevs(repo, match, follow, revs, fncache):
+def walkfilerevs(repo, match, follow, revs, fncache, filename=False):
     '''Walks the file history for the matched files.
 
     Returns the changeset revs that are involved in the file history.
@@ -1100,7 +1100,10 @@ 
                     ancestors.update(flparentlinkrevs)
 
             fncache.setdefault(rev, []).append(file_)
-            wanted.add(rev)
+            if filename:
+                wanted.add((rev, file_))
+            else:
+                wanted.add(rev)
             if copied:
                 copies.append(copied)
 
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -1125,7 +1125,10 @@ 
     changegroup.writebundle(cg, fname, bundletype)
 
 @command('cat',
-    [('o', 'output', '',
+    [('f', 'follow', None,
+    _('follow changeset history,'
+    ' or file history across copies and renames')),
+    ('o', 'output', '',
      _('print output to file with formatted name'), _('FORMAT')),
     ('r', 'rev', '', _('print the given revision'), _('REV')),
     ('', 'decode', None, _('apply any matching decode filter')),
@@ -1150,8 +1153,8 @@ 
     """
     ctx = scmutil.revsingle(repo, opts.get('rev'))
     err = 1
-    m = scmutil.match(ctx, (file1,) + pats, opts)
-    for abs in ctx.walk(m):
+
+    def writedata(abs):
         fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
                                  pathname=abs)
         data = ctx[abs].data()
@@ -1159,7 +1162,23 @@ 
             data = repo.wwritedata(abs, data)
         fp.write(data)
         fp.close()
-        err = 0
+        return 0
+
+    if opts.get('follow'):
+        m = scmutil.match(repo[None], (file1,) + pats, opts)
+        wanted = cmdutil.walkfilerevs(repo, m, True, [0], {}, filename=True)
+        revs = [rev for rev, file in wanted]
+        try:
+            position = revs.index(int(opts.get('rev')))
+            file = list(wanted)[position][1]
+            print ("%s was %s:") % (file1, file)
+            err = writedata(file)
+        except:
+            print ('%s has no ancestor in rev %s') % (file1, ctx)
+    else:
+        m = scmutil.match(ctx, (file1,) + pats, opts)
+        for abs in ctx.walk(m):
+            err = writedata(abs)
     return err
 
 @command('^clone',