revset: introduce a `nodefromfile` revset
authorPierre-Yves David <pierre-yves.david@octobus.net>
Wed, 17 Mar 2021 20:06:35 +0100
changeset 46809 56d441256e82
parent 46808 b26f9560f40d
child 46811 5a0b930cfb3e
revset: introduce a `nodefromfile` revset I though we had one, but actually we don't seem to. So here is a revset to reuse a list of node previously stored. Differential Revision: https://phab.mercurial-scm.org/D10230
mercurial/revset.py
tests/test-default-push.t
tests/test-revset.t
--- a/mercurial/revset.py	Fri Mar 19 00:28:30 2021 -0400
+++ b/mercurial/revset.py	Wed Mar 17 20:06:35 2021 +0100
@@ -1335,6 +1335,29 @@
     return subset & rs
 
 
+@predicate(b'nodefromfile(path)')
+def nodefromfile(repo, subset, x):
+    """
+    An alias for ``::.`` (ancestors of the working directory's first parent).
+    If file pattern is specified, the histories of files matching given
+    pattern in the revision given by startrev are followed, including copies.
+    """
+    path = getstring(x, _(b"nodefromfile require a file path"))
+    listed_rev = set()
+    try:
+        with pycompat.open(path, 'rb') as f:
+            for line in f:
+                n = line.strip()
+                rn = _node(repo, n)
+                if rn is not None:
+                    listed_rev.add(rn)
+    except IOError as exc:
+        m = _(b'cannot open nodes file "%s": %s')
+        m %= (path, encoding.strtolocal(exc.strerror))
+        raise error.Abort(m)
+    return subset & baseset(listed_rev)
+
+
 @predicate(b'all()', safe=True)
 def getall(repo, subset, x):
     """All changesets, the same as ``0:tip``."""
@@ -1697,13 +1720,9 @@
     return subset & names
 
 
-@predicate(b'id(string)', safe=True)
-def node_(repo, subset, x):
-    """Revision non-ambiguously specified by the given hex string prefix."""
-    # i18n: "id" is a keyword
-    l = getargs(x, 1, 1, _(b"id requires one argument"))
-    # i18n: "id" is a keyword
-    n = getstring(l[0], _(b"id requires a string"))
+def _node(repo, n):
+    """process a node input"""
+    rn = None
     if len(n) == 40:
         try:
             rn = repo.changelog.rev(bin(n))
@@ -1712,7 +1731,6 @@
         except (LookupError, TypeError):
             rn = None
     else:
-        rn = None
         try:
             pm = scmutil.resolvehexnodeidprefix(repo, n)
             if pm is not None:
@@ -1721,6 +1739,17 @@
             pass
         except error.WdirUnsupported:
             rn = wdirrev
+    return rn
+
+
+@predicate(b'id(string)', safe=True)
+def node_(repo, subset, x):
+    """Revision non-ambiguously specified by the given hex string prefix."""
+    # i18n: "id" is a keyword
+    l = getargs(x, 1, 1, _(b"id requires one argument"))
+    # i18n: "id" is a keyword
+    n = getstring(l[0], _(b"id requires a string"))
+    rn = _node(repo, n)
 
     if rn is None:
         return baseset()
--- a/tests/test-default-push.t	Fri Mar 19 00:28:30 2021 -0400
+++ b/tests/test-default-push.t	Wed Mar 17 20:06:35 2021 +0100
@@ -137,6 +137,7 @@
   $ hg --config 'paths.default:pushrev=notdefined()' push
   pushing to file:/*/$TESTTMP/pushurlsource/../pushurldest (glob)
   hg: parse error: unknown identifier: notdefined
+  (did you mean nodefromfile?)
   [10]
 
   $ hg --config 'paths.default:pushrev=(' push
--- a/tests/test-revset.t	Fri Mar 19 00:28:30 2021 -0400
+++ b/tests/test-revset.t	Wed Mar 17 20:06:35 2021 +0100
@@ -3108,3 +3108,18 @@
   $ log 'expectsize(0:2, :2)'
   abort: revset size mismatch. expected between 0 and 2, got 3
   [255]
+
+Test getting list of node from file
+
+  $ hg log -r '0:2' -T '{node}\n' > some.nodes
+  $ hg log -r 'nodefromfile("some.nodes")' -T '{rev}\n'
+  0
+  1
+  2
+  $ hg log -r 'nodefromfile("missing-file")' -T '{rev}\n'
+  abort: cannot open nodes file "missing-file": $ENOENT$
+  [255]
+  $ echo bad-node > bad.nodes
+  $ hg log -r 'nodefromfile("bad.nodes")' -T '{rev}\n'
+  $ echo abcdefabcdefabcdeabcdeabcdeabcdeabcdeabc > missing.nodes
+