revset: introduce an internal `_rev` predicate for '%d' usage
In 24a1f67bb75a, we aligned "%d" behavior on "%ld" one, invalid revisions got
silently ignored. However, soon after in 8aca89a694d4 and 26b0a7514f01, a side
effect changed the behavior of "%ld" to no longer silently filter invalid
revisions.
After discussion on the mailing list, it was decided to align on the new %ld
behavior:
https://www.mercurial-scm.org/pipermail/mercurial-devel/2019-January/127291.html
This changeset introduce a '_rev()' predicated that keep the benefit from
24a1f67bb75a while enforcing a more strict checking on the inputs.
--- a/mercurial/revset.py Fri Jan 18 16:03:37 2019 +0100
+++ b/mercurial/revset.py Fri Jan 18 14:21:47 2019 +0100
@@ -1765,6 +1765,20 @@
return baseset()
return subset & baseset([l])
+@predicate('_rev(number)', safe=True)
+def _rev(repo, subset, x):
+ # internal version of "rev(x)" that raise error if "x" is invalid
+ # i18n: "rev" is a keyword
+ l = getargs(x, 1, 1, _("rev requires one argument"))
+ try:
+ # i18n: "rev" is a keyword
+ l = int(getstring(l[0], _("rev requires a number")))
+ except (TypeError, ValueError):
+ # i18n: "rev" is a keyword
+ raise error.ParseError(_("rev expects a number"))
+ repo.changelog.node(l) # check that the rev exists
+ return subset & baseset([l])
+
@predicate('revset(set)', safe=True, takeorder=True)
def revsetpredicate(repo, subset, x, order):
"""Strictly interpret the content as a revset.
--- a/mercurial/revsetlang.py Fri Jan 18 16:03:37 2019 +0100
+++ b/mercurial/revsetlang.py Fri Jan 18 14:21:47 2019 +0100
@@ -585,7 +585,7 @@
def _formatargtype(c, arg):
if c == 'd':
- return 'rev(%d)' % int(arg)
+ return '_rev(%d)' % int(arg)
elif c == 's':
return _quote(arg)
elif c == 'r':
@@ -663,9 +663,9 @@
>>> formatspec(b'%r:: and %lr', b'10 or 11', (b"this()", b"that()"))
'(10 or 11):: and ((this()) or (that()))'
>>> formatspec(b'%d:: and not %d::', 10, 20)
- 'rev(10):: and not rev(20)::'
+ '_rev(10):: and not _rev(20)::'
>>> formatspec(b'%ld or %ld', [], [1])
- "_list('') or rev(1)"
+ "_list('') or _rev(1)"
>>> formatspec(b'keyword(%s)', b'foo\\xe9')
"keyword('foo\\\\xe9')"
>>> b = lambda: b'default'