templater: create string unescape helper (
issue4798)
This gives us a unified place to do error-handling of string-escaping
syntax errors
--- a/mercurial/templater.py Sat Sep 05 16:50:35 2015 +0900
+++ b/mercurial/templater.py Wed Sep 09 14:43:45 2015 -0700
@@ -39,6 +39,13 @@
"end": (0, None, None, None, None),
}
+def _unescape(s):
+ try:
+ return s.decode("string_escape")
+ except ValueError as e:
+ # mangle Python's exception into our format
+ raise error.ParseError(str(e).lower())
+
def tokenize(program, start, end):
pos = start
while pos < end:
@@ -105,11 +112,8 @@
pos += 4 # skip over double escaped characters
continue
if program.startswith(quote, pos, end):
- try:
- # interpret as if it were a part of an outer string
- data = program[s:pos].decode('string-escape')
- except ValueError: # unbalanced escapes
- raise error.ParseError(_("syntax error"), s)
+ # interpret as if it were a part of an outer string
+ data = _unescape(program[s:pos])
if token == 'template':
data = _parsetemplate(data, 0, len(data))[0]
yield (token, data, s)
@@ -158,19 +162,18 @@
n = min((tmpl.find(c, pos, stop) for c in sepchars),
key=lambda n: (n < 0, n))
if n < 0:
- parsed.append(('string', tmpl[pos:stop].decode('string-escape')))
+ parsed.append(('string', _unescape(tmpl[pos:stop])))
pos = stop
break
c = tmpl[n]
bs = (n - pos) - len(tmpl[pos:n].rstrip('\\'))
if bs % 2 == 1:
# escaped (e.g. '\{', '\\\{', but not '\\{')
- parsed.append(('string',
- tmpl[pos:n - 1].decode('string-escape') + c))
+ parsed.append(('string', _unescape(tmpl[pos:n - 1]) + c))
pos = n + 1
continue
if n > pos:
- parsed.append(('string', tmpl[pos:n].decode('string-escape')))
+ parsed.append(('string', _unescape(tmpl[pos:n])))
if c == quote:
return parsed, n + 1
--- a/tests/test-command-template.t Sat Sep 05 16:50:35 2015 +0900
+++ b/tests/test-command-template.t Wed Sep 09 14:43:45 2015 -0700
@@ -2936,10 +2936,10 @@
hg: parse error at 21: unterminated string
[255]
$ hg log -r 2 -T '{if(rev, \"\\"")}\n'
- hg: parse error at 11: syntax error
+ hg: parse error: trailing \ in string
[255]
$ hg log -r 2 -T '{if(rev, r\"\\"")}\n'
- hg: parse error at 12: syntax error
+ hg: parse error: trailing \ in string
[255]
$ cd ..
@@ -3417,3 +3417,12 @@
$ hg log -T "{indent(date, ' ')}\n" -r 2:3 -R a
1200000.00
1300000.00
+
+Test broken string escapes:
+
+ $ hg log -T "bogus\\" -R a
+ hg: parse error: trailing \ in string
+ [255]
+ $ hg log -T "\\xy" -R a
+ hg: parse error: invalid \x escape
+ [255]