Mercurial > hg
comparison mercurial/templatefuncs.py @ 44592: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 |
comparison
equal
deleted
inserted
replaced
44591:1f81f680912f | 44592:7cd5c0968139 |
---|---|
14 bin, | 14 bin, |
15 wdirid, | 15 wdirid, |
16 ) | 16 ) |
17 from . import ( | 17 from . import ( |
18 color, | 18 color, |
19 dagop, | |
19 diffutil, | 20 diffutil, |
20 encoding, | 21 encoding, |
21 error, | 22 error, |
22 minirst, | 23 minirst, |
23 obsutil, | 24 obsutil, |
840 if text.startswith(patn): | 841 if text.startswith(patn): |
841 return text | 842 return text |
842 return b'' | 843 return b'' |
843 | 844 |
844 | 845 |
846 @templatefunc( | |
847 b'subsetparents(rev, revset)', | |
848 argspec=b'rev revset', | |
849 requires={b'repo', b'cache'}, | |
850 ) | |
851 def subsetparents(context, mapping, args): | |
852 """Look up parents of the rev in the sub graph given by the revset.""" | |
853 if b'rev' not in args or b'revset' not in args: | |
854 # i18n: "subsetparents" is a keyword | |
855 raise error.ParseError(_(b"subsetparents expects two arguments")) | |
856 | |
857 repo = context.resource(mapping, b'repo') | |
858 | |
859 rev = templateutil.evalinteger(context, mapping, args[b'rev']) | |
860 | |
861 # TODO: maybe subsetparents(rev) should be allowed. the default revset | |
862 # will be the revisions specified by -rREV argument. | |
863 q = templateutil.evalwrapped(context, mapping, args[b'revset']) | |
864 if not isinstance(q, templateutil.revslist): | |
865 # i18n: "subsetparents" is a keyword | |
866 raise error.ParseError(_(b"subsetparents expects a queried revset")) | |
867 subset = q.tovalue(context, mapping) | |
868 key = q.cachekey | |
869 | |
870 if key: | |
871 # cache only if revset query isn't dynamic | |
872 cache = context.resource(mapping, b'cache') | |
873 walkercache = cache.setdefault(b'subsetparentswalker', {}) | |
874 if key in walkercache: | |
875 walker = walkercache[key] | |
876 else: | |
877 walker = dagop.subsetparentswalker(repo, subset) | |
878 walkercache[key] = walker | |
879 else: | |
880 # for one-shot use, specify startrev to limit the search space | |
881 walker = dagop.subsetparentswalker(repo, subset, startrev=rev) | |
882 return templateutil.revslist(repo, walker.parentsset(rev)) | |
883 | |
884 | |
845 @templatefunc(b'word(number, text[, separator])') | 885 @templatefunc(b'word(number, text[, separator])') |
846 def word(context, mapping, args): | 886 def word(context, mapping, args): |
847 """Return the nth word from a string.""" | 887 """Return the nth word from a string.""" |
848 if not (2 <= len(args) <= 3): | 888 if not (2 <= len(args) <= 3): |
849 # i18n: "word" is a keyword | 889 # i18n: "word" is a keyword |