@@ -668,7 +668,7 @@ def revset(context, mapping, args):
else:
revs = query(raw)
revsetcache[raw] = revs
- return templatekw.showrevslist(context, mapping, b"revision", revs)
+ return templateutil.revslist(repo, revs, name=b'revision')
@templatefunc(b'rstdoc(text, style)')
@@ -873,24 +873,6 @@ def showrev(context, mapping):
return scmutil.intrev(ctx)
-def showrevslist(context, mapping, name, revs):
- """helper to generate a list of revisions in which a mapped template will
- be evaluated"""
- repo = context.resource(mapping, b'repo')
- # revs may be a smartset; don't compute it until f() has to be evaluated
- def f():
- srevs = [b'%d' % r for r in revs]
- return _showcompatlist(context, mapping, name, srevs)
-
- return _hybrid(
- f,
- revs,
- lambda x: {name: x, b'ctx': repo[x]},
- pycompat.identity,
- keytype=int,
- )
-
-
@templatekeyword(b'subrepos', requires={b'ctx'})
def showsubrepos(context, mapping):
"""List of strings. Updated subrepositories in the changeset."""
@@ -45,6 +45,9 @@ hybrid
hybriditem
represents a scalar printable value, also supports % operator.
+revslist
+ represents a list of revision numbers.
+
mappinggenerator, mappinglist
represents mappings (i.e. a list of dicts), which may have default
output format.
@@ -15,6 +15,7 @@ from .pycompat import getattr
from . import (
error,
pycompat,
+ smartset,
util,
)
from .utils import (
@@ -408,6 +409,74 @@ class hybriditem(mappable, wrapped):
return _unthunk(context, mapping, self._value)
+class revslist(wrapped):
+ """Wrapper for a smartset (a list/set of revision numbers)
+
+ If name specified, the revs will be rendered with the old-style list
+ template of the given name by default.
+ """
+
+ def __init__(self, repo, revs, name=None):
+ assert isinstance(revs, smartset.abstractsmartset)
+ self._repo = repo
+ self._revs = revs
+ self._name = name
+
+ def contains(self, context, mapping, item):
+ rev = unwrapinteger(context, mapping, item)
+ return rev in self._revs
+
+ def getmember(self, context, mapping, key):
+ raise error.ParseError(_(b'not a dictionary'))
+
+ def getmin(self, context, mapping):
+ makehybriditem = self._makehybriditemfunc()
+ return makehybriditem(self._revs.min())
+
+ def getmax(self, context, mapping):
+ makehybriditem = self._makehybriditemfunc()
+ return makehybriditem(self._revs.max())
+
+ def filter(self, context, mapping, select):
+ makehybriditem = self._makehybriditemfunc()
+ frevs = self._revs.filter(lambda r: select(makehybriditem(r)))
+ # once filtered, no need to support old-style list template
+ return revslist(self._repo, frevs, name=None)
+
+ def itermaps(self, context):
+ makemap = self._makemapfunc()
+ for r in self._revs:
+ yield makemap(r)
+
+ def _makehybriditemfunc(self):
+ makemap = self._makemapfunc()
+ return lambda r: hybriditem(None, r, r, makemap)
+
+ def _makemapfunc(self):
+ repo = self._repo
+ name = self._name
+ if name:
+ return lambda r: {name: r, b'ctx': repo[r]}
+ else:
+ return lambda r: {b'ctx': repo[r]}
+
+ def join(self, context, mapping, sep):
+ return joinitems(self._revs, sep)
+
+ def show(self, context, mapping):
+ if self._name:
+ srevs = [b'%d' % r for r in self._revs]
+ return _showcompatlist(context, mapping, self._name, srevs)
+ else:
+ return self.join(context, mapping, b' ')
+
+ def tobool(self, context, mapping):
+ return bool(self._revs)
+
+ def tovalue(self, context, mapping):
+ return list(self._revs)
+
+
class _mappingsequence(wrapped):
"""Wrapper for sequence of template mappings
@@ -820,6 +820,8 @@ Test json filter applied to wrapped obje
{"branch": "default"}
$ hg log -r0 -T '{date|json}\n'
[0, 0]
+ $ hg log -r0 -T '{revset(":")|json}\n'
+ [0, 1]
Test json filter applied to map result:
@@ -1263,6 +1265,28 @@ default. join() should agree with the de
5:13207e5a10d9fd28ec424934298e176197f2c67f,
4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
+for historical reasons, revset() supports old-style list template
+
+ $ hg log -T '{revset(":")}\n' -l1 \
+ > --config templates.start_revisions='"["' \
+ > --config templates.end_revisions='"]"' \
+ > --config templates.revision='"{revision}, "' \
+ > --config templates.last_revision='"{revision}"'
+ [0, 1, 2]
+ $ hg log -T '{revset(":") % " {revision}"}\n' -l1
+ 0 1 2
+
+but a filtered one doesn't
+
+ $ hg log -T '{filter(revset(":"), ifeq(rev, 1, "", "y"))}\n' -l1 \
+ > --config templates.start_revisions='"["' \
+ > --config templates.end_revisions='"]"' \
+ > --config templates.revision='"{revision}, "' \
+ > --config templates.last_revision='"{revision}"'
+ 0 2
+ $ hg log -T '{filter(revset(":"), ifeq(rev, 1, "", "y")) % "x{revision}"}\n' -l1
+ xx
+
%d parameter handling:
$ hg log -T '{revset("%d", rev)}\n' -r'wdir()'
@@ -1318,6 +1342,13 @@ Invalid arguments passed to revset()
hg: parse error: invalid argument for revspec
[255]
+Invalid operation on revset()
+
+ $ hg log -T '{get(revset(":"), "foo")}\n'
+ hg: parse error: not a dictionary
+ (get() expects a dict as first argument)
+ [255]
+
Test files function
$ hg log -T "{rev}\n{join(files('*'), '\n')}\n"
@@ -1568,6 +1599,23 @@ Test cbor filter:
}
]
+ $ hg log -T "{revset(':')|cbor}" -R a -l1 | "$PYTHON" "$TESTTMP/decodecbor.py"
+ [
+ [
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10
+ ]
+ ]
+
json filter should escape HTML tags so that the output can be embedded in hgweb:
$ hg log -T "{'<foo@example.org>'|json}\n" -R a -l1