changeset 35687:67893a516272

log: follow file history across copies even with -rREV (BC) (issue4959) Still it falls back to changelog path if glob patterns or missing paths are specified. This will be changed later. .. bc:: ``log --follow -rREV FILE..`` now follows file history across copies and renames.
author Yuya Nishihara <yuya@tcha.org>
date Wed, 03 Jan 2018 15:58:59 +0900
parents b25fa5da4ca2
children 84d0e99c063a
files mercurial/cmdutil.py tests/test-glog.t tests/test-log.t
diffstat 3 files changed, 114 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/cmdutil.py	Wed Jan 03 15:46:15 2018 +0900
+++ b/mercurial/cmdutil.py	Wed Jan 03 15:58:59 2018 +0900
@@ -2322,9 +2322,11 @@
 
     return iterate()
 
-def _makelogmatcher(repo, pats, opts):
+def _makelogmatcher(repo, revs, pats, opts):
     """Build matcher and expanded patterns from log options
 
+    If --follow, revs are the revisions to follow from.
+
     Returns (match, pats, slowpath) where
     - match: a matcher built from the given pats and -I/-X opts
     - pats: patterns used (globs are expanded on Windows)
@@ -2339,8 +2341,17 @@
     slowpath = match.anypats() or (not match.always() and opts.get('removed'))
     if not slowpath:
         follow = opts.get('follow') or opts.get('follow_first')
+        startctxs = []
+        if follow and opts.get('rev'):
+            startctxs = [repo[r] for r in revs]
         for f in match.files():
-            if follow and f not in wctx:
+            if follow and startctxs:
+                # No idea if the path was a directory at that revision, so
+                # take the slow path.
+                if any(f not in c for c in startctxs):
+                    slowpath = True
+                    continue
+            elif follow and f not in wctx:
                 # If the file exists, it may be a directory, so let it
                 # take the slow path.
                 if os.path.exists(repo.wjoin(f)):
@@ -2518,17 +2529,13 @@
     """
     follow = opts.get('follow') or opts.get('follow_first')
     followfirst = opts.get('follow_first')
-    if opts.get('rev'):
-        # TODO: do not mutate opts here
-        opts.pop('follow', None)
-        opts.pop('follow_first', None)
     limit = loglimit(opts)
     revs = _logrevs(repo, opts)
     if not revs:
         return smartset.baseset(), None
-    match, pats, slowpath = _makelogmatcher(repo, pats, opts)
+    match, pats, slowpath = _makelogmatcher(repo, revs, pats, opts)
     if follow:
-        if opts.get('rev') or slowpath or not pats:
+        if slowpath or not pats:
             revs = dagop.revancestors(repo, revs, followfirst=followfirst)
         else:
             revs = _fileancestors(repo, revs, match, followfirst)
--- a/tests/test-glog.t	Wed Jan 03 15:46:15 2018 +0900
+++ b/tests/test-glog.t	Wed Jan 03 15:58:59 2018 +0900
@@ -95,7 +95,7 @@
   >     revs = cmdutil._logrevs(repo, opts)
   >     if not revs:
   >         return None
-  >     match, pats, slowpath = cmdutil._makelogmatcher(repo, pats, opts)
+  >     match, pats, slowpath = cmdutil._makelogmatcher(repo, revs, pats, opts)
   >     return cmdutil._makelogrevset(repo, match, pats, slowpath, opts)[0]
   > 
   > def uisetup(ui):
--- a/tests/test-log.t	Wed Jan 03 15:46:15 2018 +0900
+++ b/tests/test-log.t	Wed Jan 03 15:58:59 2018 +0900
@@ -465,6 +465,104 @@
   2
   0
 
+follow files from the specified revisions (issue4959)
+
+  $ hg log -G -T '{rev} {files},{file_copies % " {source}->{name}"}\n'
+  @  4 dir/b e, dir/b->e
+  |
+  o  3 a b d g, a->b f->g
+  |
+  o  2 b dir/b f g, b->dir/b
+  |
+  o  1 b g, a->b f->g
+  |
+  o  0 a f,
+  
+
+  $ hg log -T '{rev}\n' -fr 4 e
+  4
+  2
+  1
+  0
+  $ hg log -T '{rev}\n' -fr 2 g
+  2
+  1
+  0
+  $ hg log -T '{rev}\n' -fr '2+3' g
+  3
+  2
+  1
+  0
+
+follow files from the specified revisions with glob patterns (issue5053)
+(BROKEN: should follow copies from e@4)
+
+  $ hg log -T '{rev}\n' -fr4 e -X '[abcdfg]'
+  4
+  2 (false !)
+  1 (false !)
+  0 (false !)
+
+follow files from the specified revisions with missing patterns
+(BROKEN: should follow copies from e@4)
+
+  $ hg log -T '{rev}\n' -fr4 e x
+  4
+  2 (false !)
+  1 (false !)
+  0 (false !)
+
+follow files from the specified revisions across copies with -p/--patch
+
+  $ hg log -T '== rev: {rev},{file_copies % " {source}->{name}"} ==\n' -fpr 4 e g
+  == rev: 4, dir/b->e ==
+  diff -r 2ca5ba701980 -r 7e4639b4691b e
+  --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/e	Thu Jan 01 00:00:05 1970 +0000
+  @@ -0,0 +1,1 @@
+  +a
+  
+  == rev: 3, a->b f->g ==
+  diff -r f8954cd4dc1f -r 2ca5ba701980 g
+  --- a/g	Thu Jan 01 00:00:03 1970 +0000
+  +++ b/g	Thu Jan 01 00:00:04 1970 +0000
+  @@ -1,2 +1,2 @@
+   f
+  -g
+  +f
+  
+  == rev: 2, b->dir/b ==
+  diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
+  --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/dir/b	Thu Jan 01 00:00:03 1970 +0000
+  @@ -0,0 +1,1 @@
+  +a
+  diff -r d89b0a12d229 -r f8954cd4dc1f f
+  --- a/f	Thu Jan 01 00:00:02 1970 +0000
+  +++ b/f	Thu Jan 01 00:00:03 1970 +0000
+  @@ -1,1 +1,2 @@
+   f
+  +f
+  
+  == rev: 1, a->b f->g ==
+  diff -r 9161b9aeaf16 -r d89b0a12d229 b
+  --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/b	Thu Jan 01 00:00:02 1970 +0000
+  @@ -0,0 +1,1 @@
+  +a
+  
+  == rev: 0, ==
+  diff -r 000000000000 -r 9161b9aeaf16 a
+  --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/a	Thu Jan 01 00:00:01 1970 +0000
+  @@ -0,0 +1,1 @@
+  +a
+  diff -r 000000000000 -r 9161b9aeaf16 f
+  --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/f	Thu Jan 01 00:00:01 1970 +0000
+  @@ -0,0 +1,1 @@
+  +f
+  
 
 log copies with --copies
 
@@ -1725,11 +1823,6 @@
   date:        Thu Jan 01 00:00:00 1970 +0000
   summary:     add foo, related
   
-  changeset:   2:c4c64aedf0f7
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     add unrelated old foo
-  
   $ cd ..
 
 Issue2383: hg log showing _less_ differences than hg diff