merge with stable
authorMatt Mackall <mpm@selenic.com>
Thu, 07 May 2015 13:47:45 -0500
changeset 24951 eeca859cc045
parent 24947 a02d293a1079 (current diff)
parent 24950 e6e7d1cce04d (diff)
child 24953 5115d03440f4
merge with stable
tests/test-command-template.t
--- 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'