mercurial/revset.py
changeset 16185 352053e6cd8e
parent 16181 1fd352aa08fc
child 16218 81a1a00f5738
--- a/mercurial/revset.py	Sun Feb 26 17:10:57 2012 +0100
+++ b/mercurial/revset.py	Sun Feb 26 17:10:57 2012 +0100
@@ -441,63 +441,45 @@
     """
     return limit(repo, subset, x)
 
+def _follow(repo, subset, x, name, followfirst=False):
+    l = getargs(x, 0, 1, _("%s takes no arguments or a filename") % name)
+    c = repo['.']
+    if l:
+        x = getstring(l[0], _("%s expected a filename") % name)
+        if x in c:
+            cx = c[x]
+            s = set(ctx.rev() for ctx in cx.ancestors(followfirst=followfirst))
+            # include the revision responsible for the most recent version
+            s.add(cx.linkrev())
+        else:
+            return []
+    else:
+        cut = followfirst and 1 or None
+        cl = repo.changelog
+        s = set()
+        visit = [c.rev()]
+        while visit:
+            for prev in cl.parentrevs(visit.pop(0))[:cut]:
+                if prev not in s and prev != nodemod.nullrev:
+                    visit.append(prev)
+                    s.add(prev)
+        s.add(c.rev())
+
+    return [r for r in subset if r in s]
+
 def follow(repo, subset, x):
     """``follow([file])``
     An alias for ``::.`` (ancestors of the working copy's first parent).
     If a filename is specified, the history of the given file is followed,
     including copies.
     """
-    # i18n: "follow" is a keyword
-    l = getargs(x, 0, 1, _("follow takes no arguments or a filename"))
-    c = repo['.']
-    if l:
-        x = getstring(l[0], _("follow expected a filename"))
-        if x in c:
-            cx = c[x]
-            s = set(ctx.rev() for ctx in cx.ancestors())
-            # include the revision responsible for the most recent version
-            s.add(cx.linkrev())
-        else:
-            return []
-    else:
-        s = set(repo.changelog.ancestors(c.rev()))
-        s.add(c.rev())
-
-    return [r for r in subset if r in s]
+    return _follow(repo, subset, x, 'follow')
 
 def _followfirst(repo, subset, x):
     # ``followfirst([file])``
     # Like ``follow([file])`` but follows only the first parent of
     # every revision or file revision.
-    # i18n: "_followfirst" is a keyword
-    l = getargs(x, 0, 1, _("_followfirst takes no arguments or a filename"))
-    c = repo['.']
-    if l:
-        x = getstring(l[0], _("_followfirst expected a filename"))
-        if x not in c:
-            return []
-        cx = c[x]
-        visit = {}
-        s = set([cx.linkrev()])
-        while True:
-            for p in cx.parents()[:1]:
-                visit[(p.rev(), p.node())] = p
-            if not visit:
-                break
-            cx = visit.pop(max(visit))
-            s.add(cx.rev())
-    else:
-        cl = repo.changelog
-        s = set()
-        visit = [c.rev()]
-        while visit:
-            for prev in cl.parentrevs(visit.pop(0))[:1]:
-                if prev not in s and prev != nodemod.nullrev:
-                    visit.append(prev)
-                    s.add(prev)
-        s.add(c.rev())
-
-    return [r for r in subset if r in s]
+    return _follow(repo, subset, x, '_followfirst', followfirst=True)
 
 def getall(repo, subset, x):
     """``all()``