templater: avoid recursive evaluation of string literals completely
Changeset
3d8bfe2ecf6d (released with 2.8.1) fixed "recursively
evaluate string literals as templates" problem (
issue4103) by
introducing "_evalifliteral()".
But some parts in template expressions below are still processed by
the combination of "compiletemplate()" and "runtemplate()", and may
cause same problem unexpectedly.
- 'init' and 'hang' of 'fill(text, width, init, hang)'
- 'expr' of 'sub(pat, repl, expr)'
- 'label' of 'label(label, expr)'
This patch processes them by "_evalifliteral()" instead of the
combination of "compiletemplate()" and "runtemplate()" to avoid
recursive evaluation of string literals completely.
--- a/hgext/color.py Mon Mar 03 15:50:45 2014 +0900
+++ b/hgext/color.py Mon Mar 10 01:01:42 2014 +0900
@@ -393,9 +393,7 @@
if isinstance(repo, str):
return thing
- label = templater.stringify(args[0][0](context, mapping, args[0][1]))
- label = templater.runtemplate(context, mapping,
- templater.compiletemplate(label, context))
+ label = templater._evalifliteral(args[0], context, mapping)
thing = templater.stringify(thing)
label = templater.stringify(label)
--- a/mercurial/templater.py Mon Mar 03 15:50:45 2014 +0900
+++ b/mercurial/templater.py Mon Mar 10 01:01:42 2014 +0900
@@ -234,12 +234,8 @@
except ValueError:
raise error.ParseError(_("fill expects an integer width"))
try:
- initindent = stringify(args[2][0](context, mapping, args[2][1]))
- initindent = stringify(runtemplate(context, mapping,
- compiletemplate(initindent, context)))
- hangindent = stringify(args[3][0](context, mapping, args[3][1]))
- hangindent = stringify(runtemplate(context, mapping,
- compiletemplate(hangindent, context)))
+ initindent = stringify(_evalifliteral(args[2], context, mapping))
+ hangindent = stringify(_evalifliteral(args[3], context, mapping))
except IndexError:
pass
@@ -345,9 +341,7 @@
pat = stringify(args[0][0](context, mapping, args[0][1]))
rpl = stringify(args[1][0](context, mapping, args[1][1]))
- src = stringify(args[2][0](context, mapping, args[2][1]))
- src = stringify(runtemplate(context, mapping,
- compiletemplate(src, context)))
+ src = stringify(_evalifliteral(args[2], context, mapping))
yield re.sub(pat, rpl, src)
methods = {
--- a/tests/test-command-template.t Mon Mar 03 15:50:45 2014 +0900
+++ b/tests/test-command-template.t Mon Mar 10 01:01:42 2014 +0900
@@ -1622,6 +1622,39 @@
$ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n'
test 0
+ $ hg branch -q 'text.{rev}'
+ $ echo aa >> aa
+ $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
+
+ $ hg log -r 1 --template '{fill(desc, "20", author, branch)}'
+ {node|short}desc to
+ text.{rev}be wrapped
+ text.{rev}desc to be
+ text.{rev}wrapped (no-eol)
+ $ hg log -r 1 --template '{fill(desc, "20", "{node|short}:", "text.{rev}:")}'
+ bcc7ff960b8e:desc to
+ text.1:be wrapped
+ text.1:desc to be
+ text.1:wrapped (no-eol)
+
+ $ hg log -r 1 --template '{sub(r"[0-9]", "-", author)}'
+ {node|short} (no-eol)
+ $ hg log -r 1 --template '{sub(r"[0-9]", "-", "{node|short}")}'
+ bcc-ff---b-e (no-eol)
+
+ $ cat >> .hg/hgrc <<EOF
+ > [extensions]
+ > color=
+ > [color]
+ > mode=ansi
+ > text.{rev} = red
+ > text.1 = green
+ > EOF
+ $ hg log --color=always -r 1 --template '{label(branch, "text\n")}'
+ \x1b[0;31mtext\x1b[0m (esc)
+ $ hg log --color=always -r 1 --template '{label("text.{rev}", "text\n")}'
+ \x1b[0;32mtext\x1b[0m (esc)
+
Test branches inside if statement:
$ hg log -r 0 --template '{if(branches, "yes", "no")}\n'