templater: only recursively evaluate string literals as templates (issue4103) stable
authorMatt Mackall <mpm@selenic.com>
Mon, 18 Nov 2013 15:37:09 -0500
branchstable
changeset 20067 3d8bfe2ecf6d
parent 20066 64b4f0cd7336
child 20070 509717d0d517
templater: only recursively evaluate string literals as templates (issue4103)
hgext/color.py
mercurial/templater.py
tests/test-command-template.t
--- a/hgext/color.py	Mon Nov 18 14:02:26 2013 -0500
+++ b/hgext/color.py	Mon Nov 18 15:37:09 2013 -0500
@@ -386,9 +386,7 @@
         # 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', '')
--- a/mercurial/templater.py	Mon Nov 18 14:02:26 2013 -0500
+++ b/mercurial/templater.py	Mon Nov 18 15:37:09 2013 -0500
@@ -258,6 +258,13 @@
     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 @@
 
     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 @@
     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 @@
         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:
--- a/tests/test-command-template.t	Mon Nov 18 14:02:26 2013 -0500
+++ b/tests/test-command-template.t	Mon Nov 18 15:37:09 2013 -0500
@@ -1594,3 +1594,15 @@
   <>\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