Mercurial > public > mercurial-scm > hg-stable
diff mercurial/templatefuncs.py @ 44600:7cd5c0968139
templater: add subsetparents(rev, revset) function
Naming suggestions are welcome. And this could be flagged as an (ADVANCED)
function since the primary use case is to draw a graph.
This provides all data needed for drawing revisions graph filtered by revset,
and allows us to implement a GUI graph viewer in some languages better than
Python. A frontend grapher will be quite similar to our graphmod since
subsetparents() just returns parent-child relations in the filtered sub graph.
Frontend example:
https://hg.sr.ht/~yuja/hgv/browse/default/core/hgchangesetgrapher.cpp
However, the resulting graph will be simpler than the one "hg log -G" would
generate because redundant edges are eliminated. This should be the same graph
rendering strategy as TortoiseHg.
This function could be implemented as a revset predicate, but that would mean
the scanning state couldn't be cached and thus slow.
Test cases are split to new file since test-template-functions.t is quite
big and we'll need a new branchy repository anyway.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sun, 15 Mar 2020 16:11:58 +0900 |
parents | 1f81f680912f |
children | 89a2afe31e82 |
line wrap: on
line diff
--- a/mercurial/templatefuncs.py Sun Mar 15 16:00:45 2020 +0900 +++ b/mercurial/templatefuncs.py Sun Mar 15 16:11:58 2020 +0900 @@ -16,6 +16,7 @@ ) from . import ( color, + dagop, diffutil, encoding, error, @@ -842,6 +843,45 @@ return b'' +@templatefunc( + b'subsetparents(rev, revset)', + argspec=b'rev revset', + requires={b'repo', b'cache'}, +) +def subsetparents(context, mapping, args): + """Look up parents of the rev in the sub graph given by the revset.""" + if b'rev' not in args or b'revset' not in args: + # i18n: "subsetparents" is a keyword + raise error.ParseError(_(b"subsetparents expects two arguments")) + + repo = context.resource(mapping, b'repo') + + rev = templateutil.evalinteger(context, mapping, args[b'rev']) + + # TODO: maybe subsetparents(rev) should be allowed. the default revset + # will be the revisions specified by -rREV argument. + q = templateutil.evalwrapped(context, mapping, args[b'revset']) + if not isinstance(q, templateutil.revslist): + # i18n: "subsetparents" is a keyword + raise error.ParseError(_(b"subsetparents expects a queried revset")) + subset = q.tovalue(context, mapping) + key = q.cachekey + + if key: + # cache only if revset query isn't dynamic + cache = context.resource(mapping, b'cache') + walkercache = cache.setdefault(b'subsetparentswalker', {}) + if key in walkercache: + walker = walkercache[key] + else: + walker = dagop.subsetparentswalker(repo, subset) + walkercache[key] = walker + else: + # for one-shot use, specify startrev to limit the search space + walker = dagop.subsetparentswalker(repo, subset, startrev=rev) + return templateutil.revslist(repo, walker.parentsset(rev)) + + @templatefunc(b'word(number, text[, separator])') def word(context, mapping, args): """Return the nth word from a string."""