# HG changeset patch # User Durham Goode # Date 2014-02-12 05:04:12 # Node ID cda9d2b6beabffca30efb9c70dad418239da9c52 # Parent 1e43f15a647f6acda968fcfe0dad6cca46580f41 template: add revset() template function Adds a template function that executes a revset and returns the list of revisions as the result. It has the signature 'revset(query [, args...])'. The args are optional and are applied to the query string using the standard python string.format(args) pattern. This allows things like: '{revset("parents({0})", rev)}' to produce the parents of each individual commit in the log output. If no args are specified, the revset result is cached for the duration of the templater; so it's better to not use args if performance is a concern. By itself, revset() can be used to print commit parents, print the common ancestor of a commit with the main branch, etc. It can be used with the ifcontains() function to do things like '{ifcontains(rev, revset('.'), label(...), ...)}' to color the working copy parent, to color certain branches, to color draft commits, etc. diff --git a/mercurial/templater.py b/mercurial/templater.py --- a/mercurial/templater.py +++ b/mercurial/templater.py @@ -7,7 +7,7 @@ from i18n import _ import sys, os, re -import util, config, templatefilters, parser, error +import util, config, templatefilters, templatekw, parser, error import types import minirst @@ -356,6 +356,32 @@ def label(context, mapping, args): # ignore args[0] (the label string) since this is supposed to be a a no-op yield _evalifliteral(args[1], context, mapping) +def revset(context, mapping, args): + """usage: revset(query[, formatargs...]) + """ + if not len(args) > 0: + # i18n: "revset" is a keyword + raise error.ParseError(_("revset expects one or more arguments")) + + raw = args[0][1] + ctx = mapping['ctx'] + repo = ctx._repo + + if len(args) > 1: + formatargs = list([a[0](context, mapping, a[1]) for a in args[1:]]) + revs = repo.revs(raw, *formatargs) + revs = list([str(r) for r in revs]) + else: + revsetcache = mapping['cache'].setdefault("revsetcache", {}) + if raw in revsetcache: + revs = revsetcache[raw] + else: + revs = repo.revs(raw) + revs = list([str(r) for r in revs]) + revsetcache[raw] = revs + + return templatekw.showlist("revision", revs, **mapping) + def rstdoc(context, mapping, args): if len(args) != 2: # i18n: "rstdoc" is a keyword @@ -454,6 +480,7 @@ funcs = { "join": join, "label": label, "pad": pad, + "revset": revset, "rstdoc": rstdoc, "shortest": shortest, "strip": strip, diff --git a/tests/test-command-template.t b/tests/test-command-template.t --- a/tests/test-command-template.t +++ b/tests/test-command-template.t @@ -1657,3 +1657,22 @@ Test ifcontains function $ hg log --template '{rev} {ifcontains("a", file_adds, "added a", "did not add a")}\n' 1 did not add a 0 added a + +Test revset function + + $ hg log --template '{rev} {ifcontains(rev, revset("."), "current rev", "not current rev")}\n' + 1 current rev + 0 not current rev + + $ hg log --template '{rev} Parents: {revset("parents(%s)", rev)}\n' + 1 Parents: 0 + 0 Parents: + + $ hg log --template 'Rev: {rev}\n{revset("::%s", rev) % "Ancestor: {revision}\n"}\n' + Rev: 1 + Ancestor: 0 + Ancestor: 1 + + Rev: 0 + Ancestor: 0 + diff --git a/tests/test-module-imports.t b/tests/test-module-imports.t --- a/tests/test-module-imports.t +++ b/tests/test-module-imports.t @@ -34,7 +34,7 @@ these may expose other cycles. relative: discovery, error, hbisect, phases, util mercurial/templater.py mixed imports stdlib: parser - relative: config, error, templatefilters, util + relative: config, error, templatefilters, templatekw, util mercurial/ui.py mixed imports stdlib: formatter relative: config, error, scmutil, util