--- a/mercurial/extensions.py Tue Apr 14 13:17:33 2015 -0700
+++ b/mercurial/extensions.py Thu May 07 13:47:45 2015 -0500
@@ -134,6 +134,10 @@
for fn in _aftercallbacks[shortname]:
fn(loaded=False)
+ # loadall() is called multiple times and lingering _aftercallbacks
+ # entries could result in double execution. See issue4646.
+ _aftercallbacks.clear()
+
def afterloaded(extension, callback):
'''Run the specified function after a named extension is loaded.
--- a/mercurial/templater.py Tue Apr 14 13:17:33 2015 -0700
+++ b/mercurial/templater.py Thu May 07 13:47:45 2015 -0500
@@ -87,8 +87,9 @@
if n < 0:
parsed.append((strtoken, tmpl[pos:]))
break
- if n > 0 and tmpl[n - 1] == '\\':
- # escaped
+ bs = (n - pos) - len(tmpl[pos:n].rstrip('\\'))
+ if strtoken == 'string' and bs % 2 == 1:
+ # escaped (e.g. '\{', '\\\{', but not '\\{' nor r'\{')
parsed.append((strtoken, (tmpl[pos:n - 1] + "{")))
pos = n + 1
continue
@@ -618,14 +619,13 @@
yield j
def parsestring(s, quoted=True):
- '''parse a string using simple c-like syntax.
- string must be in quotes if quoted is True.'''
+ '''unwrap quotes if quoted is True'''
if quoted:
if len(s) < 2 or s[0] != s[-1]:
raise SyntaxError(_('unmatched quotes'))
- return s[1:-1].decode('string_escape')
+ return s[1:-1]
- return s.decode('string_escape')
+ return s
class engine(object):
'''template expansion engine.
--- a/tests/test-command-template.t Tue Apr 14 13:17:33 2015 -0700
+++ b/tests/test-command-template.t Thu May 07 13:47:45 2015 -0500
@@ -2290,6 +2290,40 @@
<>\n<]>
<>\n<
+ $ hg log -R latesttag -r 0 \
+ > --config ui.logtemplate='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
+ >
+ <>\n<[>
+ <>\n<]>
+ <>\n<
+
+ $ hg log -R latesttag -r 0 -T esc \
+ > --config templates.esc='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
+ >
+ <>\n<[>
+ <>\n<]>
+ <>\n<
+
+ $ cat <<'EOF' > esctmpl
+ > changeset = '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
+ > EOF
+ $ hg log -R latesttag -r 0 --style ./esctmpl
+ >
+ <>\n<[>
+ <>\n<]>
+ <>\n<
+
+Test leading backslashes:
+
+ $ cd latesttag
+ $ hg log -r 2 -T '\{rev} {files % "\{file}"} {files % r"\{file}"}\n'
+ {rev} {file} \head1
+ $ hg log -r 2 -T '\\{rev} {files % "\\{file}"} {files % r"\\{file}"}\n'
+ \2 \head1 \\head1
+ $ hg log -r 2 -T '\\\{rev} {files % "\\\{file}"} {files % r"\\\{file}"}\n'
+ \{rev} \{file} \\\head1
+ $ cd ..
+
"string-escape"-ed "\x5c\x786e" becomes r"\x6e" (once) or r"n" (twice)
$ hg log -R a -r 0 --template '{if("1", "\x5c\x786e", "NG")}\n'