mercurial/cmdutil.py
changeset 35686 b25fa5da4ca2
parent 35685 659dfbd852e2
child 35687 67893a516272
--- a/mercurial/cmdutil.py	Wed Jan 03 15:13:22 2018 +0900
+++ b/mercurial/cmdutil.py	Wed Jan 03 15:46:15 2018 +0900
@@ -2371,6 +2371,13 @@
 
     return match, pats, slowpath
 
+def _fileancestors(repo, revs, match, followfirst):
+    fctxs = []
+    for r in revs:
+        ctx = repo[r]
+        fctxs.extend(ctx[f].introfilectx() for f in ctx.walk(match))
+    return dagop.filerevancestors(fctxs, followfirst=followfirst)
+
 def _makefollowlogfilematcher(repo, files, followfirst):
     # When displaying a revision with --patch --follow FILE, we have
     # to know which file of the revision must be diffed. With
@@ -2406,14 +2413,10 @@
 _opt2logrevset = {
     'no_merges':        ('not merge()', None),
     'only_merges':      ('merge()', None),
-    '_ancestors':       ('ancestors(%r)', None),
-    '_fancestors':      ('_firstancestors(%r)', None),
     '_matchfiles':      (None, '_matchfiles(%ps)'),
     'date':             ('date(%s)', None),
     'branch':           ('branch(%s)', '%lr'),
     '_patslog':         ('filelog(%s)', '%lr'),
-    '_patsfollow':      ('follow(%s)', '%lr'),
-    '_patsfollowfirst': ('_followfirst(%s)', '%lr'),
     'keyword':          ('keyword(%s)', '%lr'),
     'prune':            ('ancestors(%s)', 'not %lr'),
     'user':             ('user(%s)', '%lr'),
@@ -2429,19 +2432,12 @@
     opts = dict(opts)
     # follow or not follow?
     follow = opts.get('follow') or opts.get('follow_first')
-    if opts.get('follow_first'):
-        followfirst = 1
-    else:
-        followfirst = 0
 
     # branch and only_branch are really aliases and must be handled at
     # the same time
     opts['branch'] = opts.get('branch', []) + opts.get('only_branch', [])
     opts['branch'] = [repo.lookupbranch(b) for b in opts['branch']]
 
-    fpats = ('_patsfollow', '_patsfollowfirst')
-    fnopats = ('_ancestors', '_fancestors')
-
     if slowpath:
         # See walkchangerevs() slow path.
         #
@@ -2459,19 +2455,8 @@
         for p in opts.get('exclude', []):
             matchargs.append('x:' + p)
         opts['_matchfiles'] = matchargs
-        if follow:
-            opts[fnopats[followfirst]] = '.'
-    else:
-        if follow:
-            if pats:
-                # follow() revset interprets its file argument as a
-                # manifest entry, so use match.files(), not pats.
-                opts[fpats[followfirst]] = list(match.files())
-            else:
-                op = fnopats[followfirst]
-                opts[op] = '.'
-        else:
-            opts['_patslog'] = list(pats)
+    elif not follow:
+        opts['_patslog'] = list(pats)
 
     filematcher = None
     if opts.get('patch') or opts.get('stat'):
@@ -2482,7 +2467,7 @@
             # _makefollowlogfilematcher expects its files argument to be
             # relative to the repo root, so use match.files(), not pats.
             filematcher = _makefollowlogfilematcher(repo, match.files(),
-                                                    followfirst)
+                                                    opts.get('follow_first'))
         else:
             filematcher = _makenofollowlogfilematcher(repo, pats, opts)
             if filematcher is None:
@@ -2511,13 +2496,14 @@
     return expr, filematcher
 
 def _logrevs(repo, opts):
+    """Return the initial set of revisions to be filtered or followed"""
     follow = opts.get('follow') or opts.get('follow_first')
     if opts.get('rev'):
         revs = scmutil.revrange(repo, opts['rev'])
     elif follow and repo.dirstate.p1() == nullid:
         revs = smartset.baseset()
     elif follow:
-        revs = repo.revs('reverse(:.)')
+        revs = repo.revs('.')
     else:
         revs = smartset.spanset(repo)
         revs.reverse()
@@ -2541,8 +2527,11 @@
     if not revs:
         return smartset.baseset(), None
     match, pats, slowpath = _makelogmatcher(repo, pats, opts)
-    if opts.get('rev') and follow:
-        revs = dagop.revancestors(repo, revs, followfirst=followfirst)
+    if follow:
+        if opts.get('rev') or slowpath or not pats:
+            revs = dagop.revancestors(repo, revs, followfirst=followfirst)
+        else:
+            revs = _fileancestors(repo, revs, match, followfirst)
         revs.reverse()
     expr, filematcher = _makelogrevset(repo, match, pats, slowpath, opts)
     if opts.get('graph') and opts.get('rev'):