# HG changeset patch # User Matt Mackall # Date 2013-11-18 20:37:09 # Node ID 3d8bfe2ecf6d33e06996ca5fb7c3622b9b150589 # Parent 64b4f0cd73369185656a36ab8823f1ac082d1d23 templater: only recursively evaluate string literals as templates (issue4103) diff --git a/hgext/color.py b/hgext/color.py --- a/hgext/color.py +++ b/hgext/color.py @@ -386,9 +386,7 @@ def templatelabel(context, mapping, args # i18n: "label" is a keyword raise error.ParseError(_("label expects two arguments")) - thing = templater.stringify(args[1][0](context, mapping, args[1][1])) - thing = templater.runtemplate(context, mapping, - templater.compiletemplate(thing, context)) + thing = templater._evalifliteral(args[1], context, mapping) # apparently, repo could be a string that is the favicon? repo = mapping.get('repo', '') diff --git a/mercurial/templater.py b/mercurial/templater.py --- a/mercurial/templater.py +++ b/mercurial/templater.py @@ -258,6 +258,13 @@ def get(context, mapping, args): key = args[1][0](context, mapping, args[1][1]) yield dictarg.get(key) +def _evalifliteral(arg, context, mapping): + t = stringify(arg[0](context, mapping, arg[1])) + if arg[0] == runstring: + yield runtemplate(context, mapping, compiletemplate(t, context)) + else: + yield t + def if_(context, mapping, args): if not (2 <= len(args) <= 3): # i18n: "if" is a keyword @@ -265,11 +272,9 @@ def if_(context, mapping, args): test = stringify(args[0][0](context, mapping, args[0][1])) if test: - t = stringify(args[1][0](context, mapping, args[1][1])) - yield runtemplate(context, mapping, compiletemplate(t, context)) + yield _evalifliteral(args[1], context, mapping) elif len(args) == 3: - t = stringify(args[2][0](context, mapping, args[2][1])) - yield runtemplate(context, mapping, compiletemplate(t, context)) + yield _evalifliteral(args[2], context, mapping) def ifeq(context, mapping, args): if not (3 <= len(args) <= 4): @@ -279,11 +284,9 @@ def ifeq(context, mapping, args): test = stringify(args[0][0](context, mapping, args[0][1])) match = stringify(args[1][0](context, mapping, args[1][1])) if test == match: - t = stringify(args[2][0](context, mapping, args[2][1])) - yield runtemplate(context, mapping, compiletemplate(t, context)) + yield _evalifliteral(args[2], context, mapping) elif len(args) == 4: - t = stringify(args[3][0](context, mapping, args[3][1])) - yield runtemplate(context, mapping, compiletemplate(t, context)) + yield _evalifliteral(args[3], context, mapping) def join(context, mapping, args): if not (1 <= len(args) <= 2): @@ -313,8 +316,7 @@ def label(context, mapping, args): raise error.ParseError(_("label expects two arguments")) # ignore args[0] (the label string) since this is supposed to be a a no-op - t = stringify(args[1][0](context, mapping, args[1][1])) - yield runtemplate(context, mapping, compiletemplate(t, context)) + yield _evalifliteral(args[1], context, mapping) def rstdoc(context, mapping, args): if len(args) != 2: 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 @@ -1594,3 +1594,15 @@ Test string escaping: <>\n<[> <>\n<]> <>\n< + +Test recursive evaluation: + + $ hg init r + $ cd r + $ echo a > a + $ hg ci -Am '{rev}' + adding a + $ hg log -r 0 --template '{if(rev, desc)}\n' + {rev} + $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n' + test 0