##// END OF EJS Templates
templater: add parsing rule for key-value pair...
Yuya Nishihara -
r31885:d18b624c default
parent child Browse files
Show More
@@ -1,1295 +1,1300 b''
1 # templater.py - template expansion for output
1 # templater.py - template expansion for output
2 #
2 #
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import os
10 import os
11 import re
11 import re
12 import types
12 import types
13
13
14 from .i18n import _
14 from .i18n import _
15 from . import (
15 from . import (
16 color,
16 color,
17 config,
17 config,
18 encoding,
18 encoding,
19 error,
19 error,
20 minirst,
20 minirst,
21 parser,
21 parser,
22 pycompat,
22 pycompat,
23 registrar,
23 registrar,
24 revset as revsetmod,
24 revset as revsetmod,
25 revsetlang,
25 revsetlang,
26 templatefilters,
26 templatefilters,
27 templatekw,
27 templatekw,
28 util,
28 util,
29 )
29 )
30
30
31 # template parsing
31 # template parsing
32
32
33 elements = {
33 elements = {
34 # token-type: binding-strength, primary, prefix, infix, suffix
34 # token-type: binding-strength, primary, prefix, infix, suffix
35 "(": (20, None, ("group", 1, ")"), ("func", 1, ")"), None),
35 "(": (20, None, ("group", 1, ")"), ("func", 1, ")"), None),
36 "%": (16, None, None, ("%", 16), None),
36 "%": (16, None, None, ("%", 16), None),
37 "|": (15, None, None, ("|", 15), None),
37 "|": (15, None, None, ("|", 15), None),
38 "*": (5, None, None, ("*", 5), None),
38 "*": (5, None, None, ("*", 5), None),
39 "/": (5, None, None, ("/", 5), None),
39 "/": (5, None, None, ("/", 5), None),
40 "+": (4, None, None, ("+", 4), None),
40 "+": (4, None, None, ("+", 4), None),
41 "-": (4, None, ("negate", 19), ("-", 4), None),
41 "-": (4, None, ("negate", 19), ("-", 4), None),
42 "=": (3, None, None, ("keyvalue", 3), None),
42 ",": (2, None, None, ("list", 2), None),
43 ",": (2, None, None, ("list", 2), None),
43 ")": (0, None, None, None, None),
44 ")": (0, None, None, None, None),
44 "integer": (0, "integer", None, None, None),
45 "integer": (0, "integer", None, None, None),
45 "symbol": (0, "symbol", None, None, None),
46 "symbol": (0, "symbol", None, None, None),
46 "string": (0, "string", None, None, None),
47 "string": (0, "string", None, None, None),
47 "template": (0, "template", None, None, None),
48 "template": (0, "template", None, None, None),
48 "end": (0, None, None, None, None),
49 "end": (0, None, None, None, None),
49 }
50 }
50
51
51 def tokenize(program, start, end, term=None):
52 def tokenize(program, start, end, term=None):
52 """Parse a template expression into a stream of tokens, which must end
53 """Parse a template expression into a stream of tokens, which must end
53 with term if specified"""
54 with term if specified"""
54 pos = start
55 pos = start
55 while pos < end:
56 while pos < end:
56 c = program[pos]
57 c = program[pos]
57 if c.isspace(): # skip inter-token whitespace
58 if c.isspace(): # skip inter-token whitespace
58 pass
59 pass
59 elif c in "(,)%|+-*/": # handle simple operators
60 elif c in "(=,)%|+-*/": # handle simple operators
60 yield (c, None, pos)
61 yield (c, None, pos)
61 elif c in '"\'': # handle quoted templates
62 elif c in '"\'': # handle quoted templates
62 s = pos + 1
63 s = pos + 1
63 data, pos = _parsetemplate(program, s, end, c)
64 data, pos = _parsetemplate(program, s, end, c)
64 yield ('template', data, s)
65 yield ('template', data, s)
65 pos -= 1
66 pos -= 1
66 elif c == 'r' and program[pos:pos + 2] in ("r'", 'r"'):
67 elif c == 'r' and program[pos:pos + 2] in ("r'", 'r"'):
67 # handle quoted strings
68 # handle quoted strings
68 c = program[pos + 1]
69 c = program[pos + 1]
69 s = pos = pos + 2
70 s = pos = pos + 2
70 while pos < end: # find closing quote
71 while pos < end: # find closing quote
71 d = program[pos]
72 d = program[pos]
72 if d == '\\': # skip over escaped characters
73 if d == '\\': # skip over escaped characters
73 pos += 2
74 pos += 2
74 continue
75 continue
75 if d == c:
76 if d == c:
76 yield ('string', program[s:pos], s)
77 yield ('string', program[s:pos], s)
77 break
78 break
78 pos += 1
79 pos += 1
79 else:
80 else:
80 raise error.ParseError(_("unterminated string"), s)
81 raise error.ParseError(_("unterminated string"), s)
81 elif c.isdigit():
82 elif c.isdigit():
82 s = pos
83 s = pos
83 while pos < end:
84 while pos < end:
84 d = program[pos]
85 d = program[pos]
85 if not d.isdigit():
86 if not d.isdigit():
86 break
87 break
87 pos += 1
88 pos += 1
88 yield ('integer', program[s:pos], s)
89 yield ('integer', program[s:pos], s)
89 pos -= 1
90 pos -= 1
90 elif (c == '\\' and program[pos:pos + 2] in (r"\'", r'\"')
91 elif (c == '\\' and program[pos:pos + 2] in (r"\'", r'\"')
91 or c == 'r' and program[pos:pos + 3] in (r"r\'", r'r\"')):
92 or c == 'r' and program[pos:pos + 3] in (r"r\'", r'r\"')):
92 # handle escaped quoted strings for compatibility with 2.9.2-3.4,
93 # handle escaped quoted strings for compatibility with 2.9.2-3.4,
93 # where some of nested templates were preprocessed as strings and
94 # where some of nested templates were preprocessed as strings and
94 # then compiled. therefore, \"...\" was allowed. (issue4733)
95 # then compiled. therefore, \"...\" was allowed. (issue4733)
95 #
96 #
96 # processing flow of _evalifliteral() at 5ab28a2e9962:
97 # processing flow of _evalifliteral() at 5ab28a2e9962:
97 # outer template string -> stringify() -> compiletemplate()
98 # outer template string -> stringify() -> compiletemplate()
98 # ------------------------ ------------ ------------------
99 # ------------------------ ------------ ------------------
99 # {f("\\\\ {g(\"\\\"\")}"} \\ {g("\"")} [r'\\', {g("\"")}]
100 # {f("\\\\ {g(\"\\\"\")}"} \\ {g("\"")} [r'\\', {g("\"")}]
100 # ~~~~~~~~
101 # ~~~~~~~~
101 # escaped quoted string
102 # escaped quoted string
102 if c == 'r':
103 if c == 'r':
103 pos += 1
104 pos += 1
104 token = 'string'
105 token = 'string'
105 else:
106 else:
106 token = 'template'
107 token = 'template'
107 quote = program[pos:pos + 2]
108 quote = program[pos:pos + 2]
108 s = pos = pos + 2
109 s = pos = pos + 2
109 while pos < end: # find closing escaped quote
110 while pos < end: # find closing escaped quote
110 if program.startswith('\\\\\\', pos, end):
111 if program.startswith('\\\\\\', pos, end):
111 pos += 4 # skip over double escaped characters
112 pos += 4 # skip over double escaped characters
112 continue
113 continue
113 if program.startswith(quote, pos, end):
114 if program.startswith(quote, pos, end):
114 # interpret as if it were a part of an outer string
115 # interpret as if it were a part of an outer string
115 data = parser.unescapestr(program[s:pos])
116 data = parser.unescapestr(program[s:pos])
116 if token == 'template':
117 if token == 'template':
117 data = _parsetemplate(data, 0, len(data))[0]
118 data = _parsetemplate(data, 0, len(data))[0]
118 yield (token, data, s)
119 yield (token, data, s)
119 pos += 1
120 pos += 1
120 break
121 break
121 pos += 1
122 pos += 1
122 else:
123 else:
123 raise error.ParseError(_("unterminated string"), s)
124 raise error.ParseError(_("unterminated string"), s)
124 elif c.isalnum() or c in '_':
125 elif c.isalnum() or c in '_':
125 s = pos
126 s = pos
126 pos += 1
127 pos += 1
127 while pos < end: # find end of symbol
128 while pos < end: # find end of symbol
128 d = program[pos]
129 d = program[pos]
129 if not (d.isalnum() or d == "_"):
130 if not (d.isalnum() or d == "_"):
130 break
131 break
131 pos += 1
132 pos += 1
132 sym = program[s:pos]
133 sym = program[s:pos]
133 yield ('symbol', sym, s)
134 yield ('symbol', sym, s)
134 pos -= 1
135 pos -= 1
135 elif c == term:
136 elif c == term:
136 yield ('end', None, pos + 1)
137 yield ('end', None, pos + 1)
137 return
138 return
138 else:
139 else:
139 raise error.ParseError(_("syntax error"), pos)
140 raise error.ParseError(_("syntax error"), pos)
140 pos += 1
141 pos += 1
141 if term:
142 if term:
142 raise error.ParseError(_("unterminated template expansion"), start)
143 raise error.ParseError(_("unterminated template expansion"), start)
143 yield ('end', None, pos)
144 yield ('end', None, pos)
144
145
145 def _parsetemplate(tmpl, start, stop, quote=''):
146 def _parsetemplate(tmpl, start, stop, quote=''):
146 r"""
147 r"""
147 >>> _parsetemplate('foo{bar}"baz', 0, 12)
148 >>> _parsetemplate('foo{bar}"baz', 0, 12)
148 ([('string', 'foo'), ('symbol', 'bar'), ('string', '"baz')], 12)
149 ([('string', 'foo'), ('symbol', 'bar'), ('string', '"baz')], 12)
149 >>> _parsetemplate('foo{bar}"baz', 0, 12, quote='"')
150 >>> _parsetemplate('foo{bar}"baz', 0, 12, quote='"')
150 ([('string', 'foo'), ('symbol', 'bar')], 9)
151 ([('string', 'foo'), ('symbol', 'bar')], 9)
151 >>> _parsetemplate('foo"{bar}', 0, 9, quote='"')
152 >>> _parsetemplate('foo"{bar}', 0, 9, quote='"')
152 ([('string', 'foo')], 4)
153 ([('string', 'foo')], 4)
153 >>> _parsetemplate(r'foo\"bar"baz', 0, 12, quote='"')
154 >>> _parsetemplate(r'foo\"bar"baz', 0, 12, quote='"')
154 ([('string', 'foo"'), ('string', 'bar')], 9)
155 ([('string', 'foo"'), ('string', 'bar')], 9)
155 >>> _parsetemplate(r'foo\\"bar', 0, 10, quote='"')
156 >>> _parsetemplate(r'foo\\"bar', 0, 10, quote='"')
156 ([('string', 'foo\\')], 6)
157 ([('string', 'foo\\')], 6)
157 """
158 """
158 parsed = []
159 parsed = []
159 sepchars = '{' + quote
160 sepchars = '{' + quote
160 pos = start
161 pos = start
161 p = parser.parser(elements)
162 p = parser.parser(elements)
162 while pos < stop:
163 while pos < stop:
163 n = min((tmpl.find(c, pos, stop) for c in sepchars),
164 n = min((tmpl.find(c, pos, stop) for c in sepchars),
164 key=lambda n: (n < 0, n))
165 key=lambda n: (n < 0, n))
165 if n < 0:
166 if n < 0:
166 parsed.append(('string', parser.unescapestr(tmpl[pos:stop])))
167 parsed.append(('string', parser.unescapestr(tmpl[pos:stop])))
167 pos = stop
168 pos = stop
168 break
169 break
169 c = tmpl[n]
170 c = tmpl[n]
170 bs = (n - pos) - len(tmpl[pos:n].rstrip('\\'))
171 bs = (n - pos) - len(tmpl[pos:n].rstrip('\\'))
171 if bs % 2 == 1:
172 if bs % 2 == 1:
172 # escaped (e.g. '\{', '\\\{', but not '\\{')
173 # escaped (e.g. '\{', '\\\{', but not '\\{')
173 parsed.append(('string', parser.unescapestr(tmpl[pos:n - 1]) + c))
174 parsed.append(('string', parser.unescapestr(tmpl[pos:n - 1]) + c))
174 pos = n + 1
175 pos = n + 1
175 continue
176 continue
176 if n > pos:
177 if n > pos:
177 parsed.append(('string', parser.unescapestr(tmpl[pos:n])))
178 parsed.append(('string', parser.unescapestr(tmpl[pos:n])))
178 if c == quote:
179 if c == quote:
179 return parsed, n + 1
180 return parsed, n + 1
180
181
181 parseres, pos = p.parse(tokenize(tmpl, n + 1, stop, '}'))
182 parseres, pos = p.parse(tokenize(tmpl, n + 1, stop, '}'))
182 parsed.append(parseres)
183 parsed.append(parseres)
183
184
184 if quote:
185 if quote:
185 raise error.ParseError(_("unterminated string"), start)
186 raise error.ParseError(_("unterminated string"), start)
186 return parsed, pos
187 return parsed, pos
187
188
188 def _unnesttemplatelist(tree):
189 def _unnesttemplatelist(tree):
189 """Expand list of templates to node tuple
190 """Expand list of templates to node tuple
190
191
191 >>> def f(tree):
192 >>> def f(tree):
192 ... print prettyformat(_unnesttemplatelist(tree))
193 ... print prettyformat(_unnesttemplatelist(tree))
193 >>> f(('template', []))
194 >>> f(('template', []))
194 ('string', '')
195 ('string', '')
195 >>> f(('template', [('string', 'foo')]))
196 >>> f(('template', [('string', 'foo')]))
196 ('string', 'foo')
197 ('string', 'foo')
197 >>> f(('template', [('string', 'foo'), ('symbol', 'rev')]))
198 >>> f(('template', [('string', 'foo'), ('symbol', 'rev')]))
198 (template
199 (template
199 ('string', 'foo')
200 ('string', 'foo')
200 ('symbol', 'rev'))
201 ('symbol', 'rev'))
201 >>> f(('template', [('symbol', 'rev')])) # template(rev) -> str
202 >>> f(('template', [('symbol', 'rev')])) # template(rev) -> str
202 (template
203 (template
203 ('symbol', 'rev'))
204 ('symbol', 'rev'))
204 >>> f(('template', [('template', [('string', 'foo')])]))
205 >>> f(('template', [('template', [('string', 'foo')])]))
205 ('string', 'foo')
206 ('string', 'foo')
206 """
207 """
207 if not isinstance(tree, tuple):
208 if not isinstance(tree, tuple):
208 return tree
209 return tree
209 op = tree[0]
210 op = tree[0]
210 if op != 'template':
211 if op != 'template':
211 return (op,) + tuple(_unnesttemplatelist(x) for x in tree[1:])
212 return (op,) + tuple(_unnesttemplatelist(x) for x in tree[1:])
212
213
213 assert len(tree) == 2
214 assert len(tree) == 2
214 xs = tuple(_unnesttemplatelist(x) for x in tree[1])
215 xs = tuple(_unnesttemplatelist(x) for x in tree[1])
215 if not xs:
216 if not xs:
216 return ('string', '') # empty template ""
217 return ('string', '') # empty template ""
217 elif len(xs) == 1 and xs[0][0] == 'string':
218 elif len(xs) == 1 and xs[0][0] == 'string':
218 return xs[0] # fast path for string with no template fragment "x"
219 return xs[0] # fast path for string with no template fragment "x"
219 else:
220 else:
220 return (op,) + xs
221 return (op,) + xs
221
222
222 def parse(tmpl):
223 def parse(tmpl):
223 """Parse template string into tree"""
224 """Parse template string into tree"""
224 parsed, pos = _parsetemplate(tmpl, 0, len(tmpl))
225 parsed, pos = _parsetemplate(tmpl, 0, len(tmpl))
225 assert pos == len(tmpl), 'unquoted template should be consumed'
226 assert pos == len(tmpl), 'unquoted template should be consumed'
226 return _unnesttemplatelist(('template', parsed))
227 return _unnesttemplatelist(('template', parsed))
227
228
228 def _parseexpr(expr):
229 def _parseexpr(expr):
229 """Parse a template expression into tree
230 """Parse a template expression into tree
230
231
231 >>> _parseexpr('"foo"')
232 >>> _parseexpr('"foo"')
232 ('string', 'foo')
233 ('string', 'foo')
233 >>> _parseexpr('foo(bar)')
234 >>> _parseexpr('foo(bar)')
234 ('func', ('symbol', 'foo'), ('symbol', 'bar'))
235 ('func', ('symbol', 'foo'), ('symbol', 'bar'))
235 >>> _parseexpr('foo(')
236 >>> _parseexpr('foo(')
236 Traceback (most recent call last):
237 Traceback (most recent call last):
237 ...
238 ...
238 ParseError: ('not a prefix: end', 4)
239 ParseError: ('not a prefix: end', 4)
239 >>> _parseexpr('"foo" "bar"')
240 >>> _parseexpr('"foo" "bar"')
240 Traceback (most recent call last):
241 Traceback (most recent call last):
241 ...
242 ...
242 ParseError: ('invalid token', 7)
243 ParseError: ('invalid token', 7)
243 """
244 """
244 p = parser.parser(elements)
245 p = parser.parser(elements)
245 tree, pos = p.parse(tokenize(expr, 0, len(expr)))
246 tree, pos = p.parse(tokenize(expr, 0, len(expr)))
246 if pos != len(expr):
247 if pos != len(expr):
247 raise error.ParseError(_('invalid token'), pos)
248 raise error.ParseError(_('invalid token'), pos)
248 return _unnesttemplatelist(tree)
249 return _unnesttemplatelist(tree)
249
250
250 def prettyformat(tree):
251 def prettyformat(tree):
251 return parser.prettyformat(tree, ('integer', 'string', 'symbol'))
252 return parser.prettyformat(tree, ('integer', 'string', 'symbol'))
252
253
253 def compileexp(exp, context, curmethods):
254 def compileexp(exp, context, curmethods):
254 """Compile parsed template tree to (func, data) pair"""
255 """Compile parsed template tree to (func, data) pair"""
255 t = exp[0]
256 t = exp[0]
256 if t in curmethods:
257 if t in curmethods:
257 return curmethods[t](exp, context)
258 return curmethods[t](exp, context)
258 raise error.ParseError(_("unknown method '%s'") % t)
259 raise error.ParseError(_("unknown method '%s'") % t)
259
260
260 # template evaluation
261 # template evaluation
261
262
262 def getsymbol(exp):
263 def getsymbol(exp):
263 if exp[0] == 'symbol':
264 if exp[0] == 'symbol':
264 return exp[1]
265 return exp[1]
265 raise error.ParseError(_("expected a symbol, got '%s'") % exp[0])
266 raise error.ParseError(_("expected a symbol, got '%s'") % exp[0])
266
267
267 def getlist(x):
268 def getlist(x):
268 if not x:
269 if not x:
269 return []
270 return []
270 if x[0] == 'list':
271 if x[0] == 'list':
271 return getlist(x[1]) + [x[2]]
272 return getlist(x[1]) + [x[2]]
272 return [x]
273 return [x]
273
274
274 def gettemplate(exp, context):
275 def gettemplate(exp, context):
275 """Compile given template tree or load named template from map file;
276 """Compile given template tree or load named template from map file;
276 returns (func, data) pair"""
277 returns (func, data) pair"""
277 if exp[0] in ('template', 'string'):
278 if exp[0] in ('template', 'string'):
278 return compileexp(exp, context, methods)
279 return compileexp(exp, context, methods)
279 if exp[0] == 'symbol':
280 if exp[0] == 'symbol':
280 # unlike runsymbol(), here 'symbol' is always taken as template name
281 # unlike runsymbol(), here 'symbol' is always taken as template name
281 # even if it exists in mapping. this allows us to override mapping
282 # even if it exists in mapping. this allows us to override mapping
282 # by web templates, e.g. 'changelogtag' is redefined in map file.
283 # by web templates, e.g. 'changelogtag' is redefined in map file.
283 return context._load(exp[1])
284 return context._load(exp[1])
284 raise error.ParseError(_("expected template specifier"))
285 raise error.ParseError(_("expected template specifier"))
285
286
286 def evalfuncarg(context, mapping, arg):
287 def evalfuncarg(context, mapping, arg):
287 func, data = arg
288 func, data = arg
288 # func() may return string, generator of strings or arbitrary object such
289 # func() may return string, generator of strings or arbitrary object such
289 # as date tuple, but filter does not want generator.
290 # as date tuple, but filter does not want generator.
290 thing = func(context, mapping, data)
291 thing = func(context, mapping, data)
291 if isinstance(thing, types.GeneratorType):
292 if isinstance(thing, types.GeneratorType):
292 thing = stringify(thing)
293 thing = stringify(thing)
293 return thing
294 return thing
294
295
295 def evalboolean(context, mapping, arg):
296 def evalboolean(context, mapping, arg):
296 """Evaluate given argument as boolean, but also takes boolean literals"""
297 """Evaluate given argument as boolean, but also takes boolean literals"""
297 func, data = arg
298 func, data = arg
298 if func is runsymbol:
299 if func is runsymbol:
299 thing = func(context, mapping, data, default=None)
300 thing = func(context, mapping, data, default=None)
300 if thing is None:
301 if thing is None:
301 # not a template keyword, takes as a boolean literal
302 # not a template keyword, takes as a boolean literal
302 thing = util.parsebool(data)
303 thing = util.parsebool(data)
303 else:
304 else:
304 thing = func(context, mapping, data)
305 thing = func(context, mapping, data)
305 if isinstance(thing, bool):
306 if isinstance(thing, bool):
306 return thing
307 return thing
307 # other objects are evaluated as strings, which means 0 is True, but
308 # other objects are evaluated as strings, which means 0 is True, but
308 # empty dict/list should be False as they are expected to be ''
309 # empty dict/list should be False as they are expected to be ''
309 return bool(stringify(thing))
310 return bool(stringify(thing))
310
311
311 def evalinteger(context, mapping, arg, err):
312 def evalinteger(context, mapping, arg, err):
312 v = evalfuncarg(context, mapping, arg)
313 v = evalfuncarg(context, mapping, arg)
313 try:
314 try:
314 return int(v)
315 return int(v)
315 except (TypeError, ValueError):
316 except (TypeError, ValueError):
316 raise error.ParseError(err)
317 raise error.ParseError(err)
317
318
318 def evalstring(context, mapping, arg):
319 def evalstring(context, mapping, arg):
319 func, data = arg
320 func, data = arg
320 return stringify(func(context, mapping, data))
321 return stringify(func(context, mapping, data))
321
322
322 def evalstringliteral(context, mapping, arg):
323 def evalstringliteral(context, mapping, arg):
323 """Evaluate given argument as string template, but returns symbol name
324 """Evaluate given argument as string template, but returns symbol name
324 if it is unknown"""
325 if it is unknown"""
325 func, data = arg
326 func, data = arg
326 if func is runsymbol:
327 if func is runsymbol:
327 thing = func(context, mapping, data, default=data)
328 thing = func(context, mapping, data, default=data)
328 else:
329 else:
329 thing = func(context, mapping, data)
330 thing = func(context, mapping, data)
330 return stringify(thing)
331 return stringify(thing)
331
332
332 def runinteger(context, mapping, data):
333 def runinteger(context, mapping, data):
333 return int(data)
334 return int(data)
334
335
335 def runstring(context, mapping, data):
336 def runstring(context, mapping, data):
336 return data
337 return data
337
338
338 def _recursivesymbolblocker(key):
339 def _recursivesymbolblocker(key):
339 def showrecursion(**args):
340 def showrecursion(**args):
340 raise error.Abort(_("recursive reference '%s' in template") % key)
341 raise error.Abort(_("recursive reference '%s' in template") % key)
341 return showrecursion
342 return showrecursion
342
343
343 def _runrecursivesymbol(context, mapping, key):
344 def _runrecursivesymbol(context, mapping, key):
344 raise error.Abort(_("recursive reference '%s' in template") % key)
345 raise error.Abort(_("recursive reference '%s' in template") % key)
345
346
346 def runsymbol(context, mapping, key, default=''):
347 def runsymbol(context, mapping, key, default=''):
347 v = mapping.get(key)
348 v = mapping.get(key)
348 if v is None:
349 if v is None:
349 v = context._defaults.get(key)
350 v = context._defaults.get(key)
350 if v is None:
351 if v is None:
351 # put poison to cut recursion. we can't move this to parsing phase
352 # put poison to cut recursion. we can't move this to parsing phase
352 # because "x = {x}" is allowed if "x" is a keyword. (issue4758)
353 # because "x = {x}" is allowed if "x" is a keyword. (issue4758)
353 safemapping = mapping.copy()
354 safemapping = mapping.copy()
354 safemapping[key] = _recursivesymbolblocker(key)
355 safemapping[key] = _recursivesymbolblocker(key)
355 try:
356 try:
356 v = context.process(key, safemapping)
357 v = context.process(key, safemapping)
357 except TemplateNotFound:
358 except TemplateNotFound:
358 v = default
359 v = default
359 if callable(v):
360 if callable(v):
360 return v(**mapping)
361 return v(**mapping)
361 return v
362 return v
362
363
363 def buildtemplate(exp, context):
364 def buildtemplate(exp, context):
364 ctmpl = [compileexp(e, context, methods) for e in exp[1:]]
365 ctmpl = [compileexp(e, context, methods) for e in exp[1:]]
365 return (runtemplate, ctmpl)
366 return (runtemplate, ctmpl)
366
367
367 def runtemplate(context, mapping, template):
368 def runtemplate(context, mapping, template):
368 for func, data in template:
369 for func, data in template:
369 yield func(context, mapping, data)
370 yield func(context, mapping, data)
370
371
371 def buildfilter(exp, context):
372 def buildfilter(exp, context):
372 arg = compileexp(exp[1], context, methods)
373 arg = compileexp(exp[1], context, methods)
373 n = getsymbol(exp[2])
374 n = getsymbol(exp[2])
374 if n in context._filters:
375 if n in context._filters:
375 filt = context._filters[n]
376 filt = context._filters[n]
376 return (runfilter, (arg, filt))
377 return (runfilter, (arg, filt))
377 if n in funcs:
378 if n in funcs:
378 f = funcs[n]
379 f = funcs[n]
379 return (f, [arg])
380 return (f, [arg])
380 raise error.ParseError(_("unknown function '%s'") % n)
381 raise error.ParseError(_("unknown function '%s'") % n)
381
382
382 def runfilter(context, mapping, data):
383 def runfilter(context, mapping, data):
383 arg, filt = data
384 arg, filt = data
384 thing = evalfuncarg(context, mapping, arg)
385 thing = evalfuncarg(context, mapping, arg)
385 try:
386 try:
386 return filt(thing)
387 return filt(thing)
387 except (ValueError, AttributeError, TypeError):
388 except (ValueError, AttributeError, TypeError):
388 if isinstance(arg[1], tuple):
389 if isinstance(arg[1], tuple):
389 dt = arg[1][1]
390 dt = arg[1][1]
390 else:
391 else:
391 dt = arg[1]
392 dt = arg[1]
392 raise error.Abort(_("template filter '%s' is not compatible with "
393 raise error.Abort(_("template filter '%s' is not compatible with "
393 "keyword '%s'") % (filt.func_name, dt))
394 "keyword '%s'") % (filt.func_name, dt))
394
395
395 def buildmap(exp, context):
396 def buildmap(exp, context):
396 func, data = compileexp(exp[1], context, methods)
397 func, data = compileexp(exp[1], context, methods)
397 tfunc, tdata = gettemplate(exp[2], context)
398 tfunc, tdata = gettemplate(exp[2], context)
398 return (runmap, (func, data, tfunc, tdata))
399 return (runmap, (func, data, tfunc, tdata))
399
400
400 def runmap(context, mapping, data):
401 def runmap(context, mapping, data):
401 func, data, tfunc, tdata = data
402 func, data, tfunc, tdata = data
402 d = func(context, mapping, data)
403 d = func(context, mapping, data)
403 if util.safehasattr(d, 'itermaps'):
404 if util.safehasattr(d, 'itermaps'):
404 diter = d.itermaps()
405 diter = d.itermaps()
405 else:
406 else:
406 try:
407 try:
407 diter = iter(d)
408 diter = iter(d)
408 except TypeError:
409 except TypeError:
409 if func is runsymbol:
410 if func is runsymbol:
410 raise error.ParseError(_("keyword '%s' is not iterable") % data)
411 raise error.ParseError(_("keyword '%s' is not iterable") % data)
411 else:
412 else:
412 raise error.ParseError(_("%r is not iterable") % d)
413 raise error.ParseError(_("%r is not iterable") % d)
413
414
414 for i, v in enumerate(diter):
415 for i, v in enumerate(diter):
415 lm = mapping.copy()
416 lm = mapping.copy()
416 lm['index'] = i
417 lm['index'] = i
417 if isinstance(v, dict):
418 if isinstance(v, dict):
418 lm.update(v)
419 lm.update(v)
419 lm['originalnode'] = mapping.get('node')
420 lm['originalnode'] = mapping.get('node')
420 yield tfunc(context, lm, tdata)
421 yield tfunc(context, lm, tdata)
421 else:
422 else:
422 # v is not an iterable of dicts, this happen when 'key'
423 # v is not an iterable of dicts, this happen when 'key'
423 # has been fully expanded already and format is useless.
424 # has been fully expanded already and format is useless.
424 # If so, return the expanded value.
425 # If so, return the expanded value.
425 yield v
426 yield v
426
427
427 def buildnegate(exp, context):
428 def buildnegate(exp, context):
428 arg = compileexp(exp[1], context, exprmethods)
429 arg = compileexp(exp[1], context, exprmethods)
429 return (runnegate, arg)
430 return (runnegate, arg)
430
431
431 def runnegate(context, mapping, data):
432 def runnegate(context, mapping, data):
432 data = evalinteger(context, mapping, data,
433 data = evalinteger(context, mapping, data,
433 _('negation needs an integer argument'))
434 _('negation needs an integer argument'))
434 return -data
435 return -data
435
436
436 def buildarithmetic(exp, context, func):
437 def buildarithmetic(exp, context, func):
437 left = compileexp(exp[1], context, exprmethods)
438 left = compileexp(exp[1], context, exprmethods)
438 right = compileexp(exp[2], context, exprmethods)
439 right = compileexp(exp[2], context, exprmethods)
439 return (runarithmetic, (func, left, right))
440 return (runarithmetic, (func, left, right))
440
441
441 def runarithmetic(context, mapping, data):
442 def runarithmetic(context, mapping, data):
442 func, left, right = data
443 func, left, right = data
443 left = evalinteger(context, mapping, left,
444 left = evalinteger(context, mapping, left,
444 _('arithmetic only defined on integers'))
445 _('arithmetic only defined on integers'))
445 right = evalinteger(context, mapping, right,
446 right = evalinteger(context, mapping, right,
446 _('arithmetic only defined on integers'))
447 _('arithmetic only defined on integers'))
447 try:
448 try:
448 return func(left, right)
449 return func(left, right)
449 except ZeroDivisionError:
450 except ZeroDivisionError:
450 raise error.Abort(_('division by zero is not defined'))
451 raise error.Abort(_('division by zero is not defined'))
451
452
452 def buildfunc(exp, context):
453 def buildfunc(exp, context):
453 n = getsymbol(exp[1])
454 n = getsymbol(exp[1])
454 args = [compileexp(x, context, exprmethods) for x in getlist(exp[2])]
455 args = [compileexp(x, context, exprmethods) for x in getlist(exp[2])]
455 if n in funcs:
456 if n in funcs:
456 f = funcs[n]
457 f = funcs[n]
457 return (f, args)
458 return (f, args)
458 if n in context._filters:
459 if n in context._filters:
459 if len(args) != 1:
460 if len(args) != 1:
460 raise error.ParseError(_("filter %s expects one argument") % n)
461 raise error.ParseError(_("filter %s expects one argument") % n)
461 f = context._filters[n]
462 f = context._filters[n]
462 return (runfilter, (args[0], f))
463 return (runfilter, (args[0], f))
463 raise error.ParseError(_("unknown function '%s'") % n)
464 raise error.ParseError(_("unknown function '%s'") % n)
464
465
466 def buildkeyvaluepair(exp, content):
467 raise error.ParseError(_("can't use a key-value pair in this context"))
468
465 # dict of template built-in functions
469 # dict of template built-in functions
466 funcs = {}
470 funcs = {}
467
471
468 templatefunc = registrar.templatefunc(funcs)
472 templatefunc = registrar.templatefunc(funcs)
469
473
470 @templatefunc('date(date[, fmt])')
474 @templatefunc('date(date[, fmt])')
471 def date(context, mapping, args):
475 def date(context, mapping, args):
472 """Format a date. See :hg:`help dates` for formatting
476 """Format a date. See :hg:`help dates` for formatting
473 strings. The default is a Unix date format, including the timezone:
477 strings. The default is a Unix date format, including the timezone:
474 "Mon Sep 04 15:13:13 2006 0700"."""
478 "Mon Sep 04 15:13:13 2006 0700"."""
475 if not (1 <= len(args) <= 2):
479 if not (1 <= len(args) <= 2):
476 # i18n: "date" is a keyword
480 # i18n: "date" is a keyword
477 raise error.ParseError(_("date expects one or two arguments"))
481 raise error.ParseError(_("date expects one or two arguments"))
478
482
479 date = evalfuncarg(context, mapping, args[0])
483 date = evalfuncarg(context, mapping, args[0])
480 fmt = None
484 fmt = None
481 if len(args) == 2:
485 if len(args) == 2:
482 fmt = evalstring(context, mapping, args[1])
486 fmt = evalstring(context, mapping, args[1])
483 try:
487 try:
484 if fmt is None:
488 if fmt is None:
485 return util.datestr(date)
489 return util.datestr(date)
486 else:
490 else:
487 return util.datestr(date, fmt)
491 return util.datestr(date, fmt)
488 except (TypeError, ValueError):
492 except (TypeError, ValueError):
489 # i18n: "date" is a keyword
493 # i18n: "date" is a keyword
490 raise error.ParseError(_("date expects a date information"))
494 raise error.ParseError(_("date expects a date information"))
491
495
492 @templatefunc('diff([includepattern [, excludepattern]])')
496 @templatefunc('diff([includepattern [, excludepattern]])')
493 def diff(context, mapping, args):
497 def diff(context, mapping, args):
494 """Show a diff, optionally
498 """Show a diff, optionally
495 specifying files to include or exclude."""
499 specifying files to include or exclude."""
496 if len(args) > 2:
500 if len(args) > 2:
497 # i18n: "diff" is a keyword
501 # i18n: "diff" is a keyword
498 raise error.ParseError(_("diff expects zero, one, or two arguments"))
502 raise error.ParseError(_("diff expects zero, one, or two arguments"))
499
503
500 def getpatterns(i):
504 def getpatterns(i):
501 if i < len(args):
505 if i < len(args):
502 s = evalstring(context, mapping, args[i]).strip()
506 s = evalstring(context, mapping, args[i]).strip()
503 if s:
507 if s:
504 return [s]
508 return [s]
505 return []
509 return []
506
510
507 ctx = mapping['ctx']
511 ctx = mapping['ctx']
508 chunks = ctx.diff(match=ctx.match([], getpatterns(0), getpatterns(1)))
512 chunks = ctx.diff(match=ctx.match([], getpatterns(0), getpatterns(1)))
509
513
510 return ''.join(chunks)
514 return ''.join(chunks)
511
515
512 @templatefunc('files(pattern)')
516 @templatefunc('files(pattern)')
513 def files(context, mapping, args):
517 def files(context, mapping, args):
514 """All files of the current changeset matching the pattern. See
518 """All files of the current changeset matching the pattern. See
515 :hg:`help patterns`."""
519 :hg:`help patterns`."""
516 if not len(args) == 1:
520 if not len(args) == 1:
517 # i18n: "files" is a keyword
521 # i18n: "files" is a keyword
518 raise error.ParseError(_("files expects one argument"))
522 raise error.ParseError(_("files expects one argument"))
519
523
520 raw = evalstring(context, mapping, args[0])
524 raw = evalstring(context, mapping, args[0])
521 ctx = mapping['ctx']
525 ctx = mapping['ctx']
522 m = ctx.match([raw])
526 m = ctx.match([raw])
523 files = list(ctx.matches(m))
527 files = list(ctx.matches(m))
524 return templatekw.showlist("file", files, **mapping)
528 return templatekw.showlist("file", files, **mapping)
525
529
526 @templatefunc('fill(text[, width[, initialident[, hangindent]]])')
530 @templatefunc('fill(text[, width[, initialident[, hangindent]]])')
527 def fill(context, mapping, args):
531 def fill(context, mapping, args):
528 """Fill many
532 """Fill many
529 paragraphs with optional indentation. See the "fill" filter."""
533 paragraphs with optional indentation. See the "fill" filter."""
530 if not (1 <= len(args) <= 4):
534 if not (1 <= len(args) <= 4):
531 # i18n: "fill" is a keyword
535 # i18n: "fill" is a keyword
532 raise error.ParseError(_("fill expects one to four arguments"))
536 raise error.ParseError(_("fill expects one to four arguments"))
533
537
534 text = evalstring(context, mapping, args[0])
538 text = evalstring(context, mapping, args[0])
535 width = 76
539 width = 76
536 initindent = ''
540 initindent = ''
537 hangindent = ''
541 hangindent = ''
538 if 2 <= len(args) <= 4:
542 if 2 <= len(args) <= 4:
539 width = evalinteger(context, mapping, args[1],
543 width = evalinteger(context, mapping, args[1],
540 # i18n: "fill" is a keyword
544 # i18n: "fill" is a keyword
541 _("fill expects an integer width"))
545 _("fill expects an integer width"))
542 try:
546 try:
543 initindent = evalstring(context, mapping, args[2])
547 initindent = evalstring(context, mapping, args[2])
544 hangindent = evalstring(context, mapping, args[3])
548 hangindent = evalstring(context, mapping, args[3])
545 except IndexError:
549 except IndexError:
546 pass
550 pass
547
551
548 return templatefilters.fill(text, width, initindent, hangindent)
552 return templatefilters.fill(text, width, initindent, hangindent)
549
553
550 @templatefunc('formatnode(node)')
554 @templatefunc('formatnode(node)')
551 def formatnode(context, mapping, args):
555 def formatnode(context, mapping, args):
552 """Obtain the preferred form of a changeset hash. (DEPRECATED)"""
556 """Obtain the preferred form of a changeset hash. (DEPRECATED)"""
553 if len(args) != 1:
557 if len(args) != 1:
554 # i18n: "formatnode" is a keyword
558 # i18n: "formatnode" is a keyword
555 raise error.ParseError(_("formatnode expects one argument"))
559 raise error.ParseError(_("formatnode expects one argument"))
556
560
557 ui = mapping['ui']
561 ui = mapping['ui']
558 node = evalstring(context, mapping, args[0])
562 node = evalstring(context, mapping, args[0])
559 if ui.debugflag:
563 if ui.debugflag:
560 return node
564 return node
561 return templatefilters.short(node)
565 return templatefilters.short(node)
562
566
563 @templatefunc('pad(text, width[, fillchar=\' \'[, left=False]])')
567 @templatefunc('pad(text, width[, fillchar=\' \'[, left=False]])')
564 def pad(context, mapping, args):
568 def pad(context, mapping, args):
565 """Pad text with a
569 """Pad text with a
566 fill character."""
570 fill character."""
567 if not (2 <= len(args) <= 4):
571 if not (2 <= len(args) <= 4):
568 # i18n: "pad" is a keyword
572 # i18n: "pad" is a keyword
569 raise error.ParseError(_("pad() expects two to four arguments"))
573 raise error.ParseError(_("pad() expects two to four arguments"))
570
574
571 width = evalinteger(context, mapping, args[1],
575 width = evalinteger(context, mapping, args[1],
572 # i18n: "pad" is a keyword
576 # i18n: "pad" is a keyword
573 _("pad() expects an integer width"))
577 _("pad() expects an integer width"))
574
578
575 text = evalstring(context, mapping, args[0])
579 text = evalstring(context, mapping, args[0])
576
580
577 left = False
581 left = False
578 fillchar = ' '
582 fillchar = ' '
579 if len(args) > 2:
583 if len(args) > 2:
580 fillchar = evalstring(context, mapping, args[2])
584 fillchar = evalstring(context, mapping, args[2])
581 if len(color.stripeffects(fillchar)) != 1:
585 if len(color.stripeffects(fillchar)) != 1:
582 # i18n: "pad" is a keyword
586 # i18n: "pad" is a keyword
583 raise error.ParseError(_("pad() expects a single fill character"))
587 raise error.ParseError(_("pad() expects a single fill character"))
584 if len(args) > 3:
588 if len(args) > 3:
585 left = evalboolean(context, mapping, args[3])
589 left = evalboolean(context, mapping, args[3])
586
590
587 fillwidth = width - encoding.colwidth(color.stripeffects(text))
591 fillwidth = width - encoding.colwidth(color.stripeffects(text))
588 if fillwidth <= 0:
592 if fillwidth <= 0:
589 return text
593 return text
590 if left:
594 if left:
591 return fillchar * fillwidth + text
595 return fillchar * fillwidth + text
592 else:
596 else:
593 return text + fillchar * fillwidth
597 return text + fillchar * fillwidth
594
598
595 @templatefunc('indent(text, indentchars[, firstline])')
599 @templatefunc('indent(text, indentchars[, firstline])')
596 def indent(context, mapping, args):
600 def indent(context, mapping, args):
597 """Indents all non-empty lines
601 """Indents all non-empty lines
598 with the characters given in the indentchars string. An optional
602 with the characters given in the indentchars string. An optional
599 third parameter will override the indent for the first line only
603 third parameter will override the indent for the first line only
600 if present."""
604 if present."""
601 if not (2 <= len(args) <= 3):
605 if not (2 <= len(args) <= 3):
602 # i18n: "indent" is a keyword
606 # i18n: "indent" is a keyword
603 raise error.ParseError(_("indent() expects two or three arguments"))
607 raise error.ParseError(_("indent() expects two or three arguments"))
604
608
605 text = evalstring(context, mapping, args[0])
609 text = evalstring(context, mapping, args[0])
606 indent = evalstring(context, mapping, args[1])
610 indent = evalstring(context, mapping, args[1])
607
611
608 if len(args) == 3:
612 if len(args) == 3:
609 firstline = evalstring(context, mapping, args[2])
613 firstline = evalstring(context, mapping, args[2])
610 else:
614 else:
611 firstline = indent
615 firstline = indent
612
616
613 # the indent function doesn't indent the first line, so we do it here
617 # the indent function doesn't indent the first line, so we do it here
614 return templatefilters.indent(firstline + text, indent)
618 return templatefilters.indent(firstline + text, indent)
615
619
616 @templatefunc('get(dict, key)')
620 @templatefunc('get(dict, key)')
617 def get(context, mapping, args):
621 def get(context, mapping, args):
618 """Get an attribute/key from an object. Some keywords
622 """Get an attribute/key from an object. Some keywords
619 are complex types. This function allows you to obtain the value of an
623 are complex types. This function allows you to obtain the value of an
620 attribute on these types."""
624 attribute on these types."""
621 if len(args) != 2:
625 if len(args) != 2:
622 # i18n: "get" is a keyword
626 # i18n: "get" is a keyword
623 raise error.ParseError(_("get() expects two arguments"))
627 raise error.ParseError(_("get() expects two arguments"))
624
628
625 dictarg = evalfuncarg(context, mapping, args[0])
629 dictarg = evalfuncarg(context, mapping, args[0])
626 if not util.safehasattr(dictarg, 'get'):
630 if not util.safehasattr(dictarg, 'get'):
627 # i18n: "get" is a keyword
631 # i18n: "get" is a keyword
628 raise error.ParseError(_("get() expects a dict as first argument"))
632 raise error.ParseError(_("get() expects a dict as first argument"))
629
633
630 key = evalfuncarg(context, mapping, args[1])
634 key = evalfuncarg(context, mapping, args[1])
631 return dictarg.get(key)
635 return dictarg.get(key)
632
636
633 @templatefunc('if(expr, then[, else])')
637 @templatefunc('if(expr, then[, else])')
634 def if_(context, mapping, args):
638 def if_(context, mapping, args):
635 """Conditionally execute based on the result of
639 """Conditionally execute based on the result of
636 an expression."""
640 an expression."""
637 if not (2 <= len(args) <= 3):
641 if not (2 <= len(args) <= 3):
638 # i18n: "if" is a keyword
642 # i18n: "if" is a keyword
639 raise error.ParseError(_("if expects two or three arguments"))
643 raise error.ParseError(_("if expects two or three arguments"))
640
644
641 test = evalboolean(context, mapping, args[0])
645 test = evalboolean(context, mapping, args[0])
642 if test:
646 if test:
643 yield args[1][0](context, mapping, args[1][1])
647 yield args[1][0](context, mapping, args[1][1])
644 elif len(args) == 3:
648 elif len(args) == 3:
645 yield args[2][0](context, mapping, args[2][1])
649 yield args[2][0](context, mapping, args[2][1])
646
650
647 @templatefunc('ifcontains(needle, haystack, then[, else])')
651 @templatefunc('ifcontains(needle, haystack, then[, else])')
648 def ifcontains(context, mapping, args):
652 def ifcontains(context, mapping, args):
649 """Conditionally execute based
653 """Conditionally execute based
650 on whether the item "needle" is in "haystack"."""
654 on whether the item "needle" is in "haystack"."""
651 if not (3 <= len(args) <= 4):
655 if not (3 <= len(args) <= 4):
652 # i18n: "ifcontains" is a keyword
656 # i18n: "ifcontains" is a keyword
653 raise error.ParseError(_("ifcontains expects three or four arguments"))
657 raise error.ParseError(_("ifcontains expects three or four arguments"))
654
658
655 needle = evalstring(context, mapping, args[0])
659 needle = evalstring(context, mapping, args[0])
656 haystack = evalfuncarg(context, mapping, args[1])
660 haystack = evalfuncarg(context, mapping, args[1])
657
661
658 if needle in haystack:
662 if needle in haystack:
659 yield args[2][0](context, mapping, args[2][1])
663 yield args[2][0](context, mapping, args[2][1])
660 elif len(args) == 4:
664 elif len(args) == 4:
661 yield args[3][0](context, mapping, args[3][1])
665 yield args[3][0](context, mapping, args[3][1])
662
666
663 @templatefunc('ifeq(expr1, expr2, then[, else])')
667 @templatefunc('ifeq(expr1, expr2, then[, else])')
664 def ifeq(context, mapping, args):
668 def ifeq(context, mapping, args):
665 """Conditionally execute based on
669 """Conditionally execute based on
666 whether 2 items are equivalent."""
670 whether 2 items are equivalent."""
667 if not (3 <= len(args) <= 4):
671 if not (3 <= len(args) <= 4):
668 # i18n: "ifeq" is a keyword
672 # i18n: "ifeq" is a keyword
669 raise error.ParseError(_("ifeq expects three or four arguments"))
673 raise error.ParseError(_("ifeq expects three or four arguments"))
670
674
671 test = evalstring(context, mapping, args[0])
675 test = evalstring(context, mapping, args[0])
672 match = evalstring(context, mapping, args[1])
676 match = evalstring(context, mapping, args[1])
673 if test == match:
677 if test == match:
674 yield args[2][0](context, mapping, args[2][1])
678 yield args[2][0](context, mapping, args[2][1])
675 elif len(args) == 4:
679 elif len(args) == 4:
676 yield args[3][0](context, mapping, args[3][1])
680 yield args[3][0](context, mapping, args[3][1])
677
681
678 @templatefunc('join(list, sep)')
682 @templatefunc('join(list, sep)')
679 def join(context, mapping, args):
683 def join(context, mapping, args):
680 """Join items in a list with a delimiter."""
684 """Join items in a list with a delimiter."""
681 if not (1 <= len(args) <= 2):
685 if not (1 <= len(args) <= 2):
682 # i18n: "join" is a keyword
686 # i18n: "join" is a keyword
683 raise error.ParseError(_("join expects one or two arguments"))
687 raise error.ParseError(_("join expects one or two arguments"))
684
688
685 joinset = args[0][0](context, mapping, args[0][1])
689 joinset = args[0][0](context, mapping, args[0][1])
686 if util.safehasattr(joinset, 'itermaps'):
690 if util.safehasattr(joinset, 'itermaps'):
687 jf = joinset.joinfmt
691 jf = joinset.joinfmt
688 joinset = [jf(x) for x in joinset.itermaps()]
692 joinset = [jf(x) for x in joinset.itermaps()]
689
693
690 joiner = " "
694 joiner = " "
691 if len(args) > 1:
695 if len(args) > 1:
692 joiner = evalstring(context, mapping, args[1])
696 joiner = evalstring(context, mapping, args[1])
693
697
694 first = True
698 first = True
695 for x in joinset:
699 for x in joinset:
696 if first:
700 if first:
697 first = False
701 first = False
698 else:
702 else:
699 yield joiner
703 yield joiner
700 yield x
704 yield x
701
705
702 @templatefunc('label(label, expr)')
706 @templatefunc('label(label, expr)')
703 def label(context, mapping, args):
707 def label(context, mapping, args):
704 """Apply a label to generated content. Content with
708 """Apply a label to generated content. Content with
705 a label applied can result in additional post-processing, such as
709 a label applied can result in additional post-processing, such as
706 automatic colorization."""
710 automatic colorization."""
707 if len(args) != 2:
711 if len(args) != 2:
708 # i18n: "label" is a keyword
712 # i18n: "label" is a keyword
709 raise error.ParseError(_("label expects two arguments"))
713 raise error.ParseError(_("label expects two arguments"))
710
714
711 ui = mapping['ui']
715 ui = mapping['ui']
712 thing = evalstring(context, mapping, args[1])
716 thing = evalstring(context, mapping, args[1])
713 # preserve unknown symbol as literal so effects like 'red', 'bold',
717 # preserve unknown symbol as literal so effects like 'red', 'bold',
714 # etc. don't need to be quoted
718 # etc. don't need to be quoted
715 label = evalstringliteral(context, mapping, args[0])
719 label = evalstringliteral(context, mapping, args[0])
716
720
717 return ui.label(thing, label)
721 return ui.label(thing, label)
718
722
719 @templatefunc('latesttag([pattern])')
723 @templatefunc('latesttag([pattern])')
720 def latesttag(context, mapping, args):
724 def latesttag(context, mapping, args):
721 """The global tags matching the given pattern on the
725 """The global tags matching the given pattern on the
722 most recent globally tagged ancestor of this changeset.
726 most recent globally tagged ancestor of this changeset.
723 If no such tags exist, the "{tag}" template resolves to
727 If no such tags exist, the "{tag}" template resolves to
724 the string "null"."""
728 the string "null"."""
725 if len(args) > 1:
729 if len(args) > 1:
726 # i18n: "latesttag" is a keyword
730 # i18n: "latesttag" is a keyword
727 raise error.ParseError(_("latesttag expects at most one argument"))
731 raise error.ParseError(_("latesttag expects at most one argument"))
728
732
729 pattern = None
733 pattern = None
730 if len(args) == 1:
734 if len(args) == 1:
731 pattern = evalstring(context, mapping, args[0])
735 pattern = evalstring(context, mapping, args[0])
732
736
733 return templatekw.showlatesttags(pattern, **mapping)
737 return templatekw.showlatesttags(pattern, **mapping)
734
738
735 @templatefunc('localdate(date[, tz])')
739 @templatefunc('localdate(date[, tz])')
736 def localdate(context, mapping, args):
740 def localdate(context, mapping, args):
737 """Converts a date to the specified timezone.
741 """Converts a date to the specified timezone.
738 The default is local date."""
742 The default is local date."""
739 if not (1 <= len(args) <= 2):
743 if not (1 <= len(args) <= 2):
740 # i18n: "localdate" is a keyword
744 # i18n: "localdate" is a keyword
741 raise error.ParseError(_("localdate expects one or two arguments"))
745 raise error.ParseError(_("localdate expects one or two arguments"))
742
746
743 date = evalfuncarg(context, mapping, args[0])
747 date = evalfuncarg(context, mapping, args[0])
744 try:
748 try:
745 date = util.parsedate(date)
749 date = util.parsedate(date)
746 except AttributeError: # not str nor date tuple
750 except AttributeError: # not str nor date tuple
747 # i18n: "localdate" is a keyword
751 # i18n: "localdate" is a keyword
748 raise error.ParseError(_("localdate expects a date information"))
752 raise error.ParseError(_("localdate expects a date information"))
749 if len(args) >= 2:
753 if len(args) >= 2:
750 tzoffset = None
754 tzoffset = None
751 tz = evalfuncarg(context, mapping, args[1])
755 tz = evalfuncarg(context, mapping, args[1])
752 if isinstance(tz, str):
756 if isinstance(tz, str):
753 tzoffset, remainder = util.parsetimezone(tz)
757 tzoffset, remainder = util.parsetimezone(tz)
754 if remainder:
758 if remainder:
755 tzoffset = None
759 tzoffset = None
756 if tzoffset is None:
760 if tzoffset is None:
757 try:
761 try:
758 tzoffset = int(tz)
762 tzoffset = int(tz)
759 except (TypeError, ValueError):
763 except (TypeError, ValueError):
760 # i18n: "localdate" is a keyword
764 # i18n: "localdate" is a keyword
761 raise error.ParseError(_("localdate expects a timezone"))
765 raise error.ParseError(_("localdate expects a timezone"))
762 else:
766 else:
763 tzoffset = util.makedate()[1]
767 tzoffset = util.makedate()[1]
764 return (date[0], tzoffset)
768 return (date[0], tzoffset)
765
769
766 @templatefunc('mod(a, b)')
770 @templatefunc('mod(a, b)')
767 def mod(context, mapping, args):
771 def mod(context, mapping, args):
768 """Calculate a mod b such that a / b + a mod b == a"""
772 """Calculate a mod b such that a / b + a mod b == a"""
769 if not len(args) == 2:
773 if not len(args) == 2:
770 # i18n: "mod" is a keyword
774 # i18n: "mod" is a keyword
771 raise error.ParseError(_("mod expects two arguments"))
775 raise error.ParseError(_("mod expects two arguments"))
772
776
773 func = lambda a, b: a % b
777 func = lambda a, b: a % b
774 return runarithmetic(context, mapping, (func, args[0], args[1]))
778 return runarithmetic(context, mapping, (func, args[0], args[1]))
775
779
776 @templatefunc('relpath(path)')
780 @templatefunc('relpath(path)')
777 def relpath(context, mapping, args):
781 def relpath(context, mapping, args):
778 """Convert a repository-absolute path into a filesystem path relative to
782 """Convert a repository-absolute path into a filesystem path relative to
779 the current working directory."""
783 the current working directory."""
780 if len(args) != 1:
784 if len(args) != 1:
781 # i18n: "relpath" is a keyword
785 # i18n: "relpath" is a keyword
782 raise error.ParseError(_("relpath expects one argument"))
786 raise error.ParseError(_("relpath expects one argument"))
783
787
784 repo = mapping['ctx'].repo()
788 repo = mapping['ctx'].repo()
785 path = evalstring(context, mapping, args[0])
789 path = evalstring(context, mapping, args[0])
786 return repo.pathto(path)
790 return repo.pathto(path)
787
791
788 @templatefunc('revset(query[, formatargs...])')
792 @templatefunc('revset(query[, formatargs...])')
789 def revset(context, mapping, args):
793 def revset(context, mapping, args):
790 """Execute a revision set query. See
794 """Execute a revision set query. See
791 :hg:`help revset`."""
795 :hg:`help revset`."""
792 if not len(args) > 0:
796 if not len(args) > 0:
793 # i18n: "revset" is a keyword
797 # i18n: "revset" is a keyword
794 raise error.ParseError(_("revset expects one or more arguments"))
798 raise error.ParseError(_("revset expects one or more arguments"))
795
799
796 raw = evalstring(context, mapping, args[0])
800 raw = evalstring(context, mapping, args[0])
797 ctx = mapping['ctx']
801 ctx = mapping['ctx']
798 repo = ctx.repo()
802 repo = ctx.repo()
799
803
800 def query(expr):
804 def query(expr):
801 m = revsetmod.match(repo.ui, expr)
805 m = revsetmod.match(repo.ui, expr)
802 return m(repo)
806 return m(repo)
803
807
804 if len(args) > 1:
808 if len(args) > 1:
805 formatargs = [evalfuncarg(context, mapping, a) for a in args[1:]]
809 formatargs = [evalfuncarg(context, mapping, a) for a in args[1:]]
806 revs = query(revsetlang.formatspec(raw, *formatargs))
810 revs = query(revsetlang.formatspec(raw, *formatargs))
807 revs = list(revs)
811 revs = list(revs)
808 else:
812 else:
809 revsetcache = mapping['cache'].setdefault("revsetcache", {})
813 revsetcache = mapping['cache'].setdefault("revsetcache", {})
810 if raw in revsetcache:
814 if raw in revsetcache:
811 revs = revsetcache[raw]
815 revs = revsetcache[raw]
812 else:
816 else:
813 revs = query(raw)
817 revs = query(raw)
814 revs = list(revs)
818 revs = list(revs)
815 revsetcache[raw] = revs
819 revsetcache[raw] = revs
816
820
817 return templatekw.showrevslist("revision", revs, **mapping)
821 return templatekw.showrevslist("revision", revs, **mapping)
818
822
819 @templatefunc('rstdoc(text, style)')
823 @templatefunc('rstdoc(text, style)')
820 def rstdoc(context, mapping, args):
824 def rstdoc(context, mapping, args):
821 """Format reStructuredText."""
825 """Format reStructuredText."""
822 if len(args) != 2:
826 if len(args) != 2:
823 # i18n: "rstdoc" is a keyword
827 # i18n: "rstdoc" is a keyword
824 raise error.ParseError(_("rstdoc expects two arguments"))
828 raise error.ParseError(_("rstdoc expects two arguments"))
825
829
826 text = evalstring(context, mapping, args[0])
830 text = evalstring(context, mapping, args[0])
827 style = evalstring(context, mapping, args[1])
831 style = evalstring(context, mapping, args[1])
828
832
829 return minirst.format(text, style=style, keep=['verbose'])
833 return minirst.format(text, style=style, keep=['verbose'])
830
834
831 @templatefunc('separate(sep, args)')
835 @templatefunc('separate(sep, args)')
832 def separate(context, mapping, args):
836 def separate(context, mapping, args):
833 """Add a separator between non-empty arguments."""
837 """Add a separator between non-empty arguments."""
834 if not args:
838 if not args:
835 # i18n: "separate" is a keyword
839 # i18n: "separate" is a keyword
836 raise error.ParseError(_("separate expects at least one argument"))
840 raise error.ParseError(_("separate expects at least one argument"))
837
841
838 sep = evalstring(context, mapping, args[0])
842 sep = evalstring(context, mapping, args[0])
839 first = True
843 first = True
840 for arg in args[1:]:
844 for arg in args[1:]:
841 argstr = evalstring(context, mapping, arg)
845 argstr = evalstring(context, mapping, arg)
842 if not argstr:
846 if not argstr:
843 continue
847 continue
844 if first:
848 if first:
845 first = False
849 first = False
846 else:
850 else:
847 yield sep
851 yield sep
848 yield argstr
852 yield argstr
849
853
850 @templatefunc('shortest(node, minlength=4)')
854 @templatefunc('shortest(node, minlength=4)')
851 def shortest(context, mapping, args):
855 def shortest(context, mapping, args):
852 """Obtain the shortest representation of
856 """Obtain the shortest representation of
853 a node."""
857 a node."""
854 if not (1 <= len(args) <= 2):
858 if not (1 <= len(args) <= 2):
855 # i18n: "shortest" is a keyword
859 # i18n: "shortest" is a keyword
856 raise error.ParseError(_("shortest() expects one or two arguments"))
860 raise error.ParseError(_("shortest() expects one or two arguments"))
857
861
858 node = evalstring(context, mapping, args[0])
862 node = evalstring(context, mapping, args[0])
859
863
860 minlength = 4
864 minlength = 4
861 if len(args) > 1:
865 if len(args) > 1:
862 minlength = evalinteger(context, mapping, args[1],
866 minlength = evalinteger(context, mapping, args[1],
863 # i18n: "shortest" is a keyword
867 # i18n: "shortest" is a keyword
864 _("shortest() expects an integer minlength"))
868 _("shortest() expects an integer minlength"))
865
869
866 # _partialmatch() of filtered changelog could take O(len(repo)) time,
870 # _partialmatch() of filtered changelog could take O(len(repo)) time,
867 # which would be unacceptably slow. so we look for hash collision in
871 # which would be unacceptably slow. so we look for hash collision in
868 # unfiltered space, which means some hashes may be slightly longer.
872 # unfiltered space, which means some hashes may be slightly longer.
869 cl = mapping['ctx']._repo.unfiltered().changelog
873 cl = mapping['ctx']._repo.unfiltered().changelog
870 def isvalid(test):
874 def isvalid(test):
871 try:
875 try:
872 if cl._partialmatch(test) is None:
876 if cl._partialmatch(test) is None:
873 return False
877 return False
874
878
875 try:
879 try:
876 i = int(test)
880 i = int(test)
877 # if we are a pure int, then starting with zero will not be
881 # if we are a pure int, then starting with zero will not be
878 # confused as a rev; or, obviously, if the int is larger than
882 # confused as a rev; or, obviously, if the int is larger than
879 # the value of the tip rev
883 # the value of the tip rev
880 if test[0] == '0' or i > len(cl):
884 if test[0] == '0' or i > len(cl):
881 return True
885 return True
882 return False
886 return False
883 except ValueError:
887 except ValueError:
884 return True
888 return True
885 except error.RevlogError:
889 except error.RevlogError:
886 return False
890 return False
887
891
888 shortest = node
892 shortest = node
889 startlength = max(6, minlength)
893 startlength = max(6, minlength)
890 length = startlength
894 length = startlength
891 while True:
895 while True:
892 test = node[:length]
896 test = node[:length]
893 if isvalid(test):
897 if isvalid(test):
894 shortest = test
898 shortest = test
895 if length == minlength or length > startlength:
899 if length == minlength or length > startlength:
896 return shortest
900 return shortest
897 length -= 1
901 length -= 1
898 else:
902 else:
899 length += 1
903 length += 1
900 if len(shortest) <= length:
904 if len(shortest) <= length:
901 return shortest
905 return shortest
902
906
903 @templatefunc('strip(text[, chars])')
907 @templatefunc('strip(text[, chars])')
904 def strip(context, mapping, args):
908 def strip(context, mapping, args):
905 """Strip characters from a string. By default,
909 """Strip characters from a string. By default,
906 strips all leading and trailing whitespace."""
910 strips all leading and trailing whitespace."""
907 if not (1 <= len(args) <= 2):
911 if not (1 <= len(args) <= 2):
908 # i18n: "strip" is a keyword
912 # i18n: "strip" is a keyword
909 raise error.ParseError(_("strip expects one or two arguments"))
913 raise error.ParseError(_("strip expects one or two arguments"))
910
914
911 text = evalstring(context, mapping, args[0])
915 text = evalstring(context, mapping, args[0])
912 if len(args) == 2:
916 if len(args) == 2:
913 chars = evalstring(context, mapping, args[1])
917 chars = evalstring(context, mapping, args[1])
914 return text.strip(chars)
918 return text.strip(chars)
915 return text.strip()
919 return text.strip()
916
920
917 @templatefunc('sub(pattern, replacement, expression)')
921 @templatefunc('sub(pattern, replacement, expression)')
918 def sub(context, mapping, args):
922 def sub(context, mapping, args):
919 """Perform text substitution
923 """Perform text substitution
920 using regular expressions."""
924 using regular expressions."""
921 if len(args) != 3:
925 if len(args) != 3:
922 # i18n: "sub" is a keyword
926 # i18n: "sub" is a keyword
923 raise error.ParseError(_("sub expects three arguments"))
927 raise error.ParseError(_("sub expects three arguments"))
924
928
925 pat = evalstring(context, mapping, args[0])
929 pat = evalstring(context, mapping, args[0])
926 rpl = evalstring(context, mapping, args[1])
930 rpl = evalstring(context, mapping, args[1])
927 src = evalstring(context, mapping, args[2])
931 src = evalstring(context, mapping, args[2])
928 try:
932 try:
929 patre = re.compile(pat)
933 patre = re.compile(pat)
930 except re.error:
934 except re.error:
931 # i18n: "sub" is a keyword
935 # i18n: "sub" is a keyword
932 raise error.ParseError(_("sub got an invalid pattern: %s") % pat)
936 raise error.ParseError(_("sub got an invalid pattern: %s") % pat)
933 try:
937 try:
934 yield patre.sub(rpl, src)
938 yield patre.sub(rpl, src)
935 except re.error:
939 except re.error:
936 # i18n: "sub" is a keyword
940 # i18n: "sub" is a keyword
937 raise error.ParseError(_("sub got an invalid replacement: %s") % rpl)
941 raise error.ParseError(_("sub got an invalid replacement: %s") % rpl)
938
942
939 @templatefunc('startswith(pattern, text)')
943 @templatefunc('startswith(pattern, text)')
940 def startswith(context, mapping, args):
944 def startswith(context, mapping, args):
941 """Returns the value from the "text" argument
945 """Returns the value from the "text" argument
942 if it begins with the content from the "pattern" argument."""
946 if it begins with the content from the "pattern" argument."""
943 if len(args) != 2:
947 if len(args) != 2:
944 # i18n: "startswith" is a keyword
948 # i18n: "startswith" is a keyword
945 raise error.ParseError(_("startswith expects two arguments"))
949 raise error.ParseError(_("startswith expects two arguments"))
946
950
947 patn = evalstring(context, mapping, args[0])
951 patn = evalstring(context, mapping, args[0])
948 text = evalstring(context, mapping, args[1])
952 text = evalstring(context, mapping, args[1])
949 if text.startswith(patn):
953 if text.startswith(patn):
950 return text
954 return text
951 return ''
955 return ''
952
956
953 @templatefunc('word(number, text[, separator])')
957 @templatefunc('word(number, text[, separator])')
954 def word(context, mapping, args):
958 def word(context, mapping, args):
955 """Return the nth word from a string."""
959 """Return the nth word from a string."""
956 if not (2 <= len(args) <= 3):
960 if not (2 <= len(args) <= 3):
957 # i18n: "word" is a keyword
961 # i18n: "word" is a keyword
958 raise error.ParseError(_("word expects two or three arguments, got %d")
962 raise error.ParseError(_("word expects two or three arguments, got %d")
959 % len(args))
963 % len(args))
960
964
961 num = evalinteger(context, mapping, args[0],
965 num = evalinteger(context, mapping, args[0],
962 # i18n: "word" is a keyword
966 # i18n: "word" is a keyword
963 _("word expects an integer index"))
967 _("word expects an integer index"))
964 text = evalstring(context, mapping, args[1])
968 text = evalstring(context, mapping, args[1])
965 if len(args) == 3:
969 if len(args) == 3:
966 splitter = evalstring(context, mapping, args[2])
970 splitter = evalstring(context, mapping, args[2])
967 else:
971 else:
968 splitter = None
972 splitter = None
969
973
970 tokens = text.split(splitter)
974 tokens = text.split(splitter)
971 if num >= len(tokens) or num < -len(tokens):
975 if num >= len(tokens) or num < -len(tokens):
972 return ''
976 return ''
973 else:
977 else:
974 return tokens[num]
978 return tokens[num]
975
979
976 # methods to interpret function arguments or inner expressions (e.g. {_(x)})
980 # methods to interpret function arguments or inner expressions (e.g. {_(x)})
977 exprmethods = {
981 exprmethods = {
978 "integer": lambda e, c: (runinteger, e[1]),
982 "integer": lambda e, c: (runinteger, e[1]),
979 "string": lambda e, c: (runstring, e[1]),
983 "string": lambda e, c: (runstring, e[1]),
980 "symbol": lambda e, c: (runsymbol, e[1]),
984 "symbol": lambda e, c: (runsymbol, e[1]),
981 "template": buildtemplate,
985 "template": buildtemplate,
982 "group": lambda e, c: compileexp(e[1], c, exprmethods),
986 "group": lambda e, c: compileexp(e[1], c, exprmethods),
983 # ".": buildmember,
987 # ".": buildmember,
984 "|": buildfilter,
988 "|": buildfilter,
985 "%": buildmap,
989 "%": buildmap,
986 "func": buildfunc,
990 "func": buildfunc,
991 "keyvalue": buildkeyvaluepair,
987 "+": lambda e, c: buildarithmetic(e, c, lambda a, b: a + b),
992 "+": lambda e, c: buildarithmetic(e, c, lambda a, b: a + b),
988 "-": lambda e, c: buildarithmetic(e, c, lambda a, b: a - b),
993 "-": lambda e, c: buildarithmetic(e, c, lambda a, b: a - b),
989 "negate": buildnegate,
994 "negate": buildnegate,
990 "*": lambda e, c: buildarithmetic(e, c, lambda a, b: a * b),
995 "*": lambda e, c: buildarithmetic(e, c, lambda a, b: a * b),
991 "/": lambda e, c: buildarithmetic(e, c, lambda a, b: a // b),
996 "/": lambda e, c: buildarithmetic(e, c, lambda a, b: a // b),
992 }
997 }
993
998
994 # methods to interpret top-level template (e.g. {x}, {x|_}, {x % "y"})
999 # methods to interpret top-level template (e.g. {x}, {x|_}, {x % "y"})
995 methods = exprmethods.copy()
1000 methods = exprmethods.copy()
996 methods["integer"] = exprmethods["symbol"] # '{1}' as variable
1001 methods["integer"] = exprmethods["symbol"] # '{1}' as variable
997
1002
998 class _aliasrules(parser.basealiasrules):
1003 class _aliasrules(parser.basealiasrules):
999 """Parsing and expansion rule set of template aliases"""
1004 """Parsing and expansion rule set of template aliases"""
1000 _section = _('template alias')
1005 _section = _('template alias')
1001 _parse = staticmethod(_parseexpr)
1006 _parse = staticmethod(_parseexpr)
1002
1007
1003 @staticmethod
1008 @staticmethod
1004 def _trygetfunc(tree):
1009 def _trygetfunc(tree):
1005 """Return (name, args) if tree is func(...) or ...|filter; otherwise
1010 """Return (name, args) if tree is func(...) or ...|filter; otherwise
1006 None"""
1011 None"""
1007 if tree[0] == 'func' and tree[1][0] == 'symbol':
1012 if tree[0] == 'func' and tree[1][0] == 'symbol':
1008 return tree[1][1], getlist(tree[2])
1013 return tree[1][1], getlist(tree[2])
1009 if tree[0] == '|' and tree[2][0] == 'symbol':
1014 if tree[0] == '|' and tree[2][0] == 'symbol':
1010 return tree[2][1], [tree[1]]
1015 return tree[2][1], [tree[1]]
1011
1016
1012 def expandaliases(tree, aliases):
1017 def expandaliases(tree, aliases):
1013 """Return new tree of aliases are expanded"""
1018 """Return new tree of aliases are expanded"""
1014 aliasmap = _aliasrules.buildmap(aliases)
1019 aliasmap = _aliasrules.buildmap(aliases)
1015 return _aliasrules.expand(aliasmap, tree)
1020 return _aliasrules.expand(aliasmap, tree)
1016
1021
1017 # template engine
1022 # template engine
1018
1023
1019 stringify = templatefilters.stringify
1024 stringify = templatefilters.stringify
1020
1025
1021 def _flatten(thing):
1026 def _flatten(thing):
1022 '''yield a single stream from a possibly nested set of iterators'''
1027 '''yield a single stream from a possibly nested set of iterators'''
1023 thing = templatekw.unwraphybrid(thing)
1028 thing = templatekw.unwraphybrid(thing)
1024 if isinstance(thing, str):
1029 if isinstance(thing, str):
1025 yield thing
1030 yield thing
1026 elif thing is None:
1031 elif thing is None:
1027 pass
1032 pass
1028 elif not util.safehasattr(thing, '__iter__'):
1033 elif not util.safehasattr(thing, '__iter__'):
1029 yield str(thing)
1034 yield str(thing)
1030 else:
1035 else:
1031 for i in thing:
1036 for i in thing:
1032 i = templatekw.unwraphybrid(i)
1037 i = templatekw.unwraphybrid(i)
1033 if isinstance(i, str):
1038 if isinstance(i, str):
1034 yield i
1039 yield i
1035 elif i is None:
1040 elif i is None:
1036 pass
1041 pass
1037 elif not util.safehasattr(i, '__iter__'):
1042 elif not util.safehasattr(i, '__iter__'):
1038 yield str(i)
1043 yield str(i)
1039 else:
1044 else:
1040 for j in _flatten(i):
1045 for j in _flatten(i):
1041 yield j
1046 yield j
1042
1047
1043 def unquotestring(s):
1048 def unquotestring(s):
1044 '''unwrap quotes if any; otherwise returns unmodified string'''
1049 '''unwrap quotes if any; otherwise returns unmodified string'''
1045 if len(s) < 2 or s[0] not in "'\"" or s[0] != s[-1]:
1050 if len(s) < 2 or s[0] not in "'\"" or s[0] != s[-1]:
1046 return s
1051 return s
1047 return s[1:-1]
1052 return s[1:-1]
1048
1053
1049 class engine(object):
1054 class engine(object):
1050 '''template expansion engine.
1055 '''template expansion engine.
1051
1056
1052 template expansion works like this. a map file contains key=value
1057 template expansion works like this. a map file contains key=value
1053 pairs. if value is quoted, it is treated as string. otherwise, it
1058 pairs. if value is quoted, it is treated as string. otherwise, it
1054 is treated as name of template file.
1059 is treated as name of template file.
1055
1060
1056 templater is asked to expand a key in map. it looks up key, and
1061 templater is asked to expand a key in map. it looks up key, and
1057 looks for strings like this: {foo}. it expands {foo} by looking up
1062 looks for strings like this: {foo}. it expands {foo} by looking up
1058 foo in map, and substituting it. expansion is recursive: it stops
1063 foo in map, and substituting it. expansion is recursive: it stops
1059 when there is no more {foo} to replace.
1064 when there is no more {foo} to replace.
1060
1065
1061 expansion also allows formatting and filtering.
1066 expansion also allows formatting and filtering.
1062
1067
1063 format uses key to expand each item in list. syntax is
1068 format uses key to expand each item in list. syntax is
1064 {key%format}.
1069 {key%format}.
1065
1070
1066 filter uses function to transform value. syntax is
1071 filter uses function to transform value. syntax is
1067 {key|filter1|filter2|...}.'''
1072 {key|filter1|filter2|...}.'''
1068
1073
1069 def __init__(self, loader, filters=None, defaults=None, aliases=()):
1074 def __init__(self, loader, filters=None, defaults=None, aliases=()):
1070 self._loader = loader
1075 self._loader = loader
1071 if filters is None:
1076 if filters is None:
1072 filters = {}
1077 filters = {}
1073 self._filters = filters
1078 self._filters = filters
1074 if defaults is None:
1079 if defaults is None:
1075 defaults = {}
1080 defaults = {}
1076 self._defaults = defaults
1081 self._defaults = defaults
1077 self._aliasmap = _aliasrules.buildmap(aliases)
1082 self._aliasmap = _aliasrules.buildmap(aliases)
1078 self._cache = {} # key: (func, data)
1083 self._cache = {} # key: (func, data)
1079
1084
1080 def _load(self, t):
1085 def _load(self, t):
1081 '''load, parse, and cache a template'''
1086 '''load, parse, and cache a template'''
1082 if t not in self._cache:
1087 if t not in self._cache:
1083 # put poison to cut recursion while compiling 't'
1088 # put poison to cut recursion while compiling 't'
1084 self._cache[t] = (_runrecursivesymbol, t)
1089 self._cache[t] = (_runrecursivesymbol, t)
1085 try:
1090 try:
1086 x = parse(self._loader(t))
1091 x = parse(self._loader(t))
1087 if self._aliasmap:
1092 if self._aliasmap:
1088 x = _aliasrules.expand(self._aliasmap, x)
1093 x = _aliasrules.expand(self._aliasmap, x)
1089 self._cache[t] = compileexp(x, self, methods)
1094 self._cache[t] = compileexp(x, self, methods)
1090 except: # re-raises
1095 except: # re-raises
1091 del self._cache[t]
1096 del self._cache[t]
1092 raise
1097 raise
1093 return self._cache[t]
1098 return self._cache[t]
1094
1099
1095 def process(self, t, mapping):
1100 def process(self, t, mapping):
1096 '''Perform expansion. t is name of map element to expand.
1101 '''Perform expansion. t is name of map element to expand.
1097 mapping contains added elements for use during expansion. Is a
1102 mapping contains added elements for use during expansion. Is a
1098 generator.'''
1103 generator.'''
1099 func, data = self._load(t)
1104 func, data = self._load(t)
1100 return _flatten(func(self, mapping, data))
1105 return _flatten(func(self, mapping, data))
1101
1106
1102 engines = {'default': engine}
1107 engines = {'default': engine}
1103
1108
1104 def stylelist():
1109 def stylelist():
1105 paths = templatepaths()
1110 paths = templatepaths()
1106 if not paths:
1111 if not paths:
1107 return _('no templates found, try `hg debuginstall` for more info')
1112 return _('no templates found, try `hg debuginstall` for more info')
1108 dirlist = os.listdir(paths[0])
1113 dirlist = os.listdir(paths[0])
1109 stylelist = []
1114 stylelist = []
1110 for file in dirlist:
1115 for file in dirlist:
1111 split = file.split(".")
1116 split = file.split(".")
1112 if split[-1] in ('orig', 'rej'):
1117 if split[-1] in ('orig', 'rej'):
1113 continue
1118 continue
1114 if split[0] == "map-cmdline":
1119 if split[0] == "map-cmdline":
1115 stylelist.append(split[1])
1120 stylelist.append(split[1])
1116 return ", ".join(sorted(stylelist))
1121 return ", ".join(sorted(stylelist))
1117
1122
1118 def _readmapfile(mapfile):
1123 def _readmapfile(mapfile):
1119 """Load template elements from the given map file"""
1124 """Load template elements from the given map file"""
1120 if not os.path.exists(mapfile):
1125 if not os.path.exists(mapfile):
1121 raise error.Abort(_("style '%s' not found") % mapfile,
1126 raise error.Abort(_("style '%s' not found") % mapfile,
1122 hint=_("available styles: %s") % stylelist())
1127 hint=_("available styles: %s") % stylelist())
1123
1128
1124 base = os.path.dirname(mapfile)
1129 base = os.path.dirname(mapfile)
1125 conf = config.config(includepaths=templatepaths())
1130 conf = config.config(includepaths=templatepaths())
1126 conf.read(mapfile)
1131 conf.read(mapfile)
1127
1132
1128 cache = {}
1133 cache = {}
1129 tmap = {}
1134 tmap = {}
1130 for key, val in conf[''].items():
1135 for key, val in conf[''].items():
1131 if not val:
1136 if not val:
1132 raise error.ParseError(_('missing value'), conf.source('', key))
1137 raise error.ParseError(_('missing value'), conf.source('', key))
1133 if val[0] in "'\"":
1138 if val[0] in "'\"":
1134 if val[0] != val[-1]:
1139 if val[0] != val[-1]:
1135 raise error.ParseError(_('unmatched quotes'),
1140 raise error.ParseError(_('unmatched quotes'),
1136 conf.source('', key))
1141 conf.source('', key))
1137 cache[key] = unquotestring(val)
1142 cache[key] = unquotestring(val)
1138 elif key == "__base__":
1143 elif key == "__base__":
1139 # treat as a pointer to a base class for this style
1144 # treat as a pointer to a base class for this style
1140 path = util.normpath(os.path.join(base, val))
1145 path = util.normpath(os.path.join(base, val))
1141
1146
1142 # fallback check in template paths
1147 # fallback check in template paths
1143 if not os.path.exists(path):
1148 if not os.path.exists(path):
1144 for p in templatepaths():
1149 for p in templatepaths():
1145 p2 = util.normpath(os.path.join(p, val))
1150 p2 = util.normpath(os.path.join(p, val))
1146 if os.path.isfile(p2):
1151 if os.path.isfile(p2):
1147 path = p2
1152 path = p2
1148 break
1153 break
1149 p3 = util.normpath(os.path.join(p2, "map"))
1154 p3 = util.normpath(os.path.join(p2, "map"))
1150 if os.path.isfile(p3):
1155 if os.path.isfile(p3):
1151 path = p3
1156 path = p3
1152 break
1157 break
1153
1158
1154 bcache, btmap = _readmapfile(path)
1159 bcache, btmap = _readmapfile(path)
1155 for k in bcache:
1160 for k in bcache:
1156 if k not in cache:
1161 if k not in cache:
1157 cache[k] = bcache[k]
1162 cache[k] = bcache[k]
1158 for k in btmap:
1163 for k in btmap:
1159 if k not in tmap:
1164 if k not in tmap:
1160 tmap[k] = btmap[k]
1165 tmap[k] = btmap[k]
1161 else:
1166 else:
1162 val = 'default', val
1167 val = 'default', val
1163 if ':' in val[1]:
1168 if ':' in val[1]:
1164 val = val[1].split(':', 1)
1169 val = val[1].split(':', 1)
1165 tmap[key] = val[0], os.path.join(base, val[1])
1170 tmap[key] = val[0], os.path.join(base, val[1])
1166 return cache, tmap
1171 return cache, tmap
1167
1172
1168 class TemplateNotFound(error.Abort):
1173 class TemplateNotFound(error.Abort):
1169 pass
1174 pass
1170
1175
1171 class templater(object):
1176 class templater(object):
1172
1177
1173 def __init__(self, filters=None, defaults=None, cache=None, aliases=(),
1178 def __init__(self, filters=None, defaults=None, cache=None, aliases=(),
1174 minchunk=1024, maxchunk=65536):
1179 minchunk=1024, maxchunk=65536):
1175 '''set up template engine.
1180 '''set up template engine.
1176 filters is dict of functions. each transforms a value into another.
1181 filters is dict of functions. each transforms a value into another.
1177 defaults is dict of default map definitions.
1182 defaults is dict of default map definitions.
1178 aliases is list of alias (name, replacement) pairs.
1183 aliases is list of alias (name, replacement) pairs.
1179 '''
1184 '''
1180 if filters is None:
1185 if filters is None:
1181 filters = {}
1186 filters = {}
1182 if defaults is None:
1187 if defaults is None:
1183 defaults = {}
1188 defaults = {}
1184 if cache is None:
1189 if cache is None:
1185 cache = {}
1190 cache = {}
1186 self.cache = cache.copy()
1191 self.cache = cache.copy()
1187 self.map = {}
1192 self.map = {}
1188 self.filters = templatefilters.filters.copy()
1193 self.filters = templatefilters.filters.copy()
1189 self.filters.update(filters)
1194 self.filters.update(filters)
1190 self.defaults = defaults
1195 self.defaults = defaults
1191 self._aliases = aliases
1196 self._aliases = aliases
1192 self.minchunk, self.maxchunk = minchunk, maxchunk
1197 self.minchunk, self.maxchunk = minchunk, maxchunk
1193 self.ecache = {}
1198 self.ecache = {}
1194
1199
1195 @classmethod
1200 @classmethod
1196 def frommapfile(cls, mapfile, filters=None, defaults=None, cache=None,
1201 def frommapfile(cls, mapfile, filters=None, defaults=None, cache=None,
1197 minchunk=1024, maxchunk=65536):
1202 minchunk=1024, maxchunk=65536):
1198 """Create templater from the specified map file"""
1203 """Create templater from the specified map file"""
1199 t = cls(filters, defaults, cache, [], minchunk, maxchunk)
1204 t = cls(filters, defaults, cache, [], minchunk, maxchunk)
1200 cache, tmap = _readmapfile(mapfile)
1205 cache, tmap = _readmapfile(mapfile)
1201 t.cache.update(cache)
1206 t.cache.update(cache)
1202 t.map = tmap
1207 t.map = tmap
1203 return t
1208 return t
1204
1209
1205 def __contains__(self, key):
1210 def __contains__(self, key):
1206 return key in self.cache or key in self.map
1211 return key in self.cache or key in self.map
1207
1212
1208 def load(self, t):
1213 def load(self, t):
1209 '''Get the template for the given template name. Use a local cache.'''
1214 '''Get the template for the given template name. Use a local cache.'''
1210 if t not in self.cache:
1215 if t not in self.cache:
1211 try:
1216 try:
1212 self.cache[t] = util.readfile(self.map[t][1])
1217 self.cache[t] = util.readfile(self.map[t][1])
1213 except KeyError as inst:
1218 except KeyError as inst:
1214 raise TemplateNotFound(_('"%s" not in template map') %
1219 raise TemplateNotFound(_('"%s" not in template map') %
1215 inst.args[0])
1220 inst.args[0])
1216 except IOError as inst:
1221 except IOError as inst:
1217 raise IOError(inst.args[0], _('template file %s: %s') %
1222 raise IOError(inst.args[0], _('template file %s: %s') %
1218 (self.map[t][1], inst.args[1]))
1223 (self.map[t][1], inst.args[1]))
1219 return self.cache[t]
1224 return self.cache[t]
1220
1225
1221 def __call__(self, t, **mapping):
1226 def __call__(self, t, **mapping):
1222 ttype = t in self.map and self.map[t][0] or 'default'
1227 ttype = t in self.map and self.map[t][0] or 'default'
1223 if ttype not in self.ecache:
1228 if ttype not in self.ecache:
1224 try:
1229 try:
1225 ecls = engines[ttype]
1230 ecls = engines[ttype]
1226 except KeyError:
1231 except KeyError:
1227 raise error.Abort(_('invalid template engine: %s') % ttype)
1232 raise error.Abort(_('invalid template engine: %s') % ttype)
1228 self.ecache[ttype] = ecls(self.load, self.filters, self.defaults,
1233 self.ecache[ttype] = ecls(self.load, self.filters, self.defaults,
1229 self._aliases)
1234 self._aliases)
1230 proc = self.ecache[ttype]
1235 proc = self.ecache[ttype]
1231
1236
1232 stream = proc.process(t, mapping)
1237 stream = proc.process(t, mapping)
1233 if self.minchunk:
1238 if self.minchunk:
1234 stream = util.increasingchunks(stream, min=self.minchunk,
1239 stream = util.increasingchunks(stream, min=self.minchunk,
1235 max=self.maxchunk)
1240 max=self.maxchunk)
1236 return stream
1241 return stream
1237
1242
1238 def templatepaths():
1243 def templatepaths():
1239 '''return locations used for template files.'''
1244 '''return locations used for template files.'''
1240 pathsrel = ['templates']
1245 pathsrel = ['templates']
1241 paths = [os.path.normpath(os.path.join(util.datapath, f))
1246 paths = [os.path.normpath(os.path.join(util.datapath, f))
1242 for f in pathsrel]
1247 for f in pathsrel]
1243 return [p for p in paths if os.path.isdir(p)]
1248 return [p for p in paths if os.path.isdir(p)]
1244
1249
1245 def templatepath(name):
1250 def templatepath(name):
1246 '''return location of template file. returns None if not found.'''
1251 '''return location of template file. returns None if not found.'''
1247 for p in templatepaths():
1252 for p in templatepaths():
1248 f = os.path.join(p, name)
1253 f = os.path.join(p, name)
1249 if os.path.exists(f):
1254 if os.path.exists(f):
1250 return f
1255 return f
1251 return None
1256 return None
1252
1257
1253 def stylemap(styles, paths=None):
1258 def stylemap(styles, paths=None):
1254 """Return path to mapfile for a given style.
1259 """Return path to mapfile for a given style.
1255
1260
1256 Searches mapfile in the following locations:
1261 Searches mapfile in the following locations:
1257 1. templatepath/style/map
1262 1. templatepath/style/map
1258 2. templatepath/map-style
1263 2. templatepath/map-style
1259 3. templatepath/map
1264 3. templatepath/map
1260 """
1265 """
1261
1266
1262 if paths is None:
1267 if paths is None:
1263 paths = templatepaths()
1268 paths = templatepaths()
1264 elif isinstance(paths, str):
1269 elif isinstance(paths, str):
1265 paths = [paths]
1270 paths = [paths]
1266
1271
1267 if isinstance(styles, str):
1272 if isinstance(styles, str):
1268 styles = [styles]
1273 styles = [styles]
1269
1274
1270 for style in styles:
1275 for style in styles:
1271 # only plain name is allowed to honor template paths
1276 # only plain name is allowed to honor template paths
1272 if (not style
1277 if (not style
1273 or style in (os.curdir, os.pardir)
1278 or style in (os.curdir, os.pardir)
1274 or pycompat.ossep in style
1279 or pycompat.ossep in style
1275 or pycompat.osaltsep and pycompat.osaltsep in style):
1280 or pycompat.osaltsep and pycompat.osaltsep in style):
1276 continue
1281 continue
1277 locations = [os.path.join(style, 'map'), 'map-' + style]
1282 locations = [os.path.join(style, 'map'), 'map-' + style]
1278 locations.append('map')
1283 locations.append('map')
1279
1284
1280 for path in paths:
1285 for path in paths:
1281 for location in locations:
1286 for location in locations:
1282 mapfile = os.path.join(path, location)
1287 mapfile = os.path.join(path, location)
1283 if os.path.isfile(mapfile):
1288 if os.path.isfile(mapfile):
1284 return style, mapfile
1289 return style, mapfile
1285
1290
1286 raise RuntimeError("No hgweb templates found in %r" % paths)
1291 raise RuntimeError("No hgweb templates found in %r" % paths)
1287
1292
1288 def loadfunction(ui, extname, registrarobj):
1293 def loadfunction(ui, extname, registrarobj):
1289 """Load template function from specified registrarobj
1294 """Load template function from specified registrarobj
1290 """
1295 """
1291 for name, func in registrarobj._table.iteritems():
1296 for name, func in registrarobj._table.iteritems():
1292 funcs[name] = func
1297 funcs[name] = func
1293
1298
1294 # tell hggettext to extract docstrings from these functions:
1299 # tell hggettext to extract docstrings from these functions:
1295 i18nfunctions = funcs.values()
1300 i18nfunctions = funcs.values()
@@ -1,4169 +1,4181 b''
1 $ hg init a
1 $ hg init a
2 $ cd a
2 $ cd a
3 $ echo a > a
3 $ echo a > a
4 $ hg add a
4 $ hg add a
5 $ echo line 1 > b
5 $ echo line 1 > b
6 $ echo line 2 >> b
6 $ echo line 2 >> b
7 $ hg commit -l b -d '1000000 0' -u 'User Name <user@hostname>'
7 $ hg commit -l b -d '1000000 0' -u 'User Name <user@hostname>'
8
8
9 $ hg add b
9 $ hg add b
10 $ echo other 1 > c
10 $ echo other 1 > c
11 $ echo other 2 >> c
11 $ echo other 2 >> c
12 $ echo >> c
12 $ echo >> c
13 $ echo other 3 >> c
13 $ echo other 3 >> c
14 $ hg commit -l c -d '1100000 0' -u 'A. N. Other <other@place>'
14 $ hg commit -l c -d '1100000 0' -u 'A. N. Other <other@place>'
15
15
16 $ hg add c
16 $ hg add c
17 $ hg commit -m 'no person' -d '1200000 0' -u 'other@place'
17 $ hg commit -m 'no person' -d '1200000 0' -u 'other@place'
18 $ echo c >> c
18 $ echo c >> c
19 $ hg commit -m 'no user, no domain' -d '1300000 0' -u 'person'
19 $ hg commit -m 'no user, no domain' -d '1300000 0' -u 'person'
20
20
21 $ echo foo > .hg/branch
21 $ echo foo > .hg/branch
22 $ hg commit -m 'new branch' -d '1400000 0' -u 'person'
22 $ hg commit -m 'new branch' -d '1400000 0' -u 'person'
23
23
24 $ hg co -q 3
24 $ hg co -q 3
25 $ echo other 4 >> d
25 $ echo other 4 >> d
26 $ hg add d
26 $ hg add d
27 $ hg commit -m 'new head' -d '1500000 0' -u 'person'
27 $ hg commit -m 'new head' -d '1500000 0' -u 'person'
28
28
29 $ hg merge -q foo
29 $ hg merge -q foo
30 $ hg commit -m 'merge' -d '1500001 0' -u 'person'
30 $ hg commit -m 'merge' -d '1500001 0' -u 'person'
31
31
32 Test arithmetic operators have the right precedence:
32 Test arithmetic operators have the right precedence:
33
33
34 $ hg log -l 1 -T '{date(date, "%Y") + 5 * 10} {date(date, "%Y") - 2 * 3}\n'
34 $ hg log -l 1 -T '{date(date, "%Y") + 5 * 10} {date(date, "%Y") - 2 * 3}\n'
35 2020 1964
35 2020 1964
36 $ hg log -l 1 -T '{date(date, "%Y") * 5 + 10} {date(date, "%Y") * 3 - 2}\n'
36 $ hg log -l 1 -T '{date(date, "%Y") * 5 + 10} {date(date, "%Y") * 3 - 2}\n'
37 9860 5908
37 9860 5908
38
38
39 Test division:
39 Test division:
40
40
41 $ hg debugtemplate -r0 -v '{5 / 2} {mod(5, 2)}\n'
41 $ hg debugtemplate -r0 -v '{5 / 2} {mod(5, 2)}\n'
42 (template
42 (template
43 (/
43 (/
44 ('integer', '5')
44 ('integer', '5')
45 ('integer', '2'))
45 ('integer', '2'))
46 ('string', ' ')
46 ('string', ' ')
47 (func
47 (func
48 ('symbol', 'mod')
48 ('symbol', 'mod')
49 (list
49 (list
50 ('integer', '5')
50 ('integer', '5')
51 ('integer', '2')))
51 ('integer', '2')))
52 ('string', '\n'))
52 ('string', '\n'))
53 2 1
53 2 1
54 $ hg debugtemplate -r0 -v '{5 / -2} {mod(5, -2)}\n'
54 $ hg debugtemplate -r0 -v '{5 / -2} {mod(5, -2)}\n'
55 (template
55 (template
56 (/
56 (/
57 ('integer', '5')
57 ('integer', '5')
58 (negate
58 (negate
59 ('integer', '2')))
59 ('integer', '2')))
60 ('string', ' ')
60 ('string', ' ')
61 (func
61 (func
62 ('symbol', 'mod')
62 ('symbol', 'mod')
63 (list
63 (list
64 ('integer', '5')
64 ('integer', '5')
65 (negate
65 (negate
66 ('integer', '2'))))
66 ('integer', '2'))))
67 ('string', '\n'))
67 ('string', '\n'))
68 -3 -1
68 -3 -1
69 $ hg debugtemplate -r0 -v '{-5 / 2} {mod(-5, 2)}\n'
69 $ hg debugtemplate -r0 -v '{-5 / 2} {mod(-5, 2)}\n'
70 (template
70 (template
71 (/
71 (/
72 (negate
72 (negate
73 ('integer', '5'))
73 ('integer', '5'))
74 ('integer', '2'))
74 ('integer', '2'))
75 ('string', ' ')
75 ('string', ' ')
76 (func
76 (func
77 ('symbol', 'mod')
77 ('symbol', 'mod')
78 (list
78 (list
79 (negate
79 (negate
80 ('integer', '5'))
80 ('integer', '5'))
81 ('integer', '2')))
81 ('integer', '2')))
82 ('string', '\n'))
82 ('string', '\n'))
83 -3 1
83 -3 1
84 $ hg debugtemplate -r0 -v '{-5 / -2} {mod(-5, -2)}\n'
84 $ hg debugtemplate -r0 -v '{-5 / -2} {mod(-5, -2)}\n'
85 (template
85 (template
86 (/
86 (/
87 (negate
87 (negate
88 ('integer', '5'))
88 ('integer', '5'))
89 (negate
89 (negate
90 ('integer', '2')))
90 ('integer', '2')))
91 ('string', ' ')
91 ('string', ' ')
92 (func
92 (func
93 ('symbol', 'mod')
93 ('symbol', 'mod')
94 (list
94 (list
95 (negate
95 (negate
96 ('integer', '5'))
96 ('integer', '5'))
97 (negate
97 (negate
98 ('integer', '2'))))
98 ('integer', '2'))))
99 ('string', '\n'))
99 ('string', '\n'))
100 2 -1
100 2 -1
101
101
102 Filters bind closer than arithmetic:
102 Filters bind closer than arithmetic:
103
103
104 $ hg debugtemplate -r0 -v '{revset(".")|count - 1}\n'
104 $ hg debugtemplate -r0 -v '{revset(".")|count - 1}\n'
105 (template
105 (template
106 (-
106 (-
107 (|
107 (|
108 (func
108 (func
109 ('symbol', 'revset')
109 ('symbol', 'revset')
110 ('string', '.'))
110 ('string', '.'))
111 ('symbol', 'count'))
111 ('symbol', 'count'))
112 ('integer', '1'))
112 ('integer', '1'))
113 ('string', '\n'))
113 ('string', '\n'))
114 0
114 0
115
115
116 But negate binds closer still:
116 But negate binds closer still:
117
117
118 $ hg debugtemplate -r0 -v '{1-3|stringify}\n'
118 $ hg debugtemplate -r0 -v '{1-3|stringify}\n'
119 (template
119 (template
120 (-
120 (-
121 ('integer', '1')
121 ('integer', '1')
122 (|
122 (|
123 ('integer', '3')
123 ('integer', '3')
124 ('symbol', 'stringify')))
124 ('symbol', 'stringify')))
125 ('string', '\n'))
125 ('string', '\n'))
126 hg: parse error: arithmetic only defined on integers
126 hg: parse error: arithmetic only defined on integers
127 [255]
127 [255]
128 $ hg debugtemplate -r0 -v '{-3|stringify}\n'
128 $ hg debugtemplate -r0 -v '{-3|stringify}\n'
129 (template
129 (template
130 (|
130 (|
131 (negate
131 (negate
132 ('integer', '3'))
132 ('integer', '3'))
133 ('symbol', 'stringify'))
133 ('symbol', 'stringify'))
134 ('string', '\n'))
134 ('string', '\n'))
135 -3
135 -3
136
136
137 Keyword arguments:
138
139 $ hg debugtemplate -r0 -v '{foo=bar|baz}'
140 (template
141 (keyvalue
142 ('symbol', 'foo')
143 (|
144 ('symbol', 'bar')
145 ('symbol', 'baz'))))
146 hg: parse error: can't use a key-value pair in this context
147 [255]
148
137 Second branch starting at nullrev:
149 Second branch starting at nullrev:
138
150
139 $ hg update null
151 $ hg update null
140 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
152 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
141 $ echo second > second
153 $ echo second > second
142 $ hg add second
154 $ hg add second
143 $ hg commit -m second -d '1000000 0' -u 'User Name <user@hostname>'
155 $ hg commit -m second -d '1000000 0' -u 'User Name <user@hostname>'
144 created new head
156 created new head
145
157
146 $ echo third > third
158 $ echo third > third
147 $ hg add third
159 $ hg add third
148 $ hg mv second fourth
160 $ hg mv second fourth
149 $ hg commit -m third -d "2020-01-01 10:01"
161 $ hg commit -m third -d "2020-01-01 10:01"
150
162
151 $ hg log --template '{join(file_copies, ",\n")}\n' -r .
163 $ hg log --template '{join(file_copies, ",\n")}\n' -r .
152 fourth (second)
164 fourth (second)
153 $ hg log -T '{file_copies % "{source} -> {name}\n"}' -r .
165 $ hg log -T '{file_copies % "{source} -> {name}\n"}' -r .
154 second -> fourth
166 second -> fourth
155 $ hg log -T '{rev} {ifcontains("fourth", file_copies, "t", "f")}\n' -r .:7
167 $ hg log -T '{rev} {ifcontains("fourth", file_copies, "t", "f")}\n' -r .:7
156 8 t
168 8 t
157 7 f
169 7 f
158
170
159 Working-directory revision has special identifiers, though they are still
171 Working-directory revision has special identifiers, though they are still
160 experimental:
172 experimental:
161
173
162 $ hg log -r 'wdir()' -T '{rev}:{node}\n'
174 $ hg log -r 'wdir()' -T '{rev}:{node}\n'
163 2147483647:ffffffffffffffffffffffffffffffffffffffff
175 2147483647:ffffffffffffffffffffffffffffffffffffffff
164
176
165 Some keywords are invalid for working-directory revision, but they should
177 Some keywords are invalid for working-directory revision, but they should
166 never cause crash:
178 never cause crash:
167
179
168 $ hg log -r 'wdir()' -T '{manifest}\n'
180 $ hg log -r 'wdir()' -T '{manifest}\n'
169
181
170
182
171 Quoting for ui.logtemplate
183 Quoting for ui.logtemplate
172
184
173 $ hg tip --config "ui.logtemplate={rev}\n"
185 $ hg tip --config "ui.logtemplate={rev}\n"
174 8
186 8
175 $ hg tip --config "ui.logtemplate='{rev}\n'"
187 $ hg tip --config "ui.logtemplate='{rev}\n'"
176 8
188 8
177 $ hg tip --config 'ui.logtemplate="{rev}\n"'
189 $ hg tip --config 'ui.logtemplate="{rev}\n"'
178 8
190 8
179 $ hg tip --config 'ui.logtemplate=n{rev}\n'
191 $ hg tip --config 'ui.logtemplate=n{rev}\n'
180 n8
192 n8
181
193
182 Make sure user/global hgrc does not affect tests
194 Make sure user/global hgrc does not affect tests
183
195
184 $ echo '[ui]' > .hg/hgrc
196 $ echo '[ui]' > .hg/hgrc
185 $ echo 'logtemplate =' >> .hg/hgrc
197 $ echo 'logtemplate =' >> .hg/hgrc
186 $ echo 'style =' >> .hg/hgrc
198 $ echo 'style =' >> .hg/hgrc
187
199
188 Add some simple styles to settings
200 Add some simple styles to settings
189
201
190 $ echo '[templates]' >> .hg/hgrc
202 $ echo '[templates]' >> .hg/hgrc
191 $ printf 'simple = "{rev}\\n"\n' >> .hg/hgrc
203 $ printf 'simple = "{rev}\\n"\n' >> .hg/hgrc
192 $ printf 'simple2 = {rev}\\n\n' >> .hg/hgrc
204 $ printf 'simple2 = {rev}\\n\n' >> .hg/hgrc
193
205
194 $ hg log -l1 -Tsimple
206 $ hg log -l1 -Tsimple
195 8
207 8
196 $ hg log -l1 -Tsimple2
208 $ hg log -l1 -Tsimple2
197 8
209 8
198
210
199 Test templates and style maps in files:
211 Test templates and style maps in files:
200
212
201 $ echo "{rev}" > tmpl
213 $ echo "{rev}" > tmpl
202 $ hg log -l1 -T./tmpl
214 $ hg log -l1 -T./tmpl
203 8
215 8
204 $ hg log -l1 -Tblah/blah
216 $ hg log -l1 -Tblah/blah
205 blah/blah (no-eol)
217 blah/blah (no-eol)
206
218
207 $ printf 'changeset = "{rev}\\n"\n' > map-simple
219 $ printf 'changeset = "{rev}\\n"\n' > map-simple
208 $ hg log -l1 -T./map-simple
220 $ hg log -l1 -T./map-simple
209 8
221 8
210
222
211 Test template map inheritance
223 Test template map inheritance
212
224
213 $ echo "__base__ = map-cmdline.default" > map-simple
225 $ echo "__base__ = map-cmdline.default" > map-simple
214 $ printf 'cset = "changeset: ***{rev}***\\n"\n' >> map-simple
226 $ printf 'cset = "changeset: ***{rev}***\\n"\n' >> map-simple
215 $ hg log -l1 -T./map-simple
227 $ hg log -l1 -T./map-simple
216 changeset: ***8***
228 changeset: ***8***
217 tag: tip
229 tag: tip
218 user: test
230 user: test
219 date: Wed Jan 01 10:01:00 2020 +0000
231 date: Wed Jan 01 10:01:00 2020 +0000
220 summary: third
232 summary: third
221
233
222
234
223 Template should precede style option
235 Template should precede style option
224
236
225 $ hg log -l1 --style default -T '{rev}\n'
237 $ hg log -l1 --style default -T '{rev}\n'
226 8
238 8
227
239
228 Add a commit with empty description, to ensure that the templates
240 Add a commit with empty description, to ensure that the templates
229 below will omit the description line.
241 below will omit the description line.
230
242
231 $ echo c >> c
243 $ echo c >> c
232 $ hg add c
244 $ hg add c
233 $ hg commit -qm ' '
245 $ hg commit -qm ' '
234
246
235 Default style is like normal output. Phases style should be the same
247 Default style is like normal output. Phases style should be the same
236 as default style, except for extra phase lines.
248 as default style, except for extra phase lines.
237
249
238 $ hg log > log.out
250 $ hg log > log.out
239 $ hg log --style default > style.out
251 $ hg log --style default > style.out
240 $ cmp log.out style.out || diff -u log.out style.out
252 $ cmp log.out style.out || diff -u log.out style.out
241 $ hg log -T phases > phases.out
253 $ hg log -T phases > phases.out
242 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
254 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
243 +phase: draft
255 +phase: draft
244 +phase: draft
256 +phase: draft
245 +phase: draft
257 +phase: draft
246 +phase: draft
258 +phase: draft
247 +phase: draft
259 +phase: draft
248 +phase: draft
260 +phase: draft
249 +phase: draft
261 +phase: draft
250 +phase: draft
262 +phase: draft
251 +phase: draft
263 +phase: draft
252 +phase: draft
264 +phase: draft
253
265
254 $ hg log -v > log.out
266 $ hg log -v > log.out
255 $ hg log -v --style default > style.out
267 $ hg log -v --style default > style.out
256 $ cmp log.out style.out || diff -u log.out style.out
268 $ cmp log.out style.out || diff -u log.out style.out
257 $ hg log -v -T phases > phases.out
269 $ hg log -v -T phases > phases.out
258 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
270 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
259 +phase: draft
271 +phase: draft
260 +phase: draft
272 +phase: draft
261 +phase: draft
273 +phase: draft
262 +phase: draft
274 +phase: draft
263 +phase: draft
275 +phase: draft
264 +phase: draft
276 +phase: draft
265 +phase: draft
277 +phase: draft
266 +phase: draft
278 +phase: draft
267 +phase: draft
279 +phase: draft
268 +phase: draft
280 +phase: draft
269
281
270 $ hg log -q > log.out
282 $ hg log -q > log.out
271 $ hg log -q --style default > style.out
283 $ hg log -q --style default > style.out
272 $ cmp log.out style.out || diff -u log.out style.out
284 $ cmp log.out style.out || diff -u log.out style.out
273 $ hg log -q -T phases > phases.out
285 $ hg log -q -T phases > phases.out
274 $ cmp log.out phases.out || diff -u log.out phases.out
286 $ cmp log.out phases.out || diff -u log.out phases.out
275
287
276 $ hg log --debug > log.out
288 $ hg log --debug > log.out
277 $ hg log --debug --style default > style.out
289 $ hg log --debug --style default > style.out
278 $ cmp log.out style.out || diff -u log.out style.out
290 $ cmp log.out style.out || diff -u log.out style.out
279 $ hg log --debug -T phases > phases.out
291 $ hg log --debug -T phases > phases.out
280 $ cmp log.out phases.out || diff -u log.out phases.out
292 $ cmp log.out phases.out || diff -u log.out phases.out
281
293
282 Default style of working-directory revision should also be the same (but
294 Default style of working-directory revision should also be the same (but
283 date may change while running tests):
295 date may change while running tests):
284
296
285 $ hg log -r 'wdir()' | sed 's|^date:.*|date:|' > log.out
297 $ hg log -r 'wdir()' | sed 's|^date:.*|date:|' > log.out
286 $ hg log -r 'wdir()' --style default | sed 's|^date:.*|date:|' > style.out
298 $ hg log -r 'wdir()' --style default | sed 's|^date:.*|date:|' > style.out
287 $ cmp log.out style.out || diff -u log.out style.out
299 $ cmp log.out style.out || diff -u log.out style.out
288
300
289 $ hg log -r 'wdir()' -v | sed 's|^date:.*|date:|' > log.out
301 $ hg log -r 'wdir()' -v | sed 's|^date:.*|date:|' > log.out
290 $ hg log -r 'wdir()' -v --style default | sed 's|^date:.*|date:|' > style.out
302 $ hg log -r 'wdir()' -v --style default | sed 's|^date:.*|date:|' > style.out
291 $ cmp log.out style.out || diff -u log.out style.out
303 $ cmp log.out style.out || diff -u log.out style.out
292
304
293 $ hg log -r 'wdir()' -q > log.out
305 $ hg log -r 'wdir()' -q > log.out
294 $ hg log -r 'wdir()' -q --style default > style.out
306 $ hg log -r 'wdir()' -q --style default > style.out
295 $ cmp log.out style.out || diff -u log.out style.out
307 $ cmp log.out style.out || diff -u log.out style.out
296
308
297 $ hg log -r 'wdir()' --debug | sed 's|^date:.*|date:|' > log.out
309 $ hg log -r 'wdir()' --debug | sed 's|^date:.*|date:|' > log.out
298 $ hg log -r 'wdir()' --debug --style default \
310 $ hg log -r 'wdir()' --debug --style default \
299 > | sed 's|^date:.*|date:|' > style.out
311 > | sed 's|^date:.*|date:|' > style.out
300 $ cmp log.out style.out || diff -u log.out style.out
312 $ cmp log.out style.out || diff -u log.out style.out
301
313
302 Default style should also preserve color information (issue2866):
314 Default style should also preserve color information (issue2866):
303
315
304 $ cp $HGRCPATH $HGRCPATH-bak
316 $ cp $HGRCPATH $HGRCPATH-bak
305 $ cat <<EOF >> $HGRCPATH
317 $ cat <<EOF >> $HGRCPATH
306 > [extensions]
318 > [extensions]
307 > color=
319 > color=
308 > EOF
320 > EOF
309
321
310 $ hg --color=debug log > log.out
322 $ hg --color=debug log > log.out
311 $ hg --color=debug log --style default > style.out
323 $ hg --color=debug log --style default > style.out
312 $ cmp log.out style.out || diff -u log.out style.out
324 $ cmp log.out style.out || diff -u log.out style.out
313 $ hg --color=debug log -T phases > phases.out
325 $ hg --color=debug log -T phases > phases.out
314 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
326 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
315 +[log.phase|phase: draft]
327 +[log.phase|phase: draft]
316 +[log.phase|phase: draft]
328 +[log.phase|phase: draft]
317 +[log.phase|phase: draft]
329 +[log.phase|phase: draft]
318 +[log.phase|phase: draft]
330 +[log.phase|phase: draft]
319 +[log.phase|phase: draft]
331 +[log.phase|phase: draft]
320 +[log.phase|phase: draft]
332 +[log.phase|phase: draft]
321 +[log.phase|phase: draft]
333 +[log.phase|phase: draft]
322 +[log.phase|phase: draft]
334 +[log.phase|phase: draft]
323 +[log.phase|phase: draft]
335 +[log.phase|phase: draft]
324 +[log.phase|phase: draft]
336 +[log.phase|phase: draft]
325
337
326 $ hg --color=debug -v log > log.out
338 $ hg --color=debug -v log > log.out
327 $ hg --color=debug -v log --style default > style.out
339 $ hg --color=debug -v log --style default > style.out
328 $ cmp log.out style.out || diff -u log.out style.out
340 $ cmp log.out style.out || diff -u log.out style.out
329 $ hg --color=debug -v log -T phases > phases.out
341 $ hg --color=debug -v log -T phases > phases.out
330 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
342 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
331 +[log.phase|phase: draft]
343 +[log.phase|phase: draft]
332 +[log.phase|phase: draft]
344 +[log.phase|phase: draft]
333 +[log.phase|phase: draft]
345 +[log.phase|phase: draft]
334 +[log.phase|phase: draft]
346 +[log.phase|phase: draft]
335 +[log.phase|phase: draft]
347 +[log.phase|phase: draft]
336 +[log.phase|phase: draft]
348 +[log.phase|phase: draft]
337 +[log.phase|phase: draft]
349 +[log.phase|phase: draft]
338 +[log.phase|phase: draft]
350 +[log.phase|phase: draft]
339 +[log.phase|phase: draft]
351 +[log.phase|phase: draft]
340 +[log.phase|phase: draft]
352 +[log.phase|phase: draft]
341
353
342 $ hg --color=debug -q log > log.out
354 $ hg --color=debug -q log > log.out
343 $ hg --color=debug -q log --style default > style.out
355 $ hg --color=debug -q log --style default > style.out
344 $ cmp log.out style.out || diff -u log.out style.out
356 $ cmp log.out style.out || diff -u log.out style.out
345 $ hg --color=debug -q log -T phases > phases.out
357 $ hg --color=debug -q log -T phases > phases.out
346 $ cmp log.out phases.out || diff -u log.out phases.out
358 $ cmp log.out phases.out || diff -u log.out phases.out
347
359
348 $ hg --color=debug --debug log > log.out
360 $ hg --color=debug --debug log > log.out
349 $ hg --color=debug --debug log --style default > style.out
361 $ hg --color=debug --debug log --style default > style.out
350 $ cmp log.out style.out || diff -u log.out style.out
362 $ cmp log.out style.out || diff -u log.out style.out
351 $ hg --color=debug --debug log -T phases > phases.out
363 $ hg --color=debug --debug log -T phases > phases.out
352 $ cmp log.out phases.out || diff -u log.out phases.out
364 $ cmp log.out phases.out || diff -u log.out phases.out
353
365
354 $ mv $HGRCPATH-bak $HGRCPATH
366 $ mv $HGRCPATH-bak $HGRCPATH
355
367
356 Remove commit with empty commit message, so as to not pollute further
368 Remove commit with empty commit message, so as to not pollute further
357 tests.
369 tests.
358
370
359 $ hg --config extensions.strip= strip -q .
371 $ hg --config extensions.strip= strip -q .
360
372
361 Revision with no copies (used to print a traceback):
373 Revision with no copies (used to print a traceback):
362
374
363 $ hg tip -v --template '\n'
375 $ hg tip -v --template '\n'
364
376
365
377
366 Compact style works:
378 Compact style works:
367
379
368 $ hg log -Tcompact
380 $ hg log -Tcompact
369 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
381 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
370 third
382 third
371
383
372 7:-1 29114dbae42b 1970-01-12 13:46 +0000 user
384 7:-1 29114dbae42b 1970-01-12 13:46 +0000 user
373 second
385 second
374
386
375 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
387 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
376 merge
388 merge
377
389
378 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
390 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
379 new head
391 new head
380
392
381 4 bbe44766e73d 1970-01-17 04:53 +0000 person
393 4 bbe44766e73d 1970-01-17 04:53 +0000 person
382 new branch
394 new branch
383
395
384 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
396 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
385 no user, no domain
397 no user, no domain
386
398
387 2 97054abb4ab8 1970-01-14 21:20 +0000 other
399 2 97054abb4ab8 1970-01-14 21:20 +0000 other
388 no person
400 no person
389
401
390 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
402 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
391 other 1
403 other 1
392
404
393 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
405 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
394 line 1
406 line 1
395
407
396
408
397 $ hg log -v --style compact
409 $ hg log -v --style compact
398 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
410 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
399 third
411 third
400
412
401 7:-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
413 7:-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
402 second
414 second
403
415
404 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
416 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
405 merge
417 merge
406
418
407 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
419 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
408 new head
420 new head
409
421
410 4 bbe44766e73d 1970-01-17 04:53 +0000 person
422 4 bbe44766e73d 1970-01-17 04:53 +0000 person
411 new branch
423 new branch
412
424
413 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
425 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
414 no user, no domain
426 no user, no domain
415
427
416 2 97054abb4ab8 1970-01-14 21:20 +0000 other@place
428 2 97054abb4ab8 1970-01-14 21:20 +0000 other@place
417 no person
429 no person
418
430
419 1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
431 1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
420 other 1
432 other 1
421 other 2
433 other 2
422
434
423 other 3
435 other 3
424
436
425 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
437 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
426 line 1
438 line 1
427 line 2
439 line 2
428
440
429
441
430 $ hg log --debug --style compact
442 $ hg log --debug --style compact
431 8[tip]:7,-1 95c24699272e 2020-01-01 10:01 +0000 test
443 8[tip]:7,-1 95c24699272e 2020-01-01 10:01 +0000 test
432 third
444 third
433
445
434 7:-1,-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
446 7:-1,-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
435 second
447 second
436
448
437 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
449 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
438 merge
450 merge
439
451
440 5:3,-1 13207e5a10d9 1970-01-18 08:40 +0000 person
452 5:3,-1 13207e5a10d9 1970-01-18 08:40 +0000 person
441 new head
453 new head
442
454
443 4:3,-1 bbe44766e73d 1970-01-17 04:53 +0000 person
455 4:3,-1 bbe44766e73d 1970-01-17 04:53 +0000 person
444 new branch
456 new branch
445
457
446 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
458 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
447 no user, no domain
459 no user, no domain
448
460
449 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other@place
461 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other@place
450 no person
462 no person
451
463
452 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
464 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
453 other 1
465 other 1
454 other 2
466 other 2
455
467
456 other 3
468 other 3
457
469
458 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
470 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
459 line 1
471 line 1
460 line 2
472 line 2
461
473
462
474
463 Test xml styles:
475 Test xml styles:
464
476
465 $ hg log --style xml -r 'not all()'
477 $ hg log --style xml -r 'not all()'
466 <?xml version="1.0"?>
478 <?xml version="1.0"?>
467 <log>
479 <log>
468 </log>
480 </log>
469
481
470 $ hg log --style xml
482 $ hg log --style xml
471 <?xml version="1.0"?>
483 <?xml version="1.0"?>
472 <log>
484 <log>
473 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
485 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
474 <tag>tip</tag>
486 <tag>tip</tag>
475 <author email="test">test</author>
487 <author email="test">test</author>
476 <date>2020-01-01T10:01:00+00:00</date>
488 <date>2020-01-01T10:01:00+00:00</date>
477 <msg xml:space="preserve">third</msg>
489 <msg xml:space="preserve">third</msg>
478 </logentry>
490 </logentry>
479 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
491 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
480 <parent revision="-1" node="0000000000000000000000000000000000000000" />
492 <parent revision="-1" node="0000000000000000000000000000000000000000" />
481 <author email="user@hostname">User Name</author>
493 <author email="user@hostname">User Name</author>
482 <date>1970-01-12T13:46:40+00:00</date>
494 <date>1970-01-12T13:46:40+00:00</date>
483 <msg xml:space="preserve">second</msg>
495 <msg xml:space="preserve">second</msg>
484 </logentry>
496 </logentry>
485 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
497 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
486 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
498 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
487 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
499 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
488 <author email="person">person</author>
500 <author email="person">person</author>
489 <date>1970-01-18T08:40:01+00:00</date>
501 <date>1970-01-18T08:40:01+00:00</date>
490 <msg xml:space="preserve">merge</msg>
502 <msg xml:space="preserve">merge</msg>
491 </logentry>
503 </logentry>
492 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
504 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
493 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
505 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
494 <author email="person">person</author>
506 <author email="person">person</author>
495 <date>1970-01-18T08:40:00+00:00</date>
507 <date>1970-01-18T08:40:00+00:00</date>
496 <msg xml:space="preserve">new head</msg>
508 <msg xml:space="preserve">new head</msg>
497 </logentry>
509 </logentry>
498 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
510 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
499 <branch>foo</branch>
511 <branch>foo</branch>
500 <author email="person">person</author>
512 <author email="person">person</author>
501 <date>1970-01-17T04:53:20+00:00</date>
513 <date>1970-01-17T04:53:20+00:00</date>
502 <msg xml:space="preserve">new branch</msg>
514 <msg xml:space="preserve">new branch</msg>
503 </logentry>
515 </logentry>
504 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
516 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
505 <author email="person">person</author>
517 <author email="person">person</author>
506 <date>1970-01-16T01:06:40+00:00</date>
518 <date>1970-01-16T01:06:40+00:00</date>
507 <msg xml:space="preserve">no user, no domain</msg>
519 <msg xml:space="preserve">no user, no domain</msg>
508 </logentry>
520 </logentry>
509 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
521 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
510 <author email="other@place">other</author>
522 <author email="other@place">other</author>
511 <date>1970-01-14T21:20:00+00:00</date>
523 <date>1970-01-14T21:20:00+00:00</date>
512 <msg xml:space="preserve">no person</msg>
524 <msg xml:space="preserve">no person</msg>
513 </logentry>
525 </logentry>
514 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
526 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
515 <author email="other@place">A. N. Other</author>
527 <author email="other@place">A. N. Other</author>
516 <date>1970-01-13T17:33:20+00:00</date>
528 <date>1970-01-13T17:33:20+00:00</date>
517 <msg xml:space="preserve">other 1
529 <msg xml:space="preserve">other 1
518 other 2
530 other 2
519
531
520 other 3</msg>
532 other 3</msg>
521 </logentry>
533 </logentry>
522 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
534 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
523 <author email="user@hostname">User Name</author>
535 <author email="user@hostname">User Name</author>
524 <date>1970-01-12T13:46:40+00:00</date>
536 <date>1970-01-12T13:46:40+00:00</date>
525 <msg xml:space="preserve">line 1
537 <msg xml:space="preserve">line 1
526 line 2</msg>
538 line 2</msg>
527 </logentry>
539 </logentry>
528 </log>
540 </log>
529
541
530 $ hg log -v --style xml
542 $ hg log -v --style xml
531 <?xml version="1.0"?>
543 <?xml version="1.0"?>
532 <log>
544 <log>
533 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
545 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
534 <tag>tip</tag>
546 <tag>tip</tag>
535 <author email="test">test</author>
547 <author email="test">test</author>
536 <date>2020-01-01T10:01:00+00:00</date>
548 <date>2020-01-01T10:01:00+00:00</date>
537 <msg xml:space="preserve">third</msg>
549 <msg xml:space="preserve">third</msg>
538 <paths>
550 <paths>
539 <path action="A">fourth</path>
551 <path action="A">fourth</path>
540 <path action="A">third</path>
552 <path action="A">third</path>
541 <path action="R">second</path>
553 <path action="R">second</path>
542 </paths>
554 </paths>
543 <copies>
555 <copies>
544 <copy source="second">fourth</copy>
556 <copy source="second">fourth</copy>
545 </copies>
557 </copies>
546 </logentry>
558 </logentry>
547 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
559 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
548 <parent revision="-1" node="0000000000000000000000000000000000000000" />
560 <parent revision="-1" node="0000000000000000000000000000000000000000" />
549 <author email="user@hostname">User Name</author>
561 <author email="user@hostname">User Name</author>
550 <date>1970-01-12T13:46:40+00:00</date>
562 <date>1970-01-12T13:46:40+00:00</date>
551 <msg xml:space="preserve">second</msg>
563 <msg xml:space="preserve">second</msg>
552 <paths>
564 <paths>
553 <path action="A">second</path>
565 <path action="A">second</path>
554 </paths>
566 </paths>
555 </logentry>
567 </logentry>
556 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
568 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
557 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
569 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
558 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
570 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
559 <author email="person">person</author>
571 <author email="person">person</author>
560 <date>1970-01-18T08:40:01+00:00</date>
572 <date>1970-01-18T08:40:01+00:00</date>
561 <msg xml:space="preserve">merge</msg>
573 <msg xml:space="preserve">merge</msg>
562 <paths>
574 <paths>
563 </paths>
575 </paths>
564 </logentry>
576 </logentry>
565 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
577 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
566 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
578 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
567 <author email="person">person</author>
579 <author email="person">person</author>
568 <date>1970-01-18T08:40:00+00:00</date>
580 <date>1970-01-18T08:40:00+00:00</date>
569 <msg xml:space="preserve">new head</msg>
581 <msg xml:space="preserve">new head</msg>
570 <paths>
582 <paths>
571 <path action="A">d</path>
583 <path action="A">d</path>
572 </paths>
584 </paths>
573 </logentry>
585 </logentry>
574 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
586 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
575 <branch>foo</branch>
587 <branch>foo</branch>
576 <author email="person">person</author>
588 <author email="person">person</author>
577 <date>1970-01-17T04:53:20+00:00</date>
589 <date>1970-01-17T04:53:20+00:00</date>
578 <msg xml:space="preserve">new branch</msg>
590 <msg xml:space="preserve">new branch</msg>
579 <paths>
591 <paths>
580 </paths>
592 </paths>
581 </logentry>
593 </logentry>
582 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
594 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
583 <author email="person">person</author>
595 <author email="person">person</author>
584 <date>1970-01-16T01:06:40+00:00</date>
596 <date>1970-01-16T01:06:40+00:00</date>
585 <msg xml:space="preserve">no user, no domain</msg>
597 <msg xml:space="preserve">no user, no domain</msg>
586 <paths>
598 <paths>
587 <path action="M">c</path>
599 <path action="M">c</path>
588 </paths>
600 </paths>
589 </logentry>
601 </logentry>
590 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
602 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
591 <author email="other@place">other</author>
603 <author email="other@place">other</author>
592 <date>1970-01-14T21:20:00+00:00</date>
604 <date>1970-01-14T21:20:00+00:00</date>
593 <msg xml:space="preserve">no person</msg>
605 <msg xml:space="preserve">no person</msg>
594 <paths>
606 <paths>
595 <path action="A">c</path>
607 <path action="A">c</path>
596 </paths>
608 </paths>
597 </logentry>
609 </logentry>
598 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
610 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
599 <author email="other@place">A. N. Other</author>
611 <author email="other@place">A. N. Other</author>
600 <date>1970-01-13T17:33:20+00:00</date>
612 <date>1970-01-13T17:33:20+00:00</date>
601 <msg xml:space="preserve">other 1
613 <msg xml:space="preserve">other 1
602 other 2
614 other 2
603
615
604 other 3</msg>
616 other 3</msg>
605 <paths>
617 <paths>
606 <path action="A">b</path>
618 <path action="A">b</path>
607 </paths>
619 </paths>
608 </logentry>
620 </logentry>
609 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
621 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
610 <author email="user@hostname">User Name</author>
622 <author email="user@hostname">User Name</author>
611 <date>1970-01-12T13:46:40+00:00</date>
623 <date>1970-01-12T13:46:40+00:00</date>
612 <msg xml:space="preserve">line 1
624 <msg xml:space="preserve">line 1
613 line 2</msg>
625 line 2</msg>
614 <paths>
626 <paths>
615 <path action="A">a</path>
627 <path action="A">a</path>
616 </paths>
628 </paths>
617 </logentry>
629 </logentry>
618 </log>
630 </log>
619
631
620 $ hg log --debug --style xml
632 $ hg log --debug --style xml
621 <?xml version="1.0"?>
633 <?xml version="1.0"?>
622 <log>
634 <log>
623 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
635 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
624 <tag>tip</tag>
636 <tag>tip</tag>
625 <parent revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453" />
637 <parent revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453" />
626 <parent revision="-1" node="0000000000000000000000000000000000000000" />
638 <parent revision="-1" node="0000000000000000000000000000000000000000" />
627 <author email="test">test</author>
639 <author email="test">test</author>
628 <date>2020-01-01T10:01:00+00:00</date>
640 <date>2020-01-01T10:01:00+00:00</date>
629 <msg xml:space="preserve">third</msg>
641 <msg xml:space="preserve">third</msg>
630 <paths>
642 <paths>
631 <path action="A">fourth</path>
643 <path action="A">fourth</path>
632 <path action="A">third</path>
644 <path action="A">third</path>
633 <path action="R">second</path>
645 <path action="R">second</path>
634 </paths>
646 </paths>
635 <copies>
647 <copies>
636 <copy source="second">fourth</copy>
648 <copy source="second">fourth</copy>
637 </copies>
649 </copies>
638 <extra key="branch">default</extra>
650 <extra key="branch">default</extra>
639 </logentry>
651 </logentry>
640 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
652 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
641 <parent revision="-1" node="0000000000000000000000000000000000000000" />
653 <parent revision="-1" node="0000000000000000000000000000000000000000" />
642 <parent revision="-1" node="0000000000000000000000000000000000000000" />
654 <parent revision="-1" node="0000000000000000000000000000000000000000" />
643 <author email="user@hostname">User Name</author>
655 <author email="user@hostname">User Name</author>
644 <date>1970-01-12T13:46:40+00:00</date>
656 <date>1970-01-12T13:46:40+00:00</date>
645 <msg xml:space="preserve">second</msg>
657 <msg xml:space="preserve">second</msg>
646 <paths>
658 <paths>
647 <path action="A">second</path>
659 <path action="A">second</path>
648 </paths>
660 </paths>
649 <extra key="branch">default</extra>
661 <extra key="branch">default</extra>
650 </logentry>
662 </logentry>
651 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
663 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
652 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
664 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
653 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
665 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
654 <author email="person">person</author>
666 <author email="person">person</author>
655 <date>1970-01-18T08:40:01+00:00</date>
667 <date>1970-01-18T08:40:01+00:00</date>
656 <msg xml:space="preserve">merge</msg>
668 <msg xml:space="preserve">merge</msg>
657 <paths>
669 <paths>
658 </paths>
670 </paths>
659 <extra key="branch">default</extra>
671 <extra key="branch">default</extra>
660 </logentry>
672 </logentry>
661 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
673 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
662 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
674 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
663 <parent revision="-1" node="0000000000000000000000000000000000000000" />
675 <parent revision="-1" node="0000000000000000000000000000000000000000" />
664 <author email="person">person</author>
676 <author email="person">person</author>
665 <date>1970-01-18T08:40:00+00:00</date>
677 <date>1970-01-18T08:40:00+00:00</date>
666 <msg xml:space="preserve">new head</msg>
678 <msg xml:space="preserve">new head</msg>
667 <paths>
679 <paths>
668 <path action="A">d</path>
680 <path action="A">d</path>
669 </paths>
681 </paths>
670 <extra key="branch">default</extra>
682 <extra key="branch">default</extra>
671 </logentry>
683 </logentry>
672 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
684 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
673 <branch>foo</branch>
685 <branch>foo</branch>
674 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
686 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
675 <parent revision="-1" node="0000000000000000000000000000000000000000" />
687 <parent revision="-1" node="0000000000000000000000000000000000000000" />
676 <author email="person">person</author>
688 <author email="person">person</author>
677 <date>1970-01-17T04:53:20+00:00</date>
689 <date>1970-01-17T04:53:20+00:00</date>
678 <msg xml:space="preserve">new branch</msg>
690 <msg xml:space="preserve">new branch</msg>
679 <paths>
691 <paths>
680 </paths>
692 </paths>
681 <extra key="branch">foo</extra>
693 <extra key="branch">foo</extra>
682 </logentry>
694 </logentry>
683 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
695 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
684 <parent revision="2" node="97054abb4ab824450e9164180baf491ae0078465" />
696 <parent revision="2" node="97054abb4ab824450e9164180baf491ae0078465" />
685 <parent revision="-1" node="0000000000000000000000000000000000000000" />
697 <parent revision="-1" node="0000000000000000000000000000000000000000" />
686 <author email="person">person</author>
698 <author email="person">person</author>
687 <date>1970-01-16T01:06:40+00:00</date>
699 <date>1970-01-16T01:06:40+00:00</date>
688 <msg xml:space="preserve">no user, no domain</msg>
700 <msg xml:space="preserve">no user, no domain</msg>
689 <paths>
701 <paths>
690 <path action="M">c</path>
702 <path action="M">c</path>
691 </paths>
703 </paths>
692 <extra key="branch">default</extra>
704 <extra key="branch">default</extra>
693 </logentry>
705 </logentry>
694 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
706 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
695 <parent revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965" />
707 <parent revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965" />
696 <parent revision="-1" node="0000000000000000000000000000000000000000" />
708 <parent revision="-1" node="0000000000000000000000000000000000000000" />
697 <author email="other@place">other</author>
709 <author email="other@place">other</author>
698 <date>1970-01-14T21:20:00+00:00</date>
710 <date>1970-01-14T21:20:00+00:00</date>
699 <msg xml:space="preserve">no person</msg>
711 <msg xml:space="preserve">no person</msg>
700 <paths>
712 <paths>
701 <path action="A">c</path>
713 <path action="A">c</path>
702 </paths>
714 </paths>
703 <extra key="branch">default</extra>
715 <extra key="branch">default</extra>
704 </logentry>
716 </logentry>
705 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
717 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
706 <parent revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f" />
718 <parent revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f" />
707 <parent revision="-1" node="0000000000000000000000000000000000000000" />
719 <parent revision="-1" node="0000000000000000000000000000000000000000" />
708 <author email="other@place">A. N. Other</author>
720 <author email="other@place">A. N. Other</author>
709 <date>1970-01-13T17:33:20+00:00</date>
721 <date>1970-01-13T17:33:20+00:00</date>
710 <msg xml:space="preserve">other 1
722 <msg xml:space="preserve">other 1
711 other 2
723 other 2
712
724
713 other 3</msg>
725 other 3</msg>
714 <paths>
726 <paths>
715 <path action="A">b</path>
727 <path action="A">b</path>
716 </paths>
728 </paths>
717 <extra key="branch">default</extra>
729 <extra key="branch">default</extra>
718 </logentry>
730 </logentry>
719 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
731 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
720 <parent revision="-1" node="0000000000000000000000000000000000000000" />
732 <parent revision="-1" node="0000000000000000000000000000000000000000" />
721 <parent revision="-1" node="0000000000000000000000000000000000000000" />
733 <parent revision="-1" node="0000000000000000000000000000000000000000" />
722 <author email="user@hostname">User Name</author>
734 <author email="user@hostname">User Name</author>
723 <date>1970-01-12T13:46:40+00:00</date>
735 <date>1970-01-12T13:46:40+00:00</date>
724 <msg xml:space="preserve">line 1
736 <msg xml:space="preserve">line 1
725 line 2</msg>
737 line 2</msg>
726 <paths>
738 <paths>
727 <path action="A">a</path>
739 <path action="A">a</path>
728 </paths>
740 </paths>
729 <extra key="branch">default</extra>
741 <extra key="branch">default</extra>
730 </logentry>
742 </logentry>
731 </log>
743 </log>
732
744
733
745
734 Test JSON style:
746 Test JSON style:
735
747
736 $ hg log -k nosuch -Tjson
748 $ hg log -k nosuch -Tjson
737 []
749 []
738
750
739 $ hg log -qr . -Tjson
751 $ hg log -qr . -Tjson
740 [
752 [
741 {
753 {
742 "rev": 8,
754 "rev": 8,
743 "node": "95c24699272ef57d062b8bccc32c878bf841784a"
755 "node": "95c24699272ef57d062b8bccc32c878bf841784a"
744 }
756 }
745 ]
757 ]
746
758
747 $ hg log -vpr . -Tjson --stat
759 $ hg log -vpr . -Tjson --stat
748 [
760 [
749 {
761 {
750 "rev": 8,
762 "rev": 8,
751 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
763 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
752 "branch": "default",
764 "branch": "default",
753 "phase": "draft",
765 "phase": "draft",
754 "user": "test",
766 "user": "test",
755 "date": [1577872860, 0],
767 "date": [1577872860, 0],
756 "desc": "third",
768 "desc": "third",
757 "bookmarks": [],
769 "bookmarks": [],
758 "tags": ["tip"],
770 "tags": ["tip"],
759 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
771 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
760 "files": ["fourth", "second", "third"],
772 "files": ["fourth", "second", "third"],
761 "diffstat": " fourth | 1 +\n second | 1 -\n third | 1 +\n 3 files changed, 2 insertions(+), 1 deletions(-)\n",
773 "diffstat": " fourth | 1 +\n second | 1 -\n third | 1 +\n 3 files changed, 2 insertions(+), 1 deletions(-)\n",
762 "diff": "diff -r 29114dbae42b -r 95c24699272e fourth\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/fourth\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+second\ndiff -r 29114dbae42b -r 95c24699272e second\n--- a/second\tMon Jan 12 13:46:40 1970 +0000\n+++ /dev/null\tThu Jan 01 00:00:00 1970 +0000\n@@ -1,1 +0,0 @@\n-second\ndiff -r 29114dbae42b -r 95c24699272e third\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/third\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+third\n"
774 "diff": "diff -r 29114dbae42b -r 95c24699272e fourth\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/fourth\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+second\ndiff -r 29114dbae42b -r 95c24699272e second\n--- a/second\tMon Jan 12 13:46:40 1970 +0000\n+++ /dev/null\tThu Jan 01 00:00:00 1970 +0000\n@@ -1,1 +0,0 @@\n-second\ndiff -r 29114dbae42b -r 95c24699272e third\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/third\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+third\n"
763 }
775 }
764 ]
776 ]
765
777
766 honor --git but not format-breaking diffopts
778 honor --git but not format-breaking diffopts
767 $ hg --config diff.noprefix=True log --git -vpr . -Tjson
779 $ hg --config diff.noprefix=True log --git -vpr . -Tjson
768 [
780 [
769 {
781 {
770 "rev": 8,
782 "rev": 8,
771 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
783 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
772 "branch": "default",
784 "branch": "default",
773 "phase": "draft",
785 "phase": "draft",
774 "user": "test",
786 "user": "test",
775 "date": [1577872860, 0],
787 "date": [1577872860, 0],
776 "desc": "third",
788 "desc": "third",
777 "bookmarks": [],
789 "bookmarks": [],
778 "tags": ["tip"],
790 "tags": ["tip"],
779 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
791 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
780 "files": ["fourth", "second", "third"],
792 "files": ["fourth", "second", "third"],
781 "diff": "diff --git a/second b/fourth\nrename from second\nrename to fourth\ndiff --git a/third b/third\nnew file mode 100644\n--- /dev/null\n+++ b/third\n@@ -0,0 +1,1 @@\n+third\n"
793 "diff": "diff --git a/second b/fourth\nrename from second\nrename to fourth\ndiff --git a/third b/third\nnew file mode 100644\n--- /dev/null\n+++ b/third\n@@ -0,0 +1,1 @@\n+third\n"
782 }
794 }
783 ]
795 ]
784
796
785 $ hg log -T json
797 $ hg log -T json
786 [
798 [
787 {
799 {
788 "rev": 8,
800 "rev": 8,
789 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
801 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
790 "branch": "default",
802 "branch": "default",
791 "phase": "draft",
803 "phase": "draft",
792 "user": "test",
804 "user": "test",
793 "date": [1577872860, 0],
805 "date": [1577872860, 0],
794 "desc": "third",
806 "desc": "third",
795 "bookmarks": [],
807 "bookmarks": [],
796 "tags": ["tip"],
808 "tags": ["tip"],
797 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"]
809 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"]
798 },
810 },
799 {
811 {
800 "rev": 7,
812 "rev": 7,
801 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
813 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
802 "branch": "default",
814 "branch": "default",
803 "phase": "draft",
815 "phase": "draft",
804 "user": "User Name <user@hostname>",
816 "user": "User Name <user@hostname>",
805 "date": [1000000, 0],
817 "date": [1000000, 0],
806 "desc": "second",
818 "desc": "second",
807 "bookmarks": [],
819 "bookmarks": [],
808 "tags": [],
820 "tags": [],
809 "parents": ["0000000000000000000000000000000000000000"]
821 "parents": ["0000000000000000000000000000000000000000"]
810 },
822 },
811 {
823 {
812 "rev": 6,
824 "rev": 6,
813 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
825 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
814 "branch": "default",
826 "branch": "default",
815 "phase": "draft",
827 "phase": "draft",
816 "user": "person",
828 "user": "person",
817 "date": [1500001, 0],
829 "date": [1500001, 0],
818 "desc": "merge",
830 "desc": "merge",
819 "bookmarks": [],
831 "bookmarks": [],
820 "tags": [],
832 "tags": [],
821 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"]
833 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"]
822 },
834 },
823 {
835 {
824 "rev": 5,
836 "rev": 5,
825 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
837 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
826 "branch": "default",
838 "branch": "default",
827 "phase": "draft",
839 "phase": "draft",
828 "user": "person",
840 "user": "person",
829 "date": [1500000, 0],
841 "date": [1500000, 0],
830 "desc": "new head",
842 "desc": "new head",
831 "bookmarks": [],
843 "bookmarks": [],
832 "tags": [],
844 "tags": [],
833 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
845 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
834 },
846 },
835 {
847 {
836 "rev": 4,
848 "rev": 4,
837 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
849 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
838 "branch": "foo",
850 "branch": "foo",
839 "phase": "draft",
851 "phase": "draft",
840 "user": "person",
852 "user": "person",
841 "date": [1400000, 0],
853 "date": [1400000, 0],
842 "desc": "new branch",
854 "desc": "new branch",
843 "bookmarks": [],
855 "bookmarks": [],
844 "tags": [],
856 "tags": [],
845 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
857 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
846 },
858 },
847 {
859 {
848 "rev": 3,
860 "rev": 3,
849 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
861 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
850 "branch": "default",
862 "branch": "default",
851 "phase": "draft",
863 "phase": "draft",
852 "user": "person",
864 "user": "person",
853 "date": [1300000, 0],
865 "date": [1300000, 0],
854 "desc": "no user, no domain",
866 "desc": "no user, no domain",
855 "bookmarks": [],
867 "bookmarks": [],
856 "tags": [],
868 "tags": [],
857 "parents": ["97054abb4ab824450e9164180baf491ae0078465"]
869 "parents": ["97054abb4ab824450e9164180baf491ae0078465"]
858 },
870 },
859 {
871 {
860 "rev": 2,
872 "rev": 2,
861 "node": "97054abb4ab824450e9164180baf491ae0078465",
873 "node": "97054abb4ab824450e9164180baf491ae0078465",
862 "branch": "default",
874 "branch": "default",
863 "phase": "draft",
875 "phase": "draft",
864 "user": "other@place",
876 "user": "other@place",
865 "date": [1200000, 0],
877 "date": [1200000, 0],
866 "desc": "no person",
878 "desc": "no person",
867 "bookmarks": [],
879 "bookmarks": [],
868 "tags": [],
880 "tags": [],
869 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"]
881 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"]
870 },
882 },
871 {
883 {
872 "rev": 1,
884 "rev": 1,
873 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
885 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
874 "branch": "default",
886 "branch": "default",
875 "phase": "draft",
887 "phase": "draft",
876 "user": "A. N. Other <other@place>",
888 "user": "A. N. Other <other@place>",
877 "date": [1100000, 0],
889 "date": [1100000, 0],
878 "desc": "other 1\nother 2\n\nother 3",
890 "desc": "other 1\nother 2\n\nother 3",
879 "bookmarks": [],
891 "bookmarks": [],
880 "tags": [],
892 "tags": [],
881 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"]
893 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"]
882 },
894 },
883 {
895 {
884 "rev": 0,
896 "rev": 0,
885 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
897 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
886 "branch": "default",
898 "branch": "default",
887 "phase": "draft",
899 "phase": "draft",
888 "user": "User Name <user@hostname>",
900 "user": "User Name <user@hostname>",
889 "date": [1000000, 0],
901 "date": [1000000, 0],
890 "desc": "line 1\nline 2",
902 "desc": "line 1\nline 2",
891 "bookmarks": [],
903 "bookmarks": [],
892 "tags": [],
904 "tags": [],
893 "parents": ["0000000000000000000000000000000000000000"]
905 "parents": ["0000000000000000000000000000000000000000"]
894 }
906 }
895 ]
907 ]
896
908
897 $ hg heads -v -Tjson
909 $ hg heads -v -Tjson
898 [
910 [
899 {
911 {
900 "rev": 8,
912 "rev": 8,
901 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
913 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
902 "branch": "default",
914 "branch": "default",
903 "phase": "draft",
915 "phase": "draft",
904 "user": "test",
916 "user": "test",
905 "date": [1577872860, 0],
917 "date": [1577872860, 0],
906 "desc": "third",
918 "desc": "third",
907 "bookmarks": [],
919 "bookmarks": [],
908 "tags": ["tip"],
920 "tags": ["tip"],
909 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
921 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
910 "files": ["fourth", "second", "third"]
922 "files": ["fourth", "second", "third"]
911 },
923 },
912 {
924 {
913 "rev": 6,
925 "rev": 6,
914 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
926 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
915 "branch": "default",
927 "branch": "default",
916 "phase": "draft",
928 "phase": "draft",
917 "user": "person",
929 "user": "person",
918 "date": [1500001, 0],
930 "date": [1500001, 0],
919 "desc": "merge",
931 "desc": "merge",
920 "bookmarks": [],
932 "bookmarks": [],
921 "tags": [],
933 "tags": [],
922 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
934 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
923 "files": []
935 "files": []
924 },
936 },
925 {
937 {
926 "rev": 4,
938 "rev": 4,
927 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
939 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
928 "branch": "foo",
940 "branch": "foo",
929 "phase": "draft",
941 "phase": "draft",
930 "user": "person",
942 "user": "person",
931 "date": [1400000, 0],
943 "date": [1400000, 0],
932 "desc": "new branch",
944 "desc": "new branch",
933 "bookmarks": [],
945 "bookmarks": [],
934 "tags": [],
946 "tags": [],
935 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
947 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
936 "files": []
948 "files": []
937 }
949 }
938 ]
950 ]
939
951
940 $ hg log --debug -Tjson
952 $ hg log --debug -Tjson
941 [
953 [
942 {
954 {
943 "rev": 8,
955 "rev": 8,
944 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
956 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
945 "branch": "default",
957 "branch": "default",
946 "phase": "draft",
958 "phase": "draft",
947 "user": "test",
959 "user": "test",
948 "date": [1577872860, 0],
960 "date": [1577872860, 0],
949 "desc": "third",
961 "desc": "third",
950 "bookmarks": [],
962 "bookmarks": [],
951 "tags": ["tip"],
963 "tags": ["tip"],
952 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
964 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
953 "manifest": "94961b75a2da554b4df6fb599e5bfc7d48de0c64",
965 "manifest": "94961b75a2da554b4df6fb599e5bfc7d48de0c64",
954 "extra": {"branch": "default"},
966 "extra": {"branch": "default"},
955 "modified": [],
967 "modified": [],
956 "added": ["fourth", "third"],
968 "added": ["fourth", "third"],
957 "removed": ["second"]
969 "removed": ["second"]
958 },
970 },
959 {
971 {
960 "rev": 7,
972 "rev": 7,
961 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
973 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
962 "branch": "default",
974 "branch": "default",
963 "phase": "draft",
975 "phase": "draft",
964 "user": "User Name <user@hostname>",
976 "user": "User Name <user@hostname>",
965 "date": [1000000, 0],
977 "date": [1000000, 0],
966 "desc": "second",
978 "desc": "second",
967 "bookmarks": [],
979 "bookmarks": [],
968 "tags": [],
980 "tags": [],
969 "parents": ["0000000000000000000000000000000000000000"],
981 "parents": ["0000000000000000000000000000000000000000"],
970 "manifest": "f2dbc354b94e5ec0b4f10680ee0cee816101d0bf",
982 "manifest": "f2dbc354b94e5ec0b4f10680ee0cee816101d0bf",
971 "extra": {"branch": "default"},
983 "extra": {"branch": "default"},
972 "modified": [],
984 "modified": [],
973 "added": ["second"],
985 "added": ["second"],
974 "removed": []
986 "removed": []
975 },
987 },
976 {
988 {
977 "rev": 6,
989 "rev": 6,
978 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
990 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
979 "branch": "default",
991 "branch": "default",
980 "phase": "draft",
992 "phase": "draft",
981 "user": "person",
993 "user": "person",
982 "date": [1500001, 0],
994 "date": [1500001, 0],
983 "desc": "merge",
995 "desc": "merge",
984 "bookmarks": [],
996 "bookmarks": [],
985 "tags": [],
997 "tags": [],
986 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
998 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
987 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
999 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
988 "extra": {"branch": "default"},
1000 "extra": {"branch": "default"},
989 "modified": [],
1001 "modified": [],
990 "added": [],
1002 "added": [],
991 "removed": []
1003 "removed": []
992 },
1004 },
993 {
1005 {
994 "rev": 5,
1006 "rev": 5,
995 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
1007 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
996 "branch": "default",
1008 "branch": "default",
997 "phase": "draft",
1009 "phase": "draft",
998 "user": "person",
1010 "user": "person",
999 "date": [1500000, 0],
1011 "date": [1500000, 0],
1000 "desc": "new head",
1012 "desc": "new head",
1001 "bookmarks": [],
1013 "bookmarks": [],
1002 "tags": [],
1014 "tags": [],
1003 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1015 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1004 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
1016 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
1005 "extra": {"branch": "default"},
1017 "extra": {"branch": "default"},
1006 "modified": [],
1018 "modified": [],
1007 "added": ["d"],
1019 "added": ["d"],
1008 "removed": []
1020 "removed": []
1009 },
1021 },
1010 {
1022 {
1011 "rev": 4,
1023 "rev": 4,
1012 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
1024 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
1013 "branch": "foo",
1025 "branch": "foo",
1014 "phase": "draft",
1026 "phase": "draft",
1015 "user": "person",
1027 "user": "person",
1016 "date": [1400000, 0],
1028 "date": [1400000, 0],
1017 "desc": "new branch",
1029 "desc": "new branch",
1018 "bookmarks": [],
1030 "bookmarks": [],
1019 "tags": [],
1031 "tags": [],
1020 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1032 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1021 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
1033 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
1022 "extra": {"branch": "foo"},
1034 "extra": {"branch": "foo"},
1023 "modified": [],
1035 "modified": [],
1024 "added": [],
1036 "added": [],
1025 "removed": []
1037 "removed": []
1026 },
1038 },
1027 {
1039 {
1028 "rev": 3,
1040 "rev": 3,
1029 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
1041 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
1030 "branch": "default",
1042 "branch": "default",
1031 "phase": "draft",
1043 "phase": "draft",
1032 "user": "person",
1044 "user": "person",
1033 "date": [1300000, 0],
1045 "date": [1300000, 0],
1034 "desc": "no user, no domain",
1046 "desc": "no user, no domain",
1035 "bookmarks": [],
1047 "bookmarks": [],
1036 "tags": [],
1048 "tags": [],
1037 "parents": ["97054abb4ab824450e9164180baf491ae0078465"],
1049 "parents": ["97054abb4ab824450e9164180baf491ae0078465"],
1038 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
1050 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
1039 "extra": {"branch": "default"},
1051 "extra": {"branch": "default"},
1040 "modified": ["c"],
1052 "modified": ["c"],
1041 "added": [],
1053 "added": [],
1042 "removed": []
1054 "removed": []
1043 },
1055 },
1044 {
1056 {
1045 "rev": 2,
1057 "rev": 2,
1046 "node": "97054abb4ab824450e9164180baf491ae0078465",
1058 "node": "97054abb4ab824450e9164180baf491ae0078465",
1047 "branch": "default",
1059 "branch": "default",
1048 "phase": "draft",
1060 "phase": "draft",
1049 "user": "other@place",
1061 "user": "other@place",
1050 "date": [1200000, 0],
1062 "date": [1200000, 0],
1051 "desc": "no person",
1063 "desc": "no person",
1052 "bookmarks": [],
1064 "bookmarks": [],
1053 "tags": [],
1065 "tags": [],
1054 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"],
1066 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"],
1055 "manifest": "6e0e82995c35d0d57a52aca8da4e56139e06b4b1",
1067 "manifest": "6e0e82995c35d0d57a52aca8da4e56139e06b4b1",
1056 "extra": {"branch": "default"},
1068 "extra": {"branch": "default"},
1057 "modified": [],
1069 "modified": [],
1058 "added": ["c"],
1070 "added": ["c"],
1059 "removed": []
1071 "removed": []
1060 },
1072 },
1061 {
1073 {
1062 "rev": 1,
1074 "rev": 1,
1063 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
1075 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
1064 "branch": "default",
1076 "branch": "default",
1065 "phase": "draft",
1077 "phase": "draft",
1066 "user": "A. N. Other <other@place>",
1078 "user": "A. N. Other <other@place>",
1067 "date": [1100000, 0],
1079 "date": [1100000, 0],
1068 "desc": "other 1\nother 2\n\nother 3",
1080 "desc": "other 1\nother 2\n\nother 3",
1069 "bookmarks": [],
1081 "bookmarks": [],
1070 "tags": [],
1082 "tags": [],
1071 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"],
1083 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"],
1072 "manifest": "4e8d705b1e53e3f9375e0e60dc7b525d8211fe55",
1084 "manifest": "4e8d705b1e53e3f9375e0e60dc7b525d8211fe55",
1073 "extra": {"branch": "default"},
1085 "extra": {"branch": "default"},
1074 "modified": [],
1086 "modified": [],
1075 "added": ["b"],
1087 "added": ["b"],
1076 "removed": []
1088 "removed": []
1077 },
1089 },
1078 {
1090 {
1079 "rev": 0,
1091 "rev": 0,
1080 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
1092 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
1081 "branch": "default",
1093 "branch": "default",
1082 "phase": "draft",
1094 "phase": "draft",
1083 "user": "User Name <user@hostname>",
1095 "user": "User Name <user@hostname>",
1084 "date": [1000000, 0],
1096 "date": [1000000, 0],
1085 "desc": "line 1\nline 2",
1097 "desc": "line 1\nline 2",
1086 "bookmarks": [],
1098 "bookmarks": [],
1087 "tags": [],
1099 "tags": [],
1088 "parents": ["0000000000000000000000000000000000000000"],
1100 "parents": ["0000000000000000000000000000000000000000"],
1089 "manifest": "a0c8bcbbb45c63b90b70ad007bf38961f64f2af0",
1101 "manifest": "a0c8bcbbb45c63b90b70ad007bf38961f64f2af0",
1090 "extra": {"branch": "default"},
1102 "extra": {"branch": "default"},
1091 "modified": [],
1103 "modified": [],
1092 "added": ["a"],
1104 "added": ["a"],
1093 "removed": []
1105 "removed": []
1094 }
1106 }
1095 ]
1107 ]
1096
1108
1097 Error if style not readable:
1109 Error if style not readable:
1098
1110
1099 #if unix-permissions no-root
1111 #if unix-permissions no-root
1100 $ touch q
1112 $ touch q
1101 $ chmod 0 q
1113 $ chmod 0 q
1102 $ hg log --style ./q
1114 $ hg log --style ./q
1103 abort: Permission denied: ./q
1115 abort: Permission denied: ./q
1104 [255]
1116 [255]
1105 #endif
1117 #endif
1106
1118
1107 Error if no style:
1119 Error if no style:
1108
1120
1109 $ hg log --style notexist
1121 $ hg log --style notexist
1110 abort: style 'notexist' not found
1122 abort: style 'notexist' not found
1111 (available styles: bisect, changelog, compact, default, phases, show, status, xml)
1123 (available styles: bisect, changelog, compact, default, phases, show, status, xml)
1112 [255]
1124 [255]
1113
1125
1114 $ hg log -T list
1126 $ hg log -T list
1115 available styles: bisect, changelog, compact, default, phases, show, status, xml
1127 available styles: bisect, changelog, compact, default, phases, show, status, xml
1116 abort: specify a template
1128 abort: specify a template
1117 [255]
1129 [255]
1118
1130
1119 Error if style missing key:
1131 Error if style missing key:
1120
1132
1121 $ echo 'q = q' > t
1133 $ echo 'q = q' > t
1122 $ hg log --style ./t
1134 $ hg log --style ./t
1123 abort: "changeset" not in template map
1135 abort: "changeset" not in template map
1124 [255]
1136 [255]
1125
1137
1126 Error if style missing value:
1138 Error if style missing value:
1127
1139
1128 $ echo 'changeset =' > t
1140 $ echo 'changeset =' > t
1129 $ hg log --style t
1141 $ hg log --style t
1130 hg: parse error at t:1: missing value
1142 hg: parse error at t:1: missing value
1131 [255]
1143 [255]
1132
1144
1133 Error if include fails:
1145 Error if include fails:
1134
1146
1135 $ echo 'changeset = q' >> t
1147 $ echo 'changeset = q' >> t
1136 #if unix-permissions no-root
1148 #if unix-permissions no-root
1137 $ hg log --style ./t
1149 $ hg log --style ./t
1138 abort: template file ./q: Permission denied
1150 abort: template file ./q: Permission denied
1139 [255]
1151 [255]
1140 $ rm -f q
1152 $ rm -f q
1141 #endif
1153 #endif
1142
1154
1143 Include works:
1155 Include works:
1144
1156
1145 $ echo '{rev}' > q
1157 $ echo '{rev}' > q
1146 $ hg log --style ./t
1158 $ hg log --style ./t
1147 8
1159 8
1148 7
1160 7
1149 6
1161 6
1150 5
1162 5
1151 4
1163 4
1152 3
1164 3
1153 2
1165 2
1154 1
1166 1
1155 0
1167 0
1156
1168
1157 Check that recursive reference does not fall into RuntimeError (issue4758):
1169 Check that recursive reference does not fall into RuntimeError (issue4758):
1158
1170
1159 common mistake:
1171 common mistake:
1160
1172
1161 $ hg log -T '{changeset}\n'
1173 $ hg log -T '{changeset}\n'
1162 abort: recursive reference 'changeset' in template
1174 abort: recursive reference 'changeset' in template
1163 [255]
1175 [255]
1164
1176
1165 circular reference:
1177 circular reference:
1166
1178
1167 $ cat << EOF > issue4758
1179 $ cat << EOF > issue4758
1168 > changeset = '{foo}'
1180 > changeset = '{foo}'
1169 > foo = '{changeset}'
1181 > foo = '{changeset}'
1170 > EOF
1182 > EOF
1171 $ hg log --style ./issue4758
1183 $ hg log --style ./issue4758
1172 abort: recursive reference 'foo' in template
1184 abort: recursive reference 'foo' in template
1173 [255]
1185 [255]
1174
1186
1175 buildmap() -> gettemplate(), where no thunk was made:
1187 buildmap() -> gettemplate(), where no thunk was made:
1176
1188
1177 $ hg log -T '{files % changeset}\n'
1189 $ hg log -T '{files % changeset}\n'
1178 abort: recursive reference 'changeset' in template
1190 abort: recursive reference 'changeset' in template
1179 [255]
1191 [255]
1180
1192
1181 not a recursion if a keyword of the same name exists:
1193 not a recursion if a keyword of the same name exists:
1182
1194
1183 $ cat << EOF > issue4758
1195 $ cat << EOF > issue4758
1184 > changeset = '{tags % rev}'
1196 > changeset = '{tags % rev}'
1185 > rev = '{rev} {tag}\n'
1197 > rev = '{rev} {tag}\n'
1186 > EOF
1198 > EOF
1187 $ hg log --style ./issue4758 -r tip
1199 $ hg log --style ./issue4758 -r tip
1188 8 tip
1200 8 tip
1189
1201
1190 Check that {phase} works correctly on parents:
1202 Check that {phase} works correctly on parents:
1191
1203
1192 $ cat << EOF > parentphase
1204 $ cat << EOF > parentphase
1193 > changeset_debug = '{rev} ({phase}):{parents}\n'
1205 > changeset_debug = '{rev} ({phase}):{parents}\n'
1194 > parent = ' {rev} ({phase})'
1206 > parent = ' {rev} ({phase})'
1195 > EOF
1207 > EOF
1196 $ hg phase -r 5 --public
1208 $ hg phase -r 5 --public
1197 $ hg phase -r 7 --secret --force
1209 $ hg phase -r 7 --secret --force
1198 $ hg log --debug -G --style ./parentphase
1210 $ hg log --debug -G --style ./parentphase
1199 @ 8 (secret): 7 (secret) -1 (public)
1211 @ 8 (secret): 7 (secret) -1 (public)
1200 |
1212 |
1201 o 7 (secret): -1 (public) -1 (public)
1213 o 7 (secret): -1 (public) -1 (public)
1202
1214
1203 o 6 (draft): 5 (public) 4 (draft)
1215 o 6 (draft): 5 (public) 4 (draft)
1204 |\
1216 |\
1205 | o 5 (public): 3 (public) -1 (public)
1217 | o 5 (public): 3 (public) -1 (public)
1206 | |
1218 | |
1207 o | 4 (draft): 3 (public) -1 (public)
1219 o | 4 (draft): 3 (public) -1 (public)
1208 |/
1220 |/
1209 o 3 (public): 2 (public) -1 (public)
1221 o 3 (public): 2 (public) -1 (public)
1210 |
1222 |
1211 o 2 (public): 1 (public) -1 (public)
1223 o 2 (public): 1 (public) -1 (public)
1212 |
1224 |
1213 o 1 (public): 0 (public) -1 (public)
1225 o 1 (public): 0 (public) -1 (public)
1214 |
1226 |
1215 o 0 (public): -1 (public) -1 (public)
1227 o 0 (public): -1 (public) -1 (public)
1216
1228
1217
1229
1218 Missing non-standard names give no error (backward compatibility):
1230 Missing non-standard names give no error (backward compatibility):
1219
1231
1220 $ echo "changeset = '{c}'" > t
1232 $ echo "changeset = '{c}'" > t
1221 $ hg log --style ./t
1233 $ hg log --style ./t
1222
1234
1223 Defining non-standard name works:
1235 Defining non-standard name works:
1224
1236
1225 $ cat <<EOF > t
1237 $ cat <<EOF > t
1226 > changeset = '{c}'
1238 > changeset = '{c}'
1227 > c = q
1239 > c = q
1228 > EOF
1240 > EOF
1229 $ hg log --style ./t
1241 $ hg log --style ./t
1230 8
1242 8
1231 7
1243 7
1232 6
1244 6
1233 5
1245 5
1234 4
1246 4
1235 3
1247 3
1236 2
1248 2
1237 1
1249 1
1238 0
1250 0
1239
1251
1240 ui.style works:
1252 ui.style works:
1241
1253
1242 $ echo '[ui]' > .hg/hgrc
1254 $ echo '[ui]' > .hg/hgrc
1243 $ echo 'style = t' >> .hg/hgrc
1255 $ echo 'style = t' >> .hg/hgrc
1244 $ hg log
1256 $ hg log
1245 8
1257 8
1246 7
1258 7
1247 6
1259 6
1248 5
1260 5
1249 4
1261 4
1250 3
1262 3
1251 2
1263 2
1252 1
1264 1
1253 0
1265 0
1254
1266
1255
1267
1256 Issue338:
1268 Issue338:
1257
1269
1258 $ hg log --style=changelog > changelog
1270 $ hg log --style=changelog > changelog
1259
1271
1260 $ cat changelog
1272 $ cat changelog
1261 2020-01-01 test <test>
1273 2020-01-01 test <test>
1262
1274
1263 * fourth, second, third:
1275 * fourth, second, third:
1264 third
1276 third
1265 [95c24699272e] [tip]
1277 [95c24699272e] [tip]
1266
1278
1267 1970-01-12 User Name <user@hostname>
1279 1970-01-12 User Name <user@hostname>
1268
1280
1269 * second:
1281 * second:
1270 second
1282 second
1271 [29114dbae42b]
1283 [29114dbae42b]
1272
1284
1273 1970-01-18 person <person>
1285 1970-01-18 person <person>
1274
1286
1275 * merge
1287 * merge
1276 [d41e714fe50d]
1288 [d41e714fe50d]
1277
1289
1278 * d:
1290 * d:
1279 new head
1291 new head
1280 [13207e5a10d9]
1292 [13207e5a10d9]
1281
1293
1282 1970-01-17 person <person>
1294 1970-01-17 person <person>
1283
1295
1284 * new branch
1296 * new branch
1285 [bbe44766e73d] <foo>
1297 [bbe44766e73d] <foo>
1286
1298
1287 1970-01-16 person <person>
1299 1970-01-16 person <person>
1288
1300
1289 * c:
1301 * c:
1290 no user, no domain
1302 no user, no domain
1291 [10e46f2dcbf4]
1303 [10e46f2dcbf4]
1292
1304
1293 1970-01-14 other <other@place>
1305 1970-01-14 other <other@place>
1294
1306
1295 * c:
1307 * c:
1296 no person
1308 no person
1297 [97054abb4ab8]
1309 [97054abb4ab8]
1298
1310
1299 1970-01-13 A. N. Other <other@place>
1311 1970-01-13 A. N. Other <other@place>
1300
1312
1301 * b:
1313 * b:
1302 other 1 other 2
1314 other 1 other 2
1303
1315
1304 other 3
1316 other 3
1305 [b608e9d1a3f0]
1317 [b608e9d1a3f0]
1306
1318
1307 1970-01-12 User Name <user@hostname>
1319 1970-01-12 User Name <user@hostname>
1308
1320
1309 * a:
1321 * a:
1310 line 1 line 2
1322 line 1 line 2
1311 [1e4e1b8f71e0]
1323 [1e4e1b8f71e0]
1312
1324
1313
1325
1314 Issue2130: xml output for 'hg heads' is malformed
1326 Issue2130: xml output for 'hg heads' is malformed
1315
1327
1316 $ hg heads --style changelog
1328 $ hg heads --style changelog
1317 2020-01-01 test <test>
1329 2020-01-01 test <test>
1318
1330
1319 * fourth, second, third:
1331 * fourth, second, third:
1320 third
1332 third
1321 [95c24699272e] [tip]
1333 [95c24699272e] [tip]
1322
1334
1323 1970-01-18 person <person>
1335 1970-01-18 person <person>
1324
1336
1325 * merge
1337 * merge
1326 [d41e714fe50d]
1338 [d41e714fe50d]
1327
1339
1328 1970-01-17 person <person>
1340 1970-01-17 person <person>
1329
1341
1330 * new branch
1342 * new branch
1331 [bbe44766e73d] <foo>
1343 [bbe44766e73d] <foo>
1332
1344
1333
1345
1334 Keys work:
1346 Keys work:
1335
1347
1336 $ for key in author branch branches date desc file_adds file_dels file_mods \
1348 $ for key in author branch branches date desc file_adds file_dels file_mods \
1337 > file_copies file_copies_switch files \
1349 > file_copies file_copies_switch files \
1338 > manifest node parents rev tags diffstat extras \
1350 > manifest node parents rev tags diffstat extras \
1339 > p1rev p2rev p1node p2node; do
1351 > p1rev p2rev p1node p2node; do
1340 > for mode in '' --verbose --debug; do
1352 > for mode in '' --verbose --debug; do
1341 > hg log $mode --template "$key$mode: {$key}\n"
1353 > hg log $mode --template "$key$mode: {$key}\n"
1342 > done
1354 > done
1343 > done
1355 > done
1344 author: test
1356 author: test
1345 author: User Name <user@hostname>
1357 author: User Name <user@hostname>
1346 author: person
1358 author: person
1347 author: person
1359 author: person
1348 author: person
1360 author: person
1349 author: person
1361 author: person
1350 author: other@place
1362 author: other@place
1351 author: A. N. Other <other@place>
1363 author: A. N. Other <other@place>
1352 author: User Name <user@hostname>
1364 author: User Name <user@hostname>
1353 author--verbose: test
1365 author--verbose: test
1354 author--verbose: User Name <user@hostname>
1366 author--verbose: User Name <user@hostname>
1355 author--verbose: person
1367 author--verbose: person
1356 author--verbose: person
1368 author--verbose: person
1357 author--verbose: person
1369 author--verbose: person
1358 author--verbose: person
1370 author--verbose: person
1359 author--verbose: other@place
1371 author--verbose: other@place
1360 author--verbose: A. N. Other <other@place>
1372 author--verbose: A. N. Other <other@place>
1361 author--verbose: User Name <user@hostname>
1373 author--verbose: User Name <user@hostname>
1362 author--debug: test
1374 author--debug: test
1363 author--debug: User Name <user@hostname>
1375 author--debug: User Name <user@hostname>
1364 author--debug: person
1376 author--debug: person
1365 author--debug: person
1377 author--debug: person
1366 author--debug: person
1378 author--debug: person
1367 author--debug: person
1379 author--debug: person
1368 author--debug: other@place
1380 author--debug: other@place
1369 author--debug: A. N. Other <other@place>
1381 author--debug: A. N. Other <other@place>
1370 author--debug: User Name <user@hostname>
1382 author--debug: User Name <user@hostname>
1371 branch: default
1383 branch: default
1372 branch: default
1384 branch: default
1373 branch: default
1385 branch: default
1374 branch: default
1386 branch: default
1375 branch: foo
1387 branch: foo
1376 branch: default
1388 branch: default
1377 branch: default
1389 branch: default
1378 branch: default
1390 branch: default
1379 branch: default
1391 branch: default
1380 branch--verbose: default
1392 branch--verbose: default
1381 branch--verbose: default
1393 branch--verbose: default
1382 branch--verbose: default
1394 branch--verbose: default
1383 branch--verbose: default
1395 branch--verbose: default
1384 branch--verbose: foo
1396 branch--verbose: foo
1385 branch--verbose: default
1397 branch--verbose: default
1386 branch--verbose: default
1398 branch--verbose: default
1387 branch--verbose: default
1399 branch--verbose: default
1388 branch--verbose: default
1400 branch--verbose: default
1389 branch--debug: default
1401 branch--debug: default
1390 branch--debug: default
1402 branch--debug: default
1391 branch--debug: default
1403 branch--debug: default
1392 branch--debug: default
1404 branch--debug: default
1393 branch--debug: foo
1405 branch--debug: foo
1394 branch--debug: default
1406 branch--debug: default
1395 branch--debug: default
1407 branch--debug: default
1396 branch--debug: default
1408 branch--debug: default
1397 branch--debug: default
1409 branch--debug: default
1398 branches:
1410 branches:
1399 branches:
1411 branches:
1400 branches:
1412 branches:
1401 branches:
1413 branches:
1402 branches: foo
1414 branches: foo
1403 branches:
1415 branches:
1404 branches:
1416 branches:
1405 branches:
1417 branches:
1406 branches:
1418 branches:
1407 branches--verbose:
1419 branches--verbose:
1408 branches--verbose:
1420 branches--verbose:
1409 branches--verbose:
1421 branches--verbose:
1410 branches--verbose:
1422 branches--verbose:
1411 branches--verbose: foo
1423 branches--verbose: foo
1412 branches--verbose:
1424 branches--verbose:
1413 branches--verbose:
1425 branches--verbose:
1414 branches--verbose:
1426 branches--verbose:
1415 branches--verbose:
1427 branches--verbose:
1416 branches--debug:
1428 branches--debug:
1417 branches--debug:
1429 branches--debug:
1418 branches--debug:
1430 branches--debug:
1419 branches--debug:
1431 branches--debug:
1420 branches--debug: foo
1432 branches--debug: foo
1421 branches--debug:
1433 branches--debug:
1422 branches--debug:
1434 branches--debug:
1423 branches--debug:
1435 branches--debug:
1424 branches--debug:
1436 branches--debug:
1425 date: 1577872860.00
1437 date: 1577872860.00
1426 date: 1000000.00
1438 date: 1000000.00
1427 date: 1500001.00
1439 date: 1500001.00
1428 date: 1500000.00
1440 date: 1500000.00
1429 date: 1400000.00
1441 date: 1400000.00
1430 date: 1300000.00
1442 date: 1300000.00
1431 date: 1200000.00
1443 date: 1200000.00
1432 date: 1100000.00
1444 date: 1100000.00
1433 date: 1000000.00
1445 date: 1000000.00
1434 date--verbose: 1577872860.00
1446 date--verbose: 1577872860.00
1435 date--verbose: 1000000.00
1447 date--verbose: 1000000.00
1436 date--verbose: 1500001.00
1448 date--verbose: 1500001.00
1437 date--verbose: 1500000.00
1449 date--verbose: 1500000.00
1438 date--verbose: 1400000.00
1450 date--verbose: 1400000.00
1439 date--verbose: 1300000.00
1451 date--verbose: 1300000.00
1440 date--verbose: 1200000.00
1452 date--verbose: 1200000.00
1441 date--verbose: 1100000.00
1453 date--verbose: 1100000.00
1442 date--verbose: 1000000.00
1454 date--verbose: 1000000.00
1443 date--debug: 1577872860.00
1455 date--debug: 1577872860.00
1444 date--debug: 1000000.00
1456 date--debug: 1000000.00
1445 date--debug: 1500001.00
1457 date--debug: 1500001.00
1446 date--debug: 1500000.00
1458 date--debug: 1500000.00
1447 date--debug: 1400000.00
1459 date--debug: 1400000.00
1448 date--debug: 1300000.00
1460 date--debug: 1300000.00
1449 date--debug: 1200000.00
1461 date--debug: 1200000.00
1450 date--debug: 1100000.00
1462 date--debug: 1100000.00
1451 date--debug: 1000000.00
1463 date--debug: 1000000.00
1452 desc: third
1464 desc: third
1453 desc: second
1465 desc: second
1454 desc: merge
1466 desc: merge
1455 desc: new head
1467 desc: new head
1456 desc: new branch
1468 desc: new branch
1457 desc: no user, no domain
1469 desc: no user, no domain
1458 desc: no person
1470 desc: no person
1459 desc: other 1
1471 desc: other 1
1460 other 2
1472 other 2
1461
1473
1462 other 3
1474 other 3
1463 desc: line 1
1475 desc: line 1
1464 line 2
1476 line 2
1465 desc--verbose: third
1477 desc--verbose: third
1466 desc--verbose: second
1478 desc--verbose: second
1467 desc--verbose: merge
1479 desc--verbose: merge
1468 desc--verbose: new head
1480 desc--verbose: new head
1469 desc--verbose: new branch
1481 desc--verbose: new branch
1470 desc--verbose: no user, no domain
1482 desc--verbose: no user, no domain
1471 desc--verbose: no person
1483 desc--verbose: no person
1472 desc--verbose: other 1
1484 desc--verbose: other 1
1473 other 2
1485 other 2
1474
1486
1475 other 3
1487 other 3
1476 desc--verbose: line 1
1488 desc--verbose: line 1
1477 line 2
1489 line 2
1478 desc--debug: third
1490 desc--debug: third
1479 desc--debug: second
1491 desc--debug: second
1480 desc--debug: merge
1492 desc--debug: merge
1481 desc--debug: new head
1493 desc--debug: new head
1482 desc--debug: new branch
1494 desc--debug: new branch
1483 desc--debug: no user, no domain
1495 desc--debug: no user, no domain
1484 desc--debug: no person
1496 desc--debug: no person
1485 desc--debug: other 1
1497 desc--debug: other 1
1486 other 2
1498 other 2
1487
1499
1488 other 3
1500 other 3
1489 desc--debug: line 1
1501 desc--debug: line 1
1490 line 2
1502 line 2
1491 file_adds: fourth third
1503 file_adds: fourth third
1492 file_adds: second
1504 file_adds: second
1493 file_adds:
1505 file_adds:
1494 file_adds: d
1506 file_adds: d
1495 file_adds:
1507 file_adds:
1496 file_adds:
1508 file_adds:
1497 file_adds: c
1509 file_adds: c
1498 file_adds: b
1510 file_adds: b
1499 file_adds: a
1511 file_adds: a
1500 file_adds--verbose: fourth third
1512 file_adds--verbose: fourth third
1501 file_adds--verbose: second
1513 file_adds--verbose: second
1502 file_adds--verbose:
1514 file_adds--verbose:
1503 file_adds--verbose: d
1515 file_adds--verbose: d
1504 file_adds--verbose:
1516 file_adds--verbose:
1505 file_adds--verbose:
1517 file_adds--verbose:
1506 file_adds--verbose: c
1518 file_adds--verbose: c
1507 file_adds--verbose: b
1519 file_adds--verbose: b
1508 file_adds--verbose: a
1520 file_adds--verbose: a
1509 file_adds--debug: fourth third
1521 file_adds--debug: fourth third
1510 file_adds--debug: second
1522 file_adds--debug: second
1511 file_adds--debug:
1523 file_adds--debug:
1512 file_adds--debug: d
1524 file_adds--debug: d
1513 file_adds--debug:
1525 file_adds--debug:
1514 file_adds--debug:
1526 file_adds--debug:
1515 file_adds--debug: c
1527 file_adds--debug: c
1516 file_adds--debug: b
1528 file_adds--debug: b
1517 file_adds--debug: a
1529 file_adds--debug: a
1518 file_dels: second
1530 file_dels: second
1519 file_dels:
1531 file_dels:
1520 file_dels:
1532 file_dels:
1521 file_dels:
1533 file_dels:
1522 file_dels:
1534 file_dels:
1523 file_dels:
1535 file_dels:
1524 file_dels:
1536 file_dels:
1525 file_dels:
1537 file_dels:
1526 file_dels:
1538 file_dels:
1527 file_dels--verbose: second
1539 file_dels--verbose: second
1528 file_dels--verbose:
1540 file_dels--verbose:
1529 file_dels--verbose:
1541 file_dels--verbose:
1530 file_dels--verbose:
1542 file_dels--verbose:
1531 file_dels--verbose:
1543 file_dels--verbose:
1532 file_dels--verbose:
1544 file_dels--verbose:
1533 file_dels--verbose:
1545 file_dels--verbose:
1534 file_dels--verbose:
1546 file_dels--verbose:
1535 file_dels--verbose:
1547 file_dels--verbose:
1536 file_dels--debug: second
1548 file_dels--debug: second
1537 file_dels--debug:
1549 file_dels--debug:
1538 file_dels--debug:
1550 file_dels--debug:
1539 file_dels--debug:
1551 file_dels--debug:
1540 file_dels--debug:
1552 file_dels--debug:
1541 file_dels--debug:
1553 file_dels--debug:
1542 file_dels--debug:
1554 file_dels--debug:
1543 file_dels--debug:
1555 file_dels--debug:
1544 file_dels--debug:
1556 file_dels--debug:
1545 file_mods:
1557 file_mods:
1546 file_mods:
1558 file_mods:
1547 file_mods:
1559 file_mods:
1548 file_mods:
1560 file_mods:
1549 file_mods:
1561 file_mods:
1550 file_mods: c
1562 file_mods: c
1551 file_mods:
1563 file_mods:
1552 file_mods:
1564 file_mods:
1553 file_mods:
1565 file_mods:
1554 file_mods--verbose:
1566 file_mods--verbose:
1555 file_mods--verbose:
1567 file_mods--verbose:
1556 file_mods--verbose:
1568 file_mods--verbose:
1557 file_mods--verbose:
1569 file_mods--verbose:
1558 file_mods--verbose:
1570 file_mods--verbose:
1559 file_mods--verbose: c
1571 file_mods--verbose: c
1560 file_mods--verbose:
1572 file_mods--verbose:
1561 file_mods--verbose:
1573 file_mods--verbose:
1562 file_mods--verbose:
1574 file_mods--verbose:
1563 file_mods--debug:
1575 file_mods--debug:
1564 file_mods--debug:
1576 file_mods--debug:
1565 file_mods--debug:
1577 file_mods--debug:
1566 file_mods--debug:
1578 file_mods--debug:
1567 file_mods--debug:
1579 file_mods--debug:
1568 file_mods--debug: c
1580 file_mods--debug: c
1569 file_mods--debug:
1581 file_mods--debug:
1570 file_mods--debug:
1582 file_mods--debug:
1571 file_mods--debug:
1583 file_mods--debug:
1572 file_copies: fourth (second)
1584 file_copies: fourth (second)
1573 file_copies:
1585 file_copies:
1574 file_copies:
1586 file_copies:
1575 file_copies:
1587 file_copies:
1576 file_copies:
1588 file_copies:
1577 file_copies:
1589 file_copies:
1578 file_copies:
1590 file_copies:
1579 file_copies:
1591 file_copies:
1580 file_copies:
1592 file_copies:
1581 file_copies--verbose: fourth (second)
1593 file_copies--verbose: fourth (second)
1582 file_copies--verbose:
1594 file_copies--verbose:
1583 file_copies--verbose:
1595 file_copies--verbose:
1584 file_copies--verbose:
1596 file_copies--verbose:
1585 file_copies--verbose:
1597 file_copies--verbose:
1586 file_copies--verbose:
1598 file_copies--verbose:
1587 file_copies--verbose:
1599 file_copies--verbose:
1588 file_copies--verbose:
1600 file_copies--verbose:
1589 file_copies--verbose:
1601 file_copies--verbose:
1590 file_copies--debug: fourth (second)
1602 file_copies--debug: fourth (second)
1591 file_copies--debug:
1603 file_copies--debug:
1592 file_copies--debug:
1604 file_copies--debug:
1593 file_copies--debug:
1605 file_copies--debug:
1594 file_copies--debug:
1606 file_copies--debug:
1595 file_copies--debug:
1607 file_copies--debug:
1596 file_copies--debug:
1608 file_copies--debug:
1597 file_copies--debug:
1609 file_copies--debug:
1598 file_copies--debug:
1610 file_copies--debug:
1599 file_copies_switch:
1611 file_copies_switch:
1600 file_copies_switch:
1612 file_copies_switch:
1601 file_copies_switch:
1613 file_copies_switch:
1602 file_copies_switch:
1614 file_copies_switch:
1603 file_copies_switch:
1615 file_copies_switch:
1604 file_copies_switch:
1616 file_copies_switch:
1605 file_copies_switch:
1617 file_copies_switch:
1606 file_copies_switch:
1618 file_copies_switch:
1607 file_copies_switch:
1619 file_copies_switch:
1608 file_copies_switch--verbose:
1620 file_copies_switch--verbose:
1609 file_copies_switch--verbose:
1621 file_copies_switch--verbose:
1610 file_copies_switch--verbose:
1622 file_copies_switch--verbose:
1611 file_copies_switch--verbose:
1623 file_copies_switch--verbose:
1612 file_copies_switch--verbose:
1624 file_copies_switch--verbose:
1613 file_copies_switch--verbose:
1625 file_copies_switch--verbose:
1614 file_copies_switch--verbose:
1626 file_copies_switch--verbose:
1615 file_copies_switch--verbose:
1627 file_copies_switch--verbose:
1616 file_copies_switch--verbose:
1628 file_copies_switch--verbose:
1617 file_copies_switch--debug:
1629 file_copies_switch--debug:
1618 file_copies_switch--debug:
1630 file_copies_switch--debug:
1619 file_copies_switch--debug:
1631 file_copies_switch--debug:
1620 file_copies_switch--debug:
1632 file_copies_switch--debug:
1621 file_copies_switch--debug:
1633 file_copies_switch--debug:
1622 file_copies_switch--debug:
1634 file_copies_switch--debug:
1623 file_copies_switch--debug:
1635 file_copies_switch--debug:
1624 file_copies_switch--debug:
1636 file_copies_switch--debug:
1625 file_copies_switch--debug:
1637 file_copies_switch--debug:
1626 files: fourth second third
1638 files: fourth second third
1627 files: second
1639 files: second
1628 files:
1640 files:
1629 files: d
1641 files: d
1630 files:
1642 files:
1631 files: c
1643 files: c
1632 files: c
1644 files: c
1633 files: b
1645 files: b
1634 files: a
1646 files: a
1635 files--verbose: fourth second third
1647 files--verbose: fourth second third
1636 files--verbose: second
1648 files--verbose: second
1637 files--verbose:
1649 files--verbose:
1638 files--verbose: d
1650 files--verbose: d
1639 files--verbose:
1651 files--verbose:
1640 files--verbose: c
1652 files--verbose: c
1641 files--verbose: c
1653 files--verbose: c
1642 files--verbose: b
1654 files--verbose: b
1643 files--verbose: a
1655 files--verbose: a
1644 files--debug: fourth second third
1656 files--debug: fourth second third
1645 files--debug: second
1657 files--debug: second
1646 files--debug:
1658 files--debug:
1647 files--debug: d
1659 files--debug: d
1648 files--debug:
1660 files--debug:
1649 files--debug: c
1661 files--debug: c
1650 files--debug: c
1662 files--debug: c
1651 files--debug: b
1663 files--debug: b
1652 files--debug: a
1664 files--debug: a
1653 manifest: 6:94961b75a2da
1665 manifest: 6:94961b75a2da
1654 manifest: 5:f2dbc354b94e
1666 manifest: 5:f2dbc354b94e
1655 manifest: 4:4dc3def4f9b4
1667 manifest: 4:4dc3def4f9b4
1656 manifest: 4:4dc3def4f9b4
1668 manifest: 4:4dc3def4f9b4
1657 manifest: 3:cb5a1327723b
1669 manifest: 3:cb5a1327723b
1658 manifest: 3:cb5a1327723b
1670 manifest: 3:cb5a1327723b
1659 manifest: 2:6e0e82995c35
1671 manifest: 2:6e0e82995c35
1660 manifest: 1:4e8d705b1e53
1672 manifest: 1:4e8d705b1e53
1661 manifest: 0:a0c8bcbbb45c
1673 manifest: 0:a0c8bcbbb45c
1662 manifest--verbose: 6:94961b75a2da
1674 manifest--verbose: 6:94961b75a2da
1663 manifest--verbose: 5:f2dbc354b94e
1675 manifest--verbose: 5:f2dbc354b94e
1664 manifest--verbose: 4:4dc3def4f9b4
1676 manifest--verbose: 4:4dc3def4f9b4
1665 manifest--verbose: 4:4dc3def4f9b4
1677 manifest--verbose: 4:4dc3def4f9b4
1666 manifest--verbose: 3:cb5a1327723b
1678 manifest--verbose: 3:cb5a1327723b
1667 manifest--verbose: 3:cb5a1327723b
1679 manifest--verbose: 3:cb5a1327723b
1668 manifest--verbose: 2:6e0e82995c35
1680 manifest--verbose: 2:6e0e82995c35
1669 manifest--verbose: 1:4e8d705b1e53
1681 manifest--verbose: 1:4e8d705b1e53
1670 manifest--verbose: 0:a0c8bcbbb45c
1682 manifest--verbose: 0:a0c8bcbbb45c
1671 manifest--debug: 6:94961b75a2da554b4df6fb599e5bfc7d48de0c64
1683 manifest--debug: 6:94961b75a2da554b4df6fb599e5bfc7d48de0c64
1672 manifest--debug: 5:f2dbc354b94e5ec0b4f10680ee0cee816101d0bf
1684 manifest--debug: 5:f2dbc354b94e5ec0b4f10680ee0cee816101d0bf
1673 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1685 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1674 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1686 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1675 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1687 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1676 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1688 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1677 manifest--debug: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
1689 manifest--debug: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
1678 manifest--debug: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
1690 manifest--debug: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
1679 manifest--debug: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
1691 manifest--debug: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
1680 node: 95c24699272ef57d062b8bccc32c878bf841784a
1692 node: 95c24699272ef57d062b8bccc32c878bf841784a
1681 node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1693 node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1682 node: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1694 node: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1683 node: 13207e5a10d9fd28ec424934298e176197f2c67f
1695 node: 13207e5a10d9fd28ec424934298e176197f2c67f
1684 node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1696 node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1685 node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1697 node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1686 node: 97054abb4ab824450e9164180baf491ae0078465
1698 node: 97054abb4ab824450e9164180baf491ae0078465
1687 node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1699 node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1688 node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1700 node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1689 node--verbose: 95c24699272ef57d062b8bccc32c878bf841784a
1701 node--verbose: 95c24699272ef57d062b8bccc32c878bf841784a
1690 node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1702 node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1691 node--verbose: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1703 node--verbose: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1692 node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1704 node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1693 node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1705 node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1694 node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1706 node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1695 node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1707 node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1696 node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1708 node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1697 node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1709 node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1698 node--debug: 95c24699272ef57d062b8bccc32c878bf841784a
1710 node--debug: 95c24699272ef57d062b8bccc32c878bf841784a
1699 node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1711 node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1700 node--debug: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1712 node--debug: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1701 node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1713 node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1702 node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1714 node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1703 node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1715 node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1704 node--debug: 97054abb4ab824450e9164180baf491ae0078465
1716 node--debug: 97054abb4ab824450e9164180baf491ae0078465
1705 node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1717 node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1706 node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1718 node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1707 parents:
1719 parents:
1708 parents: -1:000000000000
1720 parents: -1:000000000000
1709 parents: 5:13207e5a10d9 4:bbe44766e73d
1721 parents: 5:13207e5a10d9 4:bbe44766e73d
1710 parents: 3:10e46f2dcbf4
1722 parents: 3:10e46f2dcbf4
1711 parents:
1723 parents:
1712 parents:
1724 parents:
1713 parents:
1725 parents:
1714 parents:
1726 parents:
1715 parents:
1727 parents:
1716 parents--verbose:
1728 parents--verbose:
1717 parents--verbose: -1:000000000000
1729 parents--verbose: -1:000000000000
1718 parents--verbose: 5:13207e5a10d9 4:bbe44766e73d
1730 parents--verbose: 5:13207e5a10d9 4:bbe44766e73d
1719 parents--verbose: 3:10e46f2dcbf4
1731 parents--verbose: 3:10e46f2dcbf4
1720 parents--verbose:
1732 parents--verbose:
1721 parents--verbose:
1733 parents--verbose:
1722 parents--verbose:
1734 parents--verbose:
1723 parents--verbose:
1735 parents--verbose:
1724 parents--verbose:
1736 parents--verbose:
1725 parents--debug: 7:29114dbae42b9f078cf2714dbe3a86bba8ec7453 -1:0000000000000000000000000000000000000000
1737 parents--debug: 7:29114dbae42b9f078cf2714dbe3a86bba8ec7453 -1:0000000000000000000000000000000000000000
1726 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1738 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1727 parents--debug: 5:13207e5a10d9fd28ec424934298e176197f2c67f 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
1739 parents--debug: 5:13207e5a10d9fd28ec424934298e176197f2c67f 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
1728 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1740 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1729 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1741 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1730 parents--debug: 2:97054abb4ab824450e9164180baf491ae0078465 -1:0000000000000000000000000000000000000000
1742 parents--debug: 2:97054abb4ab824450e9164180baf491ae0078465 -1:0000000000000000000000000000000000000000
1731 parents--debug: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965 -1:0000000000000000000000000000000000000000
1743 parents--debug: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965 -1:0000000000000000000000000000000000000000
1732 parents--debug: 0:1e4e1b8f71e05681d422154f5421e385fec3454f -1:0000000000000000000000000000000000000000
1744 parents--debug: 0:1e4e1b8f71e05681d422154f5421e385fec3454f -1:0000000000000000000000000000000000000000
1733 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1745 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1734 rev: 8
1746 rev: 8
1735 rev: 7
1747 rev: 7
1736 rev: 6
1748 rev: 6
1737 rev: 5
1749 rev: 5
1738 rev: 4
1750 rev: 4
1739 rev: 3
1751 rev: 3
1740 rev: 2
1752 rev: 2
1741 rev: 1
1753 rev: 1
1742 rev: 0
1754 rev: 0
1743 rev--verbose: 8
1755 rev--verbose: 8
1744 rev--verbose: 7
1756 rev--verbose: 7
1745 rev--verbose: 6
1757 rev--verbose: 6
1746 rev--verbose: 5
1758 rev--verbose: 5
1747 rev--verbose: 4
1759 rev--verbose: 4
1748 rev--verbose: 3
1760 rev--verbose: 3
1749 rev--verbose: 2
1761 rev--verbose: 2
1750 rev--verbose: 1
1762 rev--verbose: 1
1751 rev--verbose: 0
1763 rev--verbose: 0
1752 rev--debug: 8
1764 rev--debug: 8
1753 rev--debug: 7
1765 rev--debug: 7
1754 rev--debug: 6
1766 rev--debug: 6
1755 rev--debug: 5
1767 rev--debug: 5
1756 rev--debug: 4
1768 rev--debug: 4
1757 rev--debug: 3
1769 rev--debug: 3
1758 rev--debug: 2
1770 rev--debug: 2
1759 rev--debug: 1
1771 rev--debug: 1
1760 rev--debug: 0
1772 rev--debug: 0
1761 tags: tip
1773 tags: tip
1762 tags:
1774 tags:
1763 tags:
1775 tags:
1764 tags:
1776 tags:
1765 tags:
1777 tags:
1766 tags:
1778 tags:
1767 tags:
1779 tags:
1768 tags:
1780 tags:
1769 tags:
1781 tags:
1770 tags--verbose: tip
1782 tags--verbose: tip
1771 tags--verbose:
1783 tags--verbose:
1772 tags--verbose:
1784 tags--verbose:
1773 tags--verbose:
1785 tags--verbose:
1774 tags--verbose:
1786 tags--verbose:
1775 tags--verbose:
1787 tags--verbose:
1776 tags--verbose:
1788 tags--verbose:
1777 tags--verbose:
1789 tags--verbose:
1778 tags--verbose:
1790 tags--verbose:
1779 tags--debug: tip
1791 tags--debug: tip
1780 tags--debug:
1792 tags--debug:
1781 tags--debug:
1793 tags--debug:
1782 tags--debug:
1794 tags--debug:
1783 tags--debug:
1795 tags--debug:
1784 tags--debug:
1796 tags--debug:
1785 tags--debug:
1797 tags--debug:
1786 tags--debug:
1798 tags--debug:
1787 tags--debug:
1799 tags--debug:
1788 diffstat: 3: +2/-1
1800 diffstat: 3: +2/-1
1789 diffstat: 1: +1/-0
1801 diffstat: 1: +1/-0
1790 diffstat: 0: +0/-0
1802 diffstat: 0: +0/-0
1791 diffstat: 1: +1/-0
1803 diffstat: 1: +1/-0
1792 diffstat: 0: +0/-0
1804 diffstat: 0: +0/-0
1793 diffstat: 1: +1/-0
1805 diffstat: 1: +1/-0
1794 diffstat: 1: +4/-0
1806 diffstat: 1: +4/-0
1795 diffstat: 1: +2/-0
1807 diffstat: 1: +2/-0
1796 diffstat: 1: +1/-0
1808 diffstat: 1: +1/-0
1797 diffstat--verbose: 3: +2/-1
1809 diffstat--verbose: 3: +2/-1
1798 diffstat--verbose: 1: +1/-0
1810 diffstat--verbose: 1: +1/-0
1799 diffstat--verbose: 0: +0/-0
1811 diffstat--verbose: 0: +0/-0
1800 diffstat--verbose: 1: +1/-0
1812 diffstat--verbose: 1: +1/-0
1801 diffstat--verbose: 0: +0/-0
1813 diffstat--verbose: 0: +0/-0
1802 diffstat--verbose: 1: +1/-0
1814 diffstat--verbose: 1: +1/-0
1803 diffstat--verbose: 1: +4/-0
1815 diffstat--verbose: 1: +4/-0
1804 diffstat--verbose: 1: +2/-0
1816 diffstat--verbose: 1: +2/-0
1805 diffstat--verbose: 1: +1/-0
1817 diffstat--verbose: 1: +1/-0
1806 diffstat--debug: 3: +2/-1
1818 diffstat--debug: 3: +2/-1
1807 diffstat--debug: 1: +1/-0
1819 diffstat--debug: 1: +1/-0
1808 diffstat--debug: 0: +0/-0
1820 diffstat--debug: 0: +0/-0
1809 diffstat--debug: 1: +1/-0
1821 diffstat--debug: 1: +1/-0
1810 diffstat--debug: 0: +0/-0
1822 diffstat--debug: 0: +0/-0
1811 diffstat--debug: 1: +1/-0
1823 diffstat--debug: 1: +1/-0
1812 diffstat--debug: 1: +4/-0
1824 diffstat--debug: 1: +4/-0
1813 diffstat--debug: 1: +2/-0
1825 diffstat--debug: 1: +2/-0
1814 diffstat--debug: 1: +1/-0
1826 diffstat--debug: 1: +1/-0
1815 extras: branch=default
1827 extras: branch=default
1816 extras: branch=default
1828 extras: branch=default
1817 extras: branch=default
1829 extras: branch=default
1818 extras: branch=default
1830 extras: branch=default
1819 extras: branch=foo
1831 extras: branch=foo
1820 extras: branch=default
1832 extras: branch=default
1821 extras: branch=default
1833 extras: branch=default
1822 extras: branch=default
1834 extras: branch=default
1823 extras: branch=default
1835 extras: branch=default
1824 extras--verbose: branch=default
1836 extras--verbose: branch=default
1825 extras--verbose: branch=default
1837 extras--verbose: branch=default
1826 extras--verbose: branch=default
1838 extras--verbose: branch=default
1827 extras--verbose: branch=default
1839 extras--verbose: branch=default
1828 extras--verbose: branch=foo
1840 extras--verbose: branch=foo
1829 extras--verbose: branch=default
1841 extras--verbose: branch=default
1830 extras--verbose: branch=default
1842 extras--verbose: branch=default
1831 extras--verbose: branch=default
1843 extras--verbose: branch=default
1832 extras--verbose: branch=default
1844 extras--verbose: branch=default
1833 extras--debug: branch=default
1845 extras--debug: branch=default
1834 extras--debug: branch=default
1846 extras--debug: branch=default
1835 extras--debug: branch=default
1847 extras--debug: branch=default
1836 extras--debug: branch=default
1848 extras--debug: branch=default
1837 extras--debug: branch=foo
1849 extras--debug: branch=foo
1838 extras--debug: branch=default
1850 extras--debug: branch=default
1839 extras--debug: branch=default
1851 extras--debug: branch=default
1840 extras--debug: branch=default
1852 extras--debug: branch=default
1841 extras--debug: branch=default
1853 extras--debug: branch=default
1842 p1rev: 7
1854 p1rev: 7
1843 p1rev: -1
1855 p1rev: -1
1844 p1rev: 5
1856 p1rev: 5
1845 p1rev: 3
1857 p1rev: 3
1846 p1rev: 3
1858 p1rev: 3
1847 p1rev: 2
1859 p1rev: 2
1848 p1rev: 1
1860 p1rev: 1
1849 p1rev: 0
1861 p1rev: 0
1850 p1rev: -1
1862 p1rev: -1
1851 p1rev--verbose: 7
1863 p1rev--verbose: 7
1852 p1rev--verbose: -1
1864 p1rev--verbose: -1
1853 p1rev--verbose: 5
1865 p1rev--verbose: 5
1854 p1rev--verbose: 3
1866 p1rev--verbose: 3
1855 p1rev--verbose: 3
1867 p1rev--verbose: 3
1856 p1rev--verbose: 2
1868 p1rev--verbose: 2
1857 p1rev--verbose: 1
1869 p1rev--verbose: 1
1858 p1rev--verbose: 0
1870 p1rev--verbose: 0
1859 p1rev--verbose: -1
1871 p1rev--verbose: -1
1860 p1rev--debug: 7
1872 p1rev--debug: 7
1861 p1rev--debug: -1
1873 p1rev--debug: -1
1862 p1rev--debug: 5
1874 p1rev--debug: 5
1863 p1rev--debug: 3
1875 p1rev--debug: 3
1864 p1rev--debug: 3
1876 p1rev--debug: 3
1865 p1rev--debug: 2
1877 p1rev--debug: 2
1866 p1rev--debug: 1
1878 p1rev--debug: 1
1867 p1rev--debug: 0
1879 p1rev--debug: 0
1868 p1rev--debug: -1
1880 p1rev--debug: -1
1869 p2rev: -1
1881 p2rev: -1
1870 p2rev: -1
1882 p2rev: -1
1871 p2rev: 4
1883 p2rev: 4
1872 p2rev: -1
1884 p2rev: -1
1873 p2rev: -1
1885 p2rev: -1
1874 p2rev: -1
1886 p2rev: -1
1875 p2rev: -1
1887 p2rev: -1
1876 p2rev: -1
1888 p2rev: -1
1877 p2rev: -1
1889 p2rev: -1
1878 p2rev--verbose: -1
1890 p2rev--verbose: -1
1879 p2rev--verbose: -1
1891 p2rev--verbose: -1
1880 p2rev--verbose: 4
1892 p2rev--verbose: 4
1881 p2rev--verbose: -1
1893 p2rev--verbose: -1
1882 p2rev--verbose: -1
1894 p2rev--verbose: -1
1883 p2rev--verbose: -1
1895 p2rev--verbose: -1
1884 p2rev--verbose: -1
1896 p2rev--verbose: -1
1885 p2rev--verbose: -1
1897 p2rev--verbose: -1
1886 p2rev--verbose: -1
1898 p2rev--verbose: -1
1887 p2rev--debug: -1
1899 p2rev--debug: -1
1888 p2rev--debug: -1
1900 p2rev--debug: -1
1889 p2rev--debug: 4
1901 p2rev--debug: 4
1890 p2rev--debug: -1
1902 p2rev--debug: -1
1891 p2rev--debug: -1
1903 p2rev--debug: -1
1892 p2rev--debug: -1
1904 p2rev--debug: -1
1893 p2rev--debug: -1
1905 p2rev--debug: -1
1894 p2rev--debug: -1
1906 p2rev--debug: -1
1895 p2rev--debug: -1
1907 p2rev--debug: -1
1896 p1node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1908 p1node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1897 p1node: 0000000000000000000000000000000000000000
1909 p1node: 0000000000000000000000000000000000000000
1898 p1node: 13207e5a10d9fd28ec424934298e176197f2c67f
1910 p1node: 13207e5a10d9fd28ec424934298e176197f2c67f
1899 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1911 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1900 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1912 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1901 p1node: 97054abb4ab824450e9164180baf491ae0078465
1913 p1node: 97054abb4ab824450e9164180baf491ae0078465
1902 p1node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1914 p1node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1903 p1node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1915 p1node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1904 p1node: 0000000000000000000000000000000000000000
1916 p1node: 0000000000000000000000000000000000000000
1905 p1node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1917 p1node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1906 p1node--verbose: 0000000000000000000000000000000000000000
1918 p1node--verbose: 0000000000000000000000000000000000000000
1907 p1node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1919 p1node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1908 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1920 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1909 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1921 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1910 p1node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1922 p1node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1911 p1node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1923 p1node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1912 p1node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1924 p1node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1913 p1node--verbose: 0000000000000000000000000000000000000000
1925 p1node--verbose: 0000000000000000000000000000000000000000
1914 p1node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1926 p1node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1915 p1node--debug: 0000000000000000000000000000000000000000
1927 p1node--debug: 0000000000000000000000000000000000000000
1916 p1node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1928 p1node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1917 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1929 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1918 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1930 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1919 p1node--debug: 97054abb4ab824450e9164180baf491ae0078465
1931 p1node--debug: 97054abb4ab824450e9164180baf491ae0078465
1920 p1node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1932 p1node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1921 p1node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1933 p1node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1922 p1node--debug: 0000000000000000000000000000000000000000
1934 p1node--debug: 0000000000000000000000000000000000000000
1923 p2node: 0000000000000000000000000000000000000000
1935 p2node: 0000000000000000000000000000000000000000
1924 p2node: 0000000000000000000000000000000000000000
1936 p2node: 0000000000000000000000000000000000000000
1925 p2node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1937 p2node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1926 p2node: 0000000000000000000000000000000000000000
1938 p2node: 0000000000000000000000000000000000000000
1927 p2node: 0000000000000000000000000000000000000000
1939 p2node: 0000000000000000000000000000000000000000
1928 p2node: 0000000000000000000000000000000000000000
1940 p2node: 0000000000000000000000000000000000000000
1929 p2node: 0000000000000000000000000000000000000000
1941 p2node: 0000000000000000000000000000000000000000
1930 p2node: 0000000000000000000000000000000000000000
1942 p2node: 0000000000000000000000000000000000000000
1931 p2node: 0000000000000000000000000000000000000000
1943 p2node: 0000000000000000000000000000000000000000
1932 p2node--verbose: 0000000000000000000000000000000000000000
1944 p2node--verbose: 0000000000000000000000000000000000000000
1933 p2node--verbose: 0000000000000000000000000000000000000000
1945 p2node--verbose: 0000000000000000000000000000000000000000
1934 p2node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1946 p2node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1935 p2node--verbose: 0000000000000000000000000000000000000000
1947 p2node--verbose: 0000000000000000000000000000000000000000
1936 p2node--verbose: 0000000000000000000000000000000000000000
1948 p2node--verbose: 0000000000000000000000000000000000000000
1937 p2node--verbose: 0000000000000000000000000000000000000000
1949 p2node--verbose: 0000000000000000000000000000000000000000
1938 p2node--verbose: 0000000000000000000000000000000000000000
1950 p2node--verbose: 0000000000000000000000000000000000000000
1939 p2node--verbose: 0000000000000000000000000000000000000000
1951 p2node--verbose: 0000000000000000000000000000000000000000
1940 p2node--verbose: 0000000000000000000000000000000000000000
1952 p2node--verbose: 0000000000000000000000000000000000000000
1941 p2node--debug: 0000000000000000000000000000000000000000
1953 p2node--debug: 0000000000000000000000000000000000000000
1942 p2node--debug: 0000000000000000000000000000000000000000
1954 p2node--debug: 0000000000000000000000000000000000000000
1943 p2node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1955 p2node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1944 p2node--debug: 0000000000000000000000000000000000000000
1956 p2node--debug: 0000000000000000000000000000000000000000
1945 p2node--debug: 0000000000000000000000000000000000000000
1957 p2node--debug: 0000000000000000000000000000000000000000
1946 p2node--debug: 0000000000000000000000000000000000000000
1958 p2node--debug: 0000000000000000000000000000000000000000
1947 p2node--debug: 0000000000000000000000000000000000000000
1959 p2node--debug: 0000000000000000000000000000000000000000
1948 p2node--debug: 0000000000000000000000000000000000000000
1960 p2node--debug: 0000000000000000000000000000000000000000
1949 p2node--debug: 0000000000000000000000000000000000000000
1961 p2node--debug: 0000000000000000000000000000000000000000
1950
1962
1951 Filters work:
1963 Filters work:
1952
1964
1953 $ hg log --template '{author|domain}\n'
1965 $ hg log --template '{author|domain}\n'
1954
1966
1955 hostname
1967 hostname
1956
1968
1957
1969
1958
1970
1959
1971
1960 place
1972 place
1961 place
1973 place
1962 hostname
1974 hostname
1963
1975
1964 $ hg log --template '{author|person}\n'
1976 $ hg log --template '{author|person}\n'
1965 test
1977 test
1966 User Name
1978 User Name
1967 person
1979 person
1968 person
1980 person
1969 person
1981 person
1970 person
1982 person
1971 other
1983 other
1972 A. N. Other
1984 A. N. Other
1973 User Name
1985 User Name
1974
1986
1975 $ hg log --template '{author|user}\n'
1987 $ hg log --template '{author|user}\n'
1976 test
1988 test
1977 user
1989 user
1978 person
1990 person
1979 person
1991 person
1980 person
1992 person
1981 person
1993 person
1982 other
1994 other
1983 other
1995 other
1984 user
1996 user
1985
1997
1986 $ hg log --template '{date|date}\n'
1998 $ hg log --template '{date|date}\n'
1987 Wed Jan 01 10:01:00 2020 +0000
1999 Wed Jan 01 10:01:00 2020 +0000
1988 Mon Jan 12 13:46:40 1970 +0000
2000 Mon Jan 12 13:46:40 1970 +0000
1989 Sun Jan 18 08:40:01 1970 +0000
2001 Sun Jan 18 08:40:01 1970 +0000
1990 Sun Jan 18 08:40:00 1970 +0000
2002 Sun Jan 18 08:40:00 1970 +0000
1991 Sat Jan 17 04:53:20 1970 +0000
2003 Sat Jan 17 04:53:20 1970 +0000
1992 Fri Jan 16 01:06:40 1970 +0000
2004 Fri Jan 16 01:06:40 1970 +0000
1993 Wed Jan 14 21:20:00 1970 +0000
2005 Wed Jan 14 21:20:00 1970 +0000
1994 Tue Jan 13 17:33:20 1970 +0000
2006 Tue Jan 13 17:33:20 1970 +0000
1995 Mon Jan 12 13:46:40 1970 +0000
2007 Mon Jan 12 13:46:40 1970 +0000
1996
2008
1997 $ hg log --template '{date|isodate}\n'
2009 $ hg log --template '{date|isodate}\n'
1998 2020-01-01 10:01 +0000
2010 2020-01-01 10:01 +0000
1999 1970-01-12 13:46 +0000
2011 1970-01-12 13:46 +0000
2000 1970-01-18 08:40 +0000
2012 1970-01-18 08:40 +0000
2001 1970-01-18 08:40 +0000
2013 1970-01-18 08:40 +0000
2002 1970-01-17 04:53 +0000
2014 1970-01-17 04:53 +0000
2003 1970-01-16 01:06 +0000
2015 1970-01-16 01:06 +0000
2004 1970-01-14 21:20 +0000
2016 1970-01-14 21:20 +0000
2005 1970-01-13 17:33 +0000
2017 1970-01-13 17:33 +0000
2006 1970-01-12 13:46 +0000
2018 1970-01-12 13:46 +0000
2007
2019
2008 $ hg log --template '{date|isodatesec}\n'
2020 $ hg log --template '{date|isodatesec}\n'
2009 2020-01-01 10:01:00 +0000
2021 2020-01-01 10:01:00 +0000
2010 1970-01-12 13:46:40 +0000
2022 1970-01-12 13:46:40 +0000
2011 1970-01-18 08:40:01 +0000
2023 1970-01-18 08:40:01 +0000
2012 1970-01-18 08:40:00 +0000
2024 1970-01-18 08:40:00 +0000
2013 1970-01-17 04:53:20 +0000
2025 1970-01-17 04:53:20 +0000
2014 1970-01-16 01:06:40 +0000
2026 1970-01-16 01:06:40 +0000
2015 1970-01-14 21:20:00 +0000
2027 1970-01-14 21:20:00 +0000
2016 1970-01-13 17:33:20 +0000
2028 1970-01-13 17:33:20 +0000
2017 1970-01-12 13:46:40 +0000
2029 1970-01-12 13:46:40 +0000
2018
2030
2019 $ hg log --template '{date|rfc822date}\n'
2031 $ hg log --template '{date|rfc822date}\n'
2020 Wed, 01 Jan 2020 10:01:00 +0000
2032 Wed, 01 Jan 2020 10:01:00 +0000
2021 Mon, 12 Jan 1970 13:46:40 +0000
2033 Mon, 12 Jan 1970 13:46:40 +0000
2022 Sun, 18 Jan 1970 08:40:01 +0000
2034 Sun, 18 Jan 1970 08:40:01 +0000
2023 Sun, 18 Jan 1970 08:40:00 +0000
2035 Sun, 18 Jan 1970 08:40:00 +0000
2024 Sat, 17 Jan 1970 04:53:20 +0000
2036 Sat, 17 Jan 1970 04:53:20 +0000
2025 Fri, 16 Jan 1970 01:06:40 +0000
2037 Fri, 16 Jan 1970 01:06:40 +0000
2026 Wed, 14 Jan 1970 21:20:00 +0000
2038 Wed, 14 Jan 1970 21:20:00 +0000
2027 Tue, 13 Jan 1970 17:33:20 +0000
2039 Tue, 13 Jan 1970 17:33:20 +0000
2028 Mon, 12 Jan 1970 13:46:40 +0000
2040 Mon, 12 Jan 1970 13:46:40 +0000
2029
2041
2030 $ hg log --template '{desc|firstline}\n'
2042 $ hg log --template '{desc|firstline}\n'
2031 third
2043 third
2032 second
2044 second
2033 merge
2045 merge
2034 new head
2046 new head
2035 new branch
2047 new branch
2036 no user, no domain
2048 no user, no domain
2037 no person
2049 no person
2038 other 1
2050 other 1
2039 line 1
2051 line 1
2040
2052
2041 $ hg log --template '{node|short}\n'
2053 $ hg log --template '{node|short}\n'
2042 95c24699272e
2054 95c24699272e
2043 29114dbae42b
2055 29114dbae42b
2044 d41e714fe50d
2056 d41e714fe50d
2045 13207e5a10d9
2057 13207e5a10d9
2046 bbe44766e73d
2058 bbe44766e73d
2047 10e46f2dcbf4
2059 10e46f2dcbf4
2048 97054abb4ab8
2060 97054abb4ab8
2049 b608e9d1a3f0
2061 b608e9d1a3f0
2050 1e4e1b8f71e0
2062 1e4e1b8f71e0
2051
2063
2052 $ hg log --template '<changeset author="{author|xmlescape}"/>\n'
2064 $ hg log --template '<changeset author="{author|xmlescape}"/>\n'
2053 <changeset author="test"/>
2065 <changeset author="test"/>
2054 <changeset author="User Name &lt;user@hostname&gt;"/>
2066 <changeset author="User Name &lt;user@hostname&gt;"/>
2055 <changeset author="person"/>
2067 <changeset author="person"/>
2056 <changeset author="person"/>
2068 <changeset author="person"/>
2057 <changeset author="person"/>
2069 <changeset author="person"/>
2058 <changeset author="person"/>
2070 <changeset author="person"/>
2059 <changeset author="other@place"/>
2071 <changeset author="other@place"/>
2060 <changeset author="A. N. Other &lt;other@place&gt;"/>
2072 <changeset author="A. N. Other &lt;other@place&gt;"/>
2061 <changeset author="User Name &lt;user@hostname&gt;"/>
2073 <changeset author="User Name &lt;user@hostname&gt;"/>
2062
2074
2063 $ hg log --template '{rev}: {children}\n'
2075 $ hg log --template '{rev}: {children}\n'
2064 8:
2076 8:
2065 7: 8:95c24699272e
2077 7: 8:95c24699272e
2066 6:
2078 6:
2067 5: 6:d41e714fe50d
2079 5: 6:d41e714fe50d
2068 4: 6:d41e714fe50d
2080 4: 6:d41e714fe50d
2069 3: 4:bbe44766e73d 5:13207e5a10d9
2081 3: 4:bbe44766e73d 5:13207e5a10d9
2070 2: 3:10e46f2dcbf4
2082 2: 3:10e46f2dcbf4
2071 1: 2:97054abb4ab8
2083 1: 2:97054abb4ab8
2072 0: 1:b608e9d1a3f0
2084 0: 1:b608e9d1a3f0
2073
2085
2074 Formatnode filter works:
2086 Formatnode filter works:
2075
2087
2076 $ hg -q log -r 0 --template '{node|formatnode}\n'
2088 $ hg -q log -r 0 --template '{node|formatnode}\n'
2077 1e4e1b8f71e0
2089 1e4e1b8f71e0
2078
2090
2079 $ hg log -r 0 --template '{node|formatnode}\n'
2091 $ hg log -r 0 --template '{node|formatnode}\n'
2080 1e4e1b8f71e0
2092 1e4e1b8f71e0
2081
2093
2082 $ hg -v log -r 0 --template '{node|formatnode}\n'
2094 $ hg -v log -r 0 --template '{node|formatnode}\n'
2083 1e4e1b8f71e0
2095 1e4e1b8f71e0
2084
2096
2085 $ hg --debug log -r 0 --template '{node|formatnode}\n'
2097 $ hg --debug log -r 0 --template '{node|formatnode}\n'
2086 1e4e1b8f71e05681d422154f5421e385fec3454f
2098 1e4e1b8f71e05681d422154f5421e385fec3454f
2087
2099
2088 Age filter:
2100 Age filter:
2089
2101
2090 $ hg init unstable-hash
2102 $ hg init unstable-hash
2091 $ cd unstable-hash
2103 $ cd unstable-hash
2092 $ hg log --template '{date|age}\n' > /dev/null || exit 1
2104 $ hg log --template '{date|age}\n' > /dev/null || exit 1
2093
2105
2094 >>> from datetime import datetime, timedelta
2106 >>> from datetime import datetime, timedelta
2095 >>> fp = open('a', 'w')
2107 >>> fp = open('a', 'w')
2096 >>> n = datetime.now() + timedelta(366 * 7)
2108 >>> n = datetime.now() + timedelta(366 * 7)
2097 >>> fp.write('%d-%d-%d 00:00' % (n.year, n.month, n.day))
2109 >>> fp.write('%d-%d-%d 00:00' % (n.year, n.month, n.day))
2098 >>> fp.close()
2110 >>> fp.close()
2099 $ hg add a
2111 $ hg add a
2100 $ hg commit -m future -d "`cat a`"
2112 $ hg commit -m future -d "`cat a`"
2101
2113
2102 $ hg log -l1 --template '{date|age}\n'
2114 $ hg log -l1 --template '{date|age}\n'
2103 7 years from now
2115 7 years from now
2104
2116
2105 $ cd ..
2117 $ cd ..
2106 $ rm -rf unstable-hash
2118 $ rm -rf unstable-hash
2107
2119
2108 Add a dummy commit to make up for the instability of the above:
2120 Add a dummy commit to make up for the instability of the above:
2109
2121
2110 $ echo a > a
2122 $ echo a > a
2111 $ hg add a
2123 $ hg add a
2112 $ hg ci -m future
2124 $ hg ci -m future
2113
2125
2114 Count filter:
2126 Count filter:
2115
2127
2116 $ hg log -l1 --template '{node|count} {node|short|count}\n'
2128 $ hg log -l1 --template '{node|count} {node|short|count}\n'
2117 40 12
2129 40 12
2118
2130
2119 $ hg log -l1 --template '{revset("null^")|count} {revset(".")|count} {revset("0::3")|count}\n'
2131 $ hg log -l1 --template '{revset("null^")|count} {revset(".")|count} {revset("0::3")|count}\n'
2120 0 1 4
2132 0 1 4
2121
2133
2122 $ hg log -G --template '{rev}: children: {children|count}, \
2134 $ hg log -G --template '{rev}: children: {children|count}, \
2123 > tags: {tags|count}, file_adds: {file_adds|count}, \
2135 > tags: {tags|count}, file_adds: {file_adds|count}, \
2124 > ancestors: {revset("ancestors(%s)", rev)|count}'
2136 > ancestors: {revset("ancestors(%s)", rev)|count}'
2125 @ 9: children: 0, tags: 1, file_adds: 1, ancestors: 3
2137 @ 9: children: 0, tags: 1, file_adds: 1, ancestors: 3
2126 |
2138 |
2127 o 8: children: 1, tags: 0, file_adds: 2, ancestors: 2
2139 o 8: children: 1, tags: 0, file_adds: 2, ancestors: 2
2128 |
2140 |
2129 o 7: children: 1, tags: 0, file_adds: 1, ancestors: 1
2141 o 7: children: 1, tags: 0, file_adds: 1, ancestors: 1
2130
2142
2131 o 6: children: 0, tags: 0, file_adds: 0, ancestors: 7
2143 o 6: children: 0, tags: 0, file_adds: 0, ancestors: 7
2132 |\
2144 |\
2133 | o 5: children: 1, tags: 0, file_adds: 1, ancestors: 5
2145 | o 5: children: 1, tags: 0, file_adds: 1, ancestors: 5
2134 | |
2146 | |
2135 o | 4: children: 1, tags: 0, file_adds: 0, ancestors: 5
2147 o | 4: children: 1, tags: 0, file_adds: 0, ancestors: 5
2136 |/
2148 |/
2137 o 3: children: 2, tags: 0, file_adds: 0, ancestors: 4
2149 o 3: children: 2, tags: 0, file_adds: 0, ancestors: 4
2138 |
2150 |
2139 o 2: children: 1, tags: 0, file_adds: 1, ancestors: 3
2151 o 2: children: 1, tags: 0, file_adds: 1, ancestors: 3
2140 |
2152 |
2141 o 1: children: 1, tags: 0, file_adds: 1, ancestors: 2
2153 o 1: children: 1, tags: 0, file_adds: 1, ancestors: 2
2142 |
2154 |
2143 o 0: children: 1, tags: 0, file_adds: 1, ancestors: 1
2155 o 0: children: 1, tags: 0, file_adds: 1, ancestors: 1
2144
2156
2145
2157
2146 Upper/lower filters:
2158 Upper/lower filters:
2147
2159
2148 $ hg log -r0 --template '{branch|upper}\n'
2160 $ hg log -r0 --template '{branch|upper}\n'
2149 DEFAULT
2161 DEFAULT
2150 $ hg log -r0 --template '{author|lower}\n'
2162 $ hg log -r0 --template '{author|lower}\n'
2151 user name <user@hostname>
2163 user name <user@hostname>
2152 $ hg log -r0 --template '{date|upper}\n'
2164 $ hg log -r0 --template '{date|upper}\n'
2153 abort: template filter 'upper' is not compatible with keyword 'date'
2165 abort: template filter 'upper' is not compatible with keyword 'date'
2154 [255]
2166 [255]
2155
2167
2156 Add a commit that does all possible modifications at once
2168 Add a commit that does all possible modifications at once
2157
2169
2158 $ echo modify >> third
2170 $ echo modify >> third
2159 $ touch b
2171 $ touch b
2160 $ hg add b
2172 $ hg add b
2161 $ hg mv fourth fifth
2173 $ hg mv fourth fifth
2162 $ hg rm a
2174 $ hg rm a
2163 $ hg ci -m "Modify, add, remove, rename"
2175 $ hg ci -m "Modify, add, remove, rename"
2164
2176
2165 Check the status template
2177 Check the status template
2166
2178
2167 $ cat <<EOF >> $HGRCPATH
2179 $ cat <<EOF >> $HGRCPATH
2168 > [extensions]
2180 > [extensions]
2169 > color=
2181 > color=
2170 > EOF
2182 > EOF
2171
2183
2172 $ hg log -T status -r 10
2184 $ hg log -T status -r 10
2173 changeset: 10:0f9759ec227a
2185 changeset: 10:0f9759ec227a
2174 tag: tip
2186 tag: tip
2175 user: test
2187 user: test
2176 date: Thu Jan 01 00:00:00 1970 +0000
2188 date: Thu Jan 01 00:00:00 1970 +0000
2177 summary: Modify, add, remove, rename
2189 summary: Modify, add, remove, rename
2178 files:
2190 files:
2179 M third
2191 M third
2180 A b
2192 A b
2181 A fifth
2193 A fifth
2182 R a
2194 R a
2183 R fourth
2195 R fourth
2184
2196
2185 $ hg log -T status -C -r 10
2197 $ hg log -T status -C -r 10
2186 changeset: 10:0f9759ec227a
2198 changeset: 10:0f9759ec227a
2187 tag: tip
2199 tag: tip
2188 user: test
2200 user: test
2189 date: Thu Jan 01 00:00:00 1970 +0000
2201 date: Thu Jan 01 00:00:00 1970 +0000
2190 summary: Modify, add, remove, rename
2202 summary: Modify, add, remove, rename
2191 files:
2203 files:
2192 M third
2204 M third
2193 A b
2205 A b
2194 A fifth
2206 A fifth
2195 fourth
2207 fourth
2196 R a
2208 R a
2197 R fourth
2209 R fourth
2198
2210
2199 $ hg log -T status -C -r 10 -v
2211 $ hg log -T status -C -r 10 -v
2200 changeset: 10:0f9759ec227a
2212 changeset: 10:0f9759ec227a
2201 tag: tip
2213 tag: tip
2202 user: test
2214 user: test
2203 date: Thu Jan 01 00:00:00 1970 +0000
2215 date: Thu Jan 01 00:00:00 1970 +0000
2204 description:
2216 description:
2205 Modify, add, remove, rename
2217 Modify, add, remove, rename
2206
2218
2207 files:
2219 files:
2208 M third
2220 M third
2209 A b
2221 A b
2210 A fifth
2222 A fifth
2211 fourth
2223 fourth
2212 R a
2224 R a
2213 R fourth
2225 R fourth
2214
2226
2215 $ hg log -T status -C -r 10 --debug
2227 $ hg log -T status -C -r 10 --debug
2216 changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c
2228 changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c
2217 tag: tip
2229 tag: tip
2218 phase: secret
2230 phase: secret
2219 parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066
2231 parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066
2220 parent: -1:0000000000000000000000000000000000000000
2232 parent: -1:0000000000000000000000000000000000000000
2221 manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567
2233 manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567
2222 user: test
2234 user: test
2223 date: Thu Jan 01 00:00:00 1970 +0000
2235 date: Thu Jan 01 00:00:00 1970 +0000
2224 extra: branch=default
2236 extra: branch=default
2225 description:
2237 description:
2226 Modify, add, remove, rename
2238 Modify, add, remove, rename
2227
2239
2228 files:
2240 files:
2229 M third
2241 M third
2230 A b
2242 A b
2231 A fifth
2243 A fifth
2232 fourth
2244 fourth
2233 R a
2245 R a
2234 R fourth
2246 R fourth
2235
2247
2236 $ hg log -T status -C -r 10 --quiet
2248 $ hg log -T status -C -r 10 --quiet
2237 10:0f9759ec227a
2249 10:0f9759ec227a
2238 $ hg --color=debug log -T status -r 10
2250 $ hg --color=debug log -T status -r 10
2239 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2251 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2240 [log.tag|tag: tip]
2252 [log.tag|tag: tip]
2241 [log.user|user: test]
2253 [log.user|user: test]
2242 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2254 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2243 [log.summary|summary: Modify, add, remove, rename]
2255 [log.summary|summary: Modify, add, remove, rename]
2244 [ui.note log.files|files:]
2256 [ui.note log.files|files:]
2245 [status.modified|M third]
2257 [status.modified|M third]
2246 [status.added|A b]
2258 [status.added|A b]
2247 [status.added|A fifth]
2259 [status.added|A fifth]
2248 [status.removed|R a]
2260 [status.removed|R a]
2249 [status.removed|R fourth]
2261 [status.removed|R fourth]
2250
2262
2251 $ hg --color=debug log -T status -C -r 10
2263 $ hg --color=debug log -T status -C -r 10
2252 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2264 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2253 [log.tag|tag: tip]
2265 [log.tag|tag: tip]
2254 [log.user|user: test]
2266 [log.user|user: test]
2255 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2267 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2256 [log.summary|summary: Modify, add, remove, rename]
2268 [log.summary|summary: Modify, add, remove, rename]
2257 [ui.note log.files|files:]
2269 [ui.note log.files|files:]
2258 [status.modified|M third]
2270 [status.modified|M third]
2259 [status.added|A b]
2271 [status.added|A b]
2260 [status.added|A fifth]
2272 [status.added|A fifth]
2261 [status.copied| fourth]
2273 [status.copied| fourth]
2262 [status.removed|R a]
2274 [status.removed|R a]
2263 [status.removed|R fourth]
2275 [status.removed|R fourth]
2264
2276
2265 $ hg --color=debug log -T status -C -r 10 -v
2277 $ hg --color=debug log -T status -C -r 10 -v
2266 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2278 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2267 [log.tag|tag: tip]
2279 [log.tag|tag: tip]
2268 [log.user|user: test]
2280 [log.user|user: test]
2269 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2281 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2270 [ui.note log.description|description:]
2282 [ui.note log.description|description:]
2271 [ui.note log.description|Modify, add, remove, rename]
2283 [ui.note log.description|Modify, add, remove, rename]
2272
2284
2273 [ui.note log.files|files:]
2285 [ui.note log.files|files:]
2274 [status.modified|M third]
2286 [status.modified|M third]
2275 [status.added|A b]
2287 [status.added|A b]
2276 [status.added|A fifth]
2288 [status.added|A fifth]
2277 [status.copied| fourth]
2289 [status.copied| fourth]
2278 [status.removed|R a]
2290 [status.removed|R a]
2279 [status.removed|R fourth]
2291 [status.removed|R fourth]
2280
2292
2281 $ hg --color=debug log -T status -C -r 10 --debug
2293 $ hg --color=debug log -T status -C -r 10 --debug
2282 [log.changeset changeset.secret|changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c]
2294 [log.changeset changeset.secret|changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c]
2283 [log.tag|tag: tip]
2295 [log.tag|tag: tip]
2284 [log.phase|phase: secret]
2296 [log.phase|phase: secret]
2285 [log.parent changeset.secret|parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066]
2297 [log.parent changeset.secret|parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066]
2286 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2298 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2287 [ui.debug log.manifest|manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567]
2299 [ui.debug log.manifest|manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567]
2288 [log.user|user: test]
2300 [log.user|user: test]
2289 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2301 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2290 [ui.debug log.extra|extra: branch=default]
2302 [ui.debug log.extra|extra: branch=default]
2291 [ui.note log.description|description:]
2303 [ui.note log.description|description:]
2292 [ui.note log.description|Modify, add, remove, rename]
2304 [ui.note log.description|Modify, add, remove, rename]
2293
2305
2294 [ui.note log.files|files:]
2306 [ui.note log.files|files:]
2295 [status.modified|M third]
2307 [status.modified|M third]
2296 [status.added|A b]
2308 [status.added|A b]
2297 [status.added|A fifth]
2309 [status.added|A fifth]
2298 [status.copied| fourth]
2310 [status.copied| fourth]
2299 [status.removed|R a]
2311 [status.removed|R a]
2300 [status.removed|R fourth]
2312 [status.removed|R fourth]
2301
2313
2302 $ hg --color=debug log -T status -C -r 10 --quiet
2314 $ hg --color=debug log -T status -C -r 10 --quiet
2303 [log.node|10:0f9759ec227a]
2315 [log.node|10:0f9759ec227a]
2304
2316
2305 Check the bisect template
2317 Check the bisect template
2306
2318
2307 $ hg bisect -g 1
2319 $ hg bisect -g 1
2308 $ hg bisect -b 3 --noupdate
2320 $ hg bisect -b 3 --noupdate
2309 Testing changeset 2:97054abb4ab8 (2 changesets remaining, ~1 tests)
2321 Testing changeset 2:97054abb4ab8 (2 changesets remaining, ~1 tests)
2310 $ hg log -T bisect -r 0:4
2322 $ hg log -T bisect -r 0:4
2311 changeset: 0:1e4e1b8f71e0
2323 changeset: 0:1e4e1b8f71e0
2312 bisect: good (implicit)
2324 bisect: good (implicit)
2313 user: User Name <user@hostname>
2325 user: User Name <user@hostname>
2314 date: Mon Jan 12 13:46:40 1970 +0000
2326 date: Mon Jan 12 13:46:40 1970 +0000
2315 summary: line 1
2327 summary: line 1
2316
2328
2317 changeset: 1:b608e9d1a3f0
2329 changeset: 1:b608e9d1a3f0
2318 bisect: good
2330 bisect: good
2319 user: A. N. Other <other@place>
2331 user: A. N. Other <other@place>
2320 date: Tue Jan 13 17:33:20 1970 +0000
2332 date: Tue Jan 13 17:33:20 1970 +0000
2321 summary: other 1
2333 summary: other 1
2322
2334
2323 changeset: 2:97054abb4ab8
2335 changeset: 2:97054abb4ab8
2324 bisect: untested
2336 bisect: untested
2325 user: other@place
2337 user: other@place
2326 date: Wed Jan 14 21:20:00 1970 +0000
2338 date: Wed Jan 14 21:20:00 1970 +0000
2327 summary: no person
2339 summary: no person
2328
2340
2329 changeset: 3:10e46f2dcbf4
2341 changeset: 3:10e46f2dcbf4
2330 bisect: bad
2342 bisect: bad
2331 user: person
2343 user: person
2332 date: Fri Jan 16 01:06:40 1970 +0000
2344 date: Fri Jan 16 01:06:40 1970 +0000
2333 summary: no user, no domain
2345 summary: no user, no domain
2334
2346
2335 changeset: 4:bbe44766e73d
2347 changeset: 4:bbe44766e73d
2336 bisect: bad (implicit)
2348 bisect: bad (implicit)
2337 branch: foo
2349 branch: foo
2338 user: person
2350 user: person
2339 date: Sat Jan 17 04:53:20 1970 +0000
2351 date: Sat Jan 17 04:53:20 1970 +0000
2340 summary: new branch
2352 summary: new branch
2341
2353
2342 $ hg log --debug -T bisect -r 0:4
2354 $ hg log --debug -T bisect -r 0:4
2343 changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
2355 changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
2344 bisect: good (implicit)
2356 bisect: good (implicit)
2345 phase: public
2357 phase: public
2346 parent: -1:0000000000000000000000000000000000000000
2358 parent: -1:0000000000000000000000000000000000000000
2347 parent: -1:0000000000000000000000000000000000000000
2359 parent: -1:0000000000000000000000000000000000000000
2348 manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
2360 manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
2349 user: User Name <user@hostname>
2361 user: User Name <user@hostname>
2350 date: Mon Jan 12 13:46:40 1970 +0000
2362 date: Mon Jan 12 13:46:40 1970 +0000
2351 files+: a
2363 files+: a
2352 extra: branch=default
2364 extra: branch=default
2353 description:
2365 description:
2354 line 1
2366 line 1
2355 line 2
2367 line 2
2356
2368
2357
2369
2358 changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2370 changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2359 bisect: good
2371 bisect: good
2360 phase: public
2372 phase: public
2361 parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
2373 parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
2362 parent: -1:0000000000000000000000000000000000000000
2374 parent: -1:0000000000000000000000000000000000000000
2363 manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
2375 manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
2364 user: A. N. Other <other@place>
2376 user: A. N. Other <other@place>
2365 date: Tue Jan 13 17:33:20 1970 +0000
2377 date: Tue Jan 13 17:33:20 1970 +0000
2366 files+: b
2378 files+: b
2367 extra: branch=default
2379 extra: branch=default
2368 description:
2380 description:
2369 other 1
2381 other 1
2370 other 2
2382 other 2
2371
2383
2372 other 3
2384 other 3
2373
2385
2374
2386
2375 changeset: 2:97054abb4ab824450e9164180baf491ae0078465
2387 changeset: 2:97054abb4ab824450e9164180baf491ae0078465
2376 bisect: untested
2388 bisect: untested
2377 phase: public
2389 phase: public
2378 parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2390 parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2379 parent: -1:0000000000000000000000000000000000000000
2391 parent: -1:0000000000000000000000000000000000000000
2380 manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
2392 manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
2381 user: other@place
2393 user: other@place
2382 date: Wed Jan 14 21:20:00 1970 +0000
2394 date: Wed Jan 14 21:20:00 1970 +0000
2383 files+: c
2395 files+: c
2384 extra: branch=default
2396 extra: branch=default
2385 description:
2397 description:
2386 no person
2398 no person
2387
2399
2388
2400
2389 changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
2401 changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
2390 bisect: bad
2402 bisect: bad
2391 phase: public
2403 phase: public
2392 parent: 2:97054abb4ab824450e9164180baf491ae0078465
2404 parent: 2:97054abb4ab824450e9164180baf491ae0078465
2393 parent: -1:0000000000000000000000000000000000000000
2405 parent: -1:0000000000000000000000000000000000000000
2394 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
2406 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
2395 user: person
2407 user: person
2396 date: Fri Jan 16 01:06:40 1970 +0000
2408 date: Fri Jan 16 01:06:40 1970 +0000
2397 files: c
2409 files: c
2398 extra: branch=default
2410 extra: branch=default
2399 description:
2411 description:
2400 no user, no domain
2412 no user, no domain
2401
2413
2402
2414
2403 changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
2415 changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
2404 bisect: bad (implicit)
2416 bisect: bad (implicit)
2405 branch: foo
2417 branch: foo
2406 phase: draft
2418 phase: draft
2407 parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
2419 parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
2408 parent: -1:0000000000000000000000000000000000000000
2420 parent: -1:0000000000000000000000000000000000000000
2409 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
2421 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
2410 user: person
2422 user: person
2411 date: Sat Jan 17 04:53:20 1970 +0000
2423 date: Sat Jan 17 04:53:20 1970 +0000
2412 extra: branch=foo
2424 extra: branch=foo
2413 description:
2425 description:
2414 new branch
2426 new branch
2415
2427
2416
2428
2417 $ hg log -v -T bisect -r 0:4
2429 $ hg log -v -T bisect -r 0:4
2418 changeset: 0:1e4e1b8f71e0
2430 changeset: 0:1e4e1b8f71e0
2419 bisect: good (implicit)
2431 bisect: good (implicit)
2420 user: User Name <user@hostname>
2432 user: User Name <user@hostname>
2421 date: Mon Jan 12 13:46:40 1970 +0000
2433 date: Mon Jan 12 13:46:40 1970 +0000
2422 files: a
2434 files: a
2423 description:
2435 description:
2424 line 1
2436 line 1
2425 line 2
2437 line 2
2426
2438
2427
2439
2428 changeset: 1:b608e9d1a3f0
2440 changeset: 1:b608e9d1a3f0
2429 bisect: good
2441 bisect: good
2430 user: A. N. Other <other@place>
2442 user: A. N. Other <other@place>
2431 date: Tue Jan 13 17:33:20 1970 +0000
2443 date: Tue Jan 13 17:33:20 1970 +0000
2432 files: b
2444 files: b
2433 description:
2445 description:
2434 other 1
2446 other 1
2435 other 2
2447 other 2
2436
2448
2437 other 3
2449 other 3
2438
2450
2439
2451
2440 changeset: 2:97054abb4ab8
2452 changeset: 2:97054abb4ab8
2441 bisect: untested
2453 bisect: untested
2442 user: other@place
2454 user: other@place
2443 date: Wed Jan 14 21:20:00 1970 +0000
2455 date: Wed Jan 14 21:20:00 1970 +0000
2444 files: c
2456 files: c
2445 description:
2457 description:
2446 no person
2458 no person
2447
2459
2448
2460
2449 changeset: 3:10e46f2dcbf4
2461 changeset: 3:10e46f2dcbf4
2450 bisect: bad
2462 bisect: bad
2451 user: person
2463 user: person
2452 date: Fri Jan 16 01:06:40 1970 +0000
2464 date: Fri Jan 16 01:06:40 1970 +0000
2453 files: c
2465 files: c
2454 description:
2466 description:
2455 no user, no domain
2467 no user, no domain
2456
2468
2457
2469
2458 changeset: 4:bbe44766e73d
2470 changeset: 4:bbe44766e73d
2459 bisect: bad (implicit)
2471 bisect: bad (implicit)
2460 branch: foo
2472 branch: foo
2461 user: person
2473 user: person
2462 date: Sat Jan 17 04:53:20 1970 +0000
2474 date: Sat Jan 17 04:53:20 1970 +0000
2463 description:
2475 description:
2464 new branch
2476 new branch
2465
2477
2466
2478
2467 $ hg --color=debug log -T bisect -r 0:4
2479 $ hg --color=debug log -T bisect -r 0:4
2468 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
2480 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
2469 [log.bisect bisect.good|bisect: good (implicit)]
2481 [log.bisect bisect.good|bisect: good (implicit)]
2470 [log.user|user: User Name <user@hostname>]
2482 [log.user|user: User Name <user@hostname>]
2471 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2483 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2472 [log.summary|summary: line 1]
2484 [log.summary|summary: line 1]
2473
2485
2474 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
2486 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
2475 [log.bisect bisect.good|bisect: good]
2487 [log.bisect bisect.good|bisect: good]
2476 [log.user|user: A. N. Other <other@place>]
2488 [log.user|user: A. N. Other <other@place>]
2477 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2489 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2478 [log.summary|summary: other 1]
2490 [log.summary|summary: other 1]
2479
2491
2480 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
2492 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
2481 [log.bisect bisect.untested|bisect: untested]
2493 [log.bisect bisect.untested|bisect: untested]
2482 [log.user|user: other@place]
2494 [log.user|user: other@place]
2483 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2495 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2484 [log.summary|summary: no person]
2496 [log.summary|summary: no person]
2485
2497
2486 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
2498 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
2487 [log.bisect bisect.bad|bisect: bad]
2499 [log.bisect bisect.bad|bisect: bad]
2488 [log.user|user: person]
2500 [log.user|user: person]
2489 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2501 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2490 [log.summary|summary: no user, no domain]
2502 [log.summary|summary: no user, no domain]
2491
2503
2492 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
2504 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
2493 [log.bisect bisect.bad|bisect: bad (implicit)]
2505 [log.bisect bisect.bad|bisect: bad (implicit)]
2494 [log.branch|branch: foo]
2506 [log.branch|branch: foo]
2495 [log.user|user: person]
2507 [log.user|user: person]
2496 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2508 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2497 [log.summary|summary: new branch]
2509 [log.summary|summary: new branch]
2498
2510
2499 $ hg --color=debug log --debug -T bisect -r 0:4
2511 $ hg --color=debug log --debug -T bisect -r 0:4
2500 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
2512 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
2501 [log.bisect bisect.good|bisect: good (implicit)]
2513 [log.bisect bisect.good|bisect: good (implicit)]
2502 [log.phase|phase: public]
2514 [log.phase|phase: public]
2503 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2515 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2504 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2516 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2505 [ui.debug log.manifest|manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0]
2517 [ui.debug log.manifest|manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0]
2506 [log.user|user: User Name <user@hostname>]
2518 [log.user|user: User Name <user@hostname>]
2507 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2519 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2508 [ui.debug log.files|files+: a]
2520 [ui.debug log.files|files+: a]
2509 [ui.debug log.extra|extra: branch=default]
2521 [ui.debug log.extra|extra: branch=default]
2510 [ui.note log.description|description:]
2522 [ui.note log.description|description:]
2511 [ui.note log.description|line 1
2523 [ui.note log.description|line 1
2512 line 2]
2524 line 2]
2513
2525
2514
2526
2515 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
2527 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
2516 [log.bisect bisect.good|bisect: good]
2528 [log.bisect bisect.good|bisect: good]
2517 [log.phase|phase: public]
2529 [log.phase|phase: public]
2518 [log.parent changeset.public|parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
2530 [log.parent changeset.public|parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
2519 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2531 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2520 [ui.debug log.manifest|manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55]
2532 [ui.debug log.manifest|manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55]
2521 [log.user|user: A. N. Other <other@place>]
2533 [log.user|user: A. N. Other <other@place>]
2522 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2534 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2523 [ui.debug log.files|files+: b]
2535 [ui.debug log.files|files+: b]
2524 [ui.debug log.extra|extra: branch=default]
2536 [ui.debug log.extra|extra: branch=default]
2525 [ui.note log.description|description:]
2537 [ui.note log.description|description:]
2526 [ui.note log.description|other 1
2538 [ui.note log.description|other 1
2527 other 2
2539 other 2
2528
2540
2529 other 3]
2541 other 3]
2530
2542
2531
2543
2532 [log.changeset changeset.public|changeset: 2:97054abb4ab824450e9164180baf491ae0078465]
2544 [log.changeset changeset.public|changeset: 2:97054abb4ab824450e9164180baf491ae0078465]
2533 [log.bisect bisect.untested|bisect: untested]
2545 [log.bisect bisect.untested|bisect: untested]
2534 [log.phase|phase: public]
2546 [log.phase|phase: public]
2535 [log.parent changeset.public|parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
2547 [log.parent changeset.public|parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
2536 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2548 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2537 [ui.debug log.manifest|manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1]
2549 [ui.debug log.manifest|manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1]
2538 [log.user|user: other@place]
2550 [log.user|user: other@place]
2539 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2551 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2540 [ui.debug log.files|files+: c]
2552 [ui.debug log.files|files+: c]
2541 [ui.debug log.extra|extra: branch=default]
2553 [ui.debug log.extra|extra: branch=default]
2542 [ui.note log.description|description:]
2554 [ui.note log.description|description:]
2543 [ui.note log.description|no person]
2555 [ui.note log.description|no person]
2544
2556
2545
2557
2546 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
2558 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
2547 [log.bisect bisect.bad|bisect: bad]
2559 [log.bisect bisect.bad|bisect: bad]
2548 [log.phase|phase: public]
2560 [log.phase|phase: public]
2549 [log.parent changeset.public|parent: 2:97054abb4ab824450e9164180baf491ae0078465]
2561 [log.parent changeset.public|parent: 2:97054abb4ab824450e9164180baf491ae0078465]
2550 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2562 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2551 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
2563 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
2552 [log.user|user: person]
2564 [log.user|user: person]
2553 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2565 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2554 [ui.debug log.files|files: c]
2566 [ui.debug log.files|files: c]
2555 [ui.debug log.extra|extra: branch=default]
2567 [ui.debug log.extra|extra: branch=default]
2556 [ui.note log.description|description:]
2568 [ui.note log.description|description:]
2557 [ui.note log.description|no user, no domain]
2569 [ui.note log.description|no user, no domain]
2558
2570
2559
2571
2560 [log.changeset changeset.draft|changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74]
2572 [log.changeset changeset.draft|changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74]
2561 [log.bisect bisect.bad|bisect: bad (implicit)]
2573 [log.bisect bisect.bad|bisect: bad (implicit)]
2562 [log.branch|branch: foo]
2574 [log.branch|branch: foo]
2563 [log.phase|phase: draft]
2575 [log.phase|phase: draft]
2564 [log.parent changeset.public|parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
2576 [log.parent changeset.public|parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
2565 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2577 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2566 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
2578 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
2567 [log.user|user: person]
2579 [log.user|user: person]
2568 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2580 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2569 [ui.debug log.extra|extra: branch=foo]
2581 [ui.debug log.extra|extra: branch=foo]
2570 [ui.note log.description|description:]
2582 [ui.note log.description|description:]
2571 [ui.note log.description|new branch]
2583 [ui.note log.description|new branch]
2572
2584
2573
2585
2574 $ hg --color=debug log -v -T bisect -r 0:4
2586 $ hg --color=debug log -v -T bisect -r 0:4
2575 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
2587 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
2576 [log.bisect bisect.good|bisect: good (implicit)]
2588 [log.bisect bisect.good|bisect: good (implicit)]
2577 [log.user|user: User Name <user@hostname>]
2589 [log.user|user: User Name <user@hostname>]
2578 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2590 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2579 [ui.note log.files|files: a]
2591 [ui.note log.files|files: a]
2580 [ui.note log.description|description:]
2592 [ui.note log.description|description:]
2581 [ui.note log.description|line 1
2593 [ui.note log.description|line 1
2582 line 2]
2594 line 2]
2583
2595
2584
2596
2585 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
2597 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
2586 [log.bisect bisect.good|bisect: good]
2598 [log.bisect bisect.good|bisect: good]
2587 [log.user|user: A. N. Other <other@place>]
2599 [log.user|user: A. N. Other <other@place>]
2588 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2600 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2589 [ui.note log.files|files: b]
2601 [ui.note log.files|files: b]
2590 [ui.note log.description|description:]
2602 [ui.note log.description|description:]
2591 [ui.note log.description|other 1
2603 [ui.note log.description|other 1
2592 other 2
2604 other 2
2593
2605
2594 other 3]
2606 other 3]
2595
2607
2596
2608
2597 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
2609 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
2598 [log.bisect bisect.untested|bisect: untested]
2610 [log.bisect bisect.untested|bisect: untested]
2599 [log.user|user: other@place]
2611 [log.user|user: other@place]
2600 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2612 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2601 [ui.note log.files|files: c]
2613 [ui.note log.files|files: c]
2602 [ui.note log.description|description:]
2614 [ui.note log.description|description:]
2603 [ui.note log.description|no person]
2615 [ui.note log.description|no person]
2604
2616
2605
2617
2606 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
2618 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
2607 [log.bisect bisect.bad|bisect: bad]
2619 [log.bisect bisect.bad|bisect: bad]
2608 [log.user|user: person]
2620 [log.user|user: person]
2609 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2621 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2610 [ui.note log.files|files: c]
2622 [ui.note log.files|files: c]
2611 [ui.note log.description|description:]
2623 [ui.note log.description|description:]
2612 [ui.note log.description|no user, no domain]
2624 [ui.note log.description|no user, no domain]
2613
2625
2614
2626
2615 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
2627 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
2616 [log.bisect bisect.bad|bisect: bad (implicit)]
2628 [log.bisect bisect.bad|bisect: bad (implicit)]
2617 [log.branch|branch: foo]
2629 [log.branch|branch: foo]
2618 [log.user|user: person]
2630 [log.user|user: person]
2619 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2631 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2620 [ui.note log.description|description:]
2632 [ui.note log.description|description:]
2621 [ui.note log.description|new branch]
2633 [ui.note log.description|new branch]
2622
2634
2623
2635
2624 $ hg bisect --reset
2636 $ hg bisect --reset
2625
2637
2626 Error on syntax:
2638 Error on syntax:
2627
2639
2628 $ echo 'x = "f' >> t
2640 $ echo 'x = "f' >> t
2629 $ hg log
2641 $ hg log
2630 hg: parse error at t:3: unmatched quotes
2642 hg: parse error at t:3: unmatched quotes
2631 [255]
2643 [255]
2632
2644
2633 $ hg log -T '{date'
2645 $ hg log -T '{date'
2634 hg: parse error at 1: unterminated template expansion
2646 hg: parse error at 1: unterminated template expansion
2635 [255]
2647 [255]
2636
2648
2637 Behind the scenes, this will throw TypeError
2649 Behind the scenes, this will throw TypeError
2638
2650
2639 $ hg log -l 3 --template '{date|obfuscate}\n'
2651 $ hg log -l 3 --template '{date|obfuscate}\n'
2640 abort: template filter 'obfuscate' is not compatible with keyword 'date'
2652 abort: template filter 'obfuscate' is not compatible with keyword 'date'
2641 [255]
2653 [255]
2642
2654
2643 Behind the scenes, this will throw a ValueError
2655 Behind the scenes, this will throw a ValueError
2644
2656
2645 $ hg log -l 3 --template 'line: {desc|shortdate}\n'
2657 $ hg log -l 3 --template 'line: {desc|shortdate}\n'
2646 abort: template filter 'shortdate' is not compatible with keyword 'desc'
2658 abort: template filter 'shortdate' is not compatible with keyword 'desc'
2647 [255]
2659 [255]
2648
2660
2649 Behind the scenes, this will throw AttributeError
2661 Behind the scenes, this will throw AttributeError
2650
2662
2651 $ hg log -l 3 --template 'line: {date|escape}\n'
2663 $ hg log -l 3 --template 'line: {date|escape}\n'
2652 abort: template filter 'escape' is not compatible with keyword 'date'
2664 abort: template filter 'escape' is not compatible with keyword 'date'
2653 [255]
2665 [255]
2654
2666
2655 $ hg log -l 3 --template 'line: {extras|localdate}\n'
2667 $ hg log -l 3 --template 'line: {extras|localdate}\n'
2656 hg: parse error: localdate expects a date information
2668 hg: parse error: localdate expects a date information
2657 [255]
2669 [255]
2658
2670
2659 Behind the scenes, this will throw ValueError
2671 Behind the scenes, this will throw ValueError
2660
2672
2661 $ hg tip --template '{author|email|date}\n'
2673 $ hg tip --template '{author|email|date}\n'
2662 hg: parse error: date expects a date information
2674 hg: parse error: date expects a date information
2663 [255]
2675 [255]
2664
2676
2665 Error in nested template:
2677 Error in nested template:
2666
2678
2667 $ hg log -T '{"date'
2679 $ hg log -T '{"date'
2668 hg: parse error at 2: unterminated string
2680 hg: parse error at 2: unterminated string
2669 [255]
2681 [255]
2670
2682
2671 $ hg log -T '{"foo{date|=}"}'
2683 $ hg log -T '{"foo{date|?}"}'
2672 hg: parse error at 11: syntax error
2684 hg: parse error at 11: syntax error
2673 [255]
2685 [255]
2674
2686
2675 Thrown an error if a template function doesn't exist
2687 Thrown an error if a template function doesn't exist
2676
2688
2677 $ hg tip --template '{foo()}\n'
2689 $ hg tip --template '{foo()}\n'
2678 hg: parse error: unknown function 'foo'
2690 hg: parse error: unknown function 'foo'
2679 [255]
2691 [255]
2680
2692
2681 Pass generator object created by template function to filter
2693 Pass generator object created by template function to filter
2682
2694
2683 $ hg log -l 1 --template '{if(author, author)|user}\n'
2695 $ hg log -l 1 --template '{if(author, author)|user}\n'
2684 test
2696 test
2685
2697
2686 Test index keyword:
2698 Test index keyword:
2687
2699
2688 $ hg log -l 2 -T '{index + 10}{files % " {index}:{file}"}\n'
2700 $ hg log -l 2 -T '{index + 10}{files % " {index}:{file}"}\n'
2689 10 0:a 1:b 2:fifth 3:fourth 4:third
2701 10 0:a 1:b 2:fifth 3:fourth 4:third
2690 11 0:a
2702 11 0:a
2691
2703
2692 $ hg branches -T '{index} {branch}\n'
2704 $ hg branches -T '{index} {branch}\n'
2693 0 default
2705 0 default
2694 1 foo
2706 1 foo
2695
2707
2696 Test diff function:
2708 Test diff function:
2697
2709
2698 $ hg diff -c 8
2710 $ hg diff -c 8
2699 diff -r 29114dbae42b -r 95c24699272e fourth
2711 diff -r 29114dbae42b -r 95c24699272e fourth
2700 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2712 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2701 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2713 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2702 @@ -0,0 +1,1 @@
2714 @@ -0,0 +1,1 @@
2703 +second
2715 +second
2704 diff -r 29114dbae42b -r 95c24699272e second
2716 diff -r 29114dbae42b -r 95c24699272e second
2705 --- a/second Mon Jan 12 13:46:40 1970 +0000
2717 --- a/second Mon Jan 12 13:46:40 1970 +0000
2706 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2718 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2707 @@ -1,1 +0,0 @@
2719 @@ -1,1 +0,0 @@
2708 -second
2720 -second
2709 diff -r 29114dbae42b -r 95c24699272e third
2721 diff -r 29114dbae42b -r 95c24699272e third
2710 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2722 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2711 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2723 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2712 @@ -0,0 +1,1 @@
2724 @@ -0,0 +1,1 @@
2713 +third
2725 +third
2714
2726
2715 $ hg log -r 8 -T "{diff()}"
2727 $ hg log -r 8 -T "{diff()}"
2716 diff -r 29114dbae42b -r 95c24699272e fourth
2728 diff -r 29114dbae42b -r 95c24699272e fourth
2717 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2729 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2718 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2730 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2719 @@ -0,0 +1,1 @@
2731 @@ -0,0 +1,1 @@
2720 +second
2732 +second
2721 diff -r 29114dbae42b -r 95c24699272e second
2733 diff -r 29114dbae42b -r 95c24699272e second
2722 --- a/second Mon Jan 12 13:46:40 1970 +0000
2734 --- a/second Mon Jan 12 13:46:40 1970 +0000
2723 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2735 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2724 @@ -1,1 +0,0 @@
2736 @@ -1,1 +0,0 @@
2725 -second
2737 -second
2726 diff -r 29114dbae42b -r 95c24699272e third
2738 diff -r 29114dbae42b -r 95c24699272e third
2727 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2739 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2728 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2740 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2729 @@ -0,0 +1,1 @@
2741 @@ -0,0 +1,1 @@
2730 +third
2742 +third
2731
2743
2732 $ hg log -r 8 -T "{diff('glob:f*')}"
2744 $ hg log -r 8 -T "{diff('glob:f*')}"
2733 diff -r 29114dbae42b -r 95c24699272e fourth
2745 diff -r 29114dbae42b -r 95c24699272e fourth
2734 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2746 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2735 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2747 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2736 @@ -0,0 +1,1 @@
2748 @@ -0,0 +1,1 @@
2737 +second
2749 +second
2738
2750
2739 $ hg log -r 8 -T "{diff('', 'glob:f*')}"
2751 $ hg log -r 8 -T "{diff('', 'glob:f*')}"
2740 diff -r 29114dbae42b -r 95c24699272e second
2752 diff -r 29114dbae42b -r 95c24699272e second
2741 --- a/second Mon Jan 12 13:46:40 1970 +0000
2753 --- a/second Mon Jan 12 13:46:40 1970 +0000
2742 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2754 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2743 @@ -1,1 +0,0 @@
2755 @@ -1,1 +0,0 @@
2744 -second
2756 -second
2745 diff -r 29114dbae42b -r 95c24699272e third
2757 diff -r 29114dbae42b -r 95c24699272e third
2746 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2758 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2747 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2759 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2748 @@ -0,0 +1,1 @@
2760 @@ -0,0 +1,1 @@
2749 +third
2761 +third
2750
2762
2751 $ hg log -r 8 -T "{diff('FOURTH'|lower)}"
2763 $ hg log -r 8 -T "{diff('FOURTH'|lower)}"
2752 diff -r 29114dbae42b -r 95c24699272e fourth
2764 diff -r 29114dbae42b -r 95c24699272e fourth
2753 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2765 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2754 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2766 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2755 @@ -0,0 +1,1 @@
2767 @@ -0,0 +1,1 @@
2756 +second
2768 +second
2757
2769
2758 $ cd ..
2770 $ cd ..
2759
2771
2760
2772
2761 latesttag:
2773 latesttag:
2762
2774
2763 $ hg init latesttag
2775 $ hg init latesttag
2764 $ cd latesttag
2776 $ cd latesttag
2765
2777
2766 $ echo a > file
2778 $ echo a > file
2767 $ hg ci -Am a -d '0 0'
2779 $ hg ci -Am a -d '0 0'
2768 adding file
2780 adding file
2769
2781
2770 $ echo b >> file
2782 $ echo b >> file
2771 $ hg ci -m b -d '1 0'
2783 $ hg ci -m b -d '1 0'
2772
2784
2773 $ echo c >> head1
2785 $ echo c >> head1
2774 $ hg ci -Am h1c -d '2 0'
2786 $ hg ci -Am h1c -d '2 0'
2775 adding head1
2787 adding head1
2776
2788
2777 $ hg update -q 1
2789 $ hg update -q 1
2778 $ echo d >> head2
2790 $ echo d >> head2
2779 $ hg ci -Am h2d -d '3 0'
2791 $ hg ci -Am h2d -d '3 0'
2780 adding head2
2792 adding head2
2781 created new head
2793 created new head
2782
2794
2783 $ echo e >> head2
2795 $ echo e >> head2
2784 $ hg ci -m h2e -d '4 0'
2796 $ hg ci -m h2e -d '4 0'
2785
2797
2786 $ hg merge -q
2798 $ hg merge -q
2787 $ hg ci -m merge -d '5 -3600'
2799 $ hg ci -m merge -d '5 -3600'
2788
2800
2789 No tag set:
2801 No tag set:
2790
2802
2791 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2803 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2792 5: null+5
2804 5: null+5
2793 4: null+4
2805 4: null+4
2794 3: null+3
2806 3: null+3
2795 2: null+3
2807 2: null+3
2796 1: null+2
2808 1: null+2
2797 0: null+1
2809 0: null+1
2798
2810
2799 One common tag: longest path wins:
2811 One common tag: longest path wins:
2800
2812
2801 $ hg tag -r 1 -m t1 -d '6 0' t1
2813 $ hg tag -r 1 -m t1 -d '6 0' t1
2802 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2814 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2803 6: t1+4
2815 6: t1+4
2804 5: t1+3
2816 5: t1+3
2805 4: t1+2
2817 4: t1+2
2806 3: t1+1
2818 3: t1+1
2807 2: t1+1
2819 2: t1+1
2808 1: t1+0
2820 1: t1+0
2809 0: null+1
2821 0: null+1
2810
2822
2811 One ancestor tag: more recent wins:
2823 One ancestor tag: more recent wins:
2812
2824
2813 $ hg tag -r 2 -m t2 -d '7 0' t2
2825 $ hg tag -r 2 -m t2 -d '7 0' t2
2814 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2826 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2815 7: t2+3
2827 7: t2+3
2816 6: t2+2
2828 6: t2+2
2817 5: t2+1
2829 5: t2+1
2818 4: t1+2
2830 4: t1+2
2819 3: t1+1
2831 3: t1+1
2820 2: t2+0
2832 2: t2+0
2821 1: t1+0
2833 1: t1+0
2822 0: null+1
2834 0: null+1
2823
2835
2824 Two branch tags: more recent wins:
2836 Two branch tags: more recent wins:
2825
2837
2826 $ hg tag -r 3 -m t3 -d '8 0' t3
2838 $ hg tag -r 3 -m t3 -d '8 0' t3
2827 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2839 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2828 8: t3+5
2840 8: t3+5
2829 7: t3+4
2841 7: t3+4
2830 6: t3+3
2842 6: t3+3
2831 5: t3+2
2843 5: t3+2
2832 4: t3+1
2844 4: t3+1
2833 3: t3+0
2845 3: t3+0
2834 2: t2+0
2846 2: t2+0
2835 1: t1+0
2847 1: t1+0
2836 0: null+1
2848 0: null+1
2837
2849
2838 Merged tag overrides:
2850 Merged tag overrides:
2839
2851
2840 $ hg tag -r 5 -m t5 -d '9 0' t5
2852 $ hg tag -r 5 -m t5 -d '9 0' t5
2841 $ hg tag -r 3 -m at3 -d '10 0' at3
2853 $ hg tag -r 3 -m at3 -d '10 0' at3
2842 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2854 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2843 10: t5+5
2855 10: t5+5
2844 9: t5+4
2856 9: t5+4
2845 8: t5+3
2857 8: t5+3
2846 7: t5+2
2858 7: t5+2
2847 6: t5+1
2859 6: t5+1
2848 5: t5+0
2860 5: t5+0
2849 4: at3:t3+1
2861 4: at3:t3+1
2850 3: at3:t3+0
2862 3: at3:t3+0
2851 2: t2+0
2863 2: t2+0
2852 1: t1+0
2864 1: t1+0
2853 0: null+1
2865 0: null+1
2854
2866
2855 $ hg log --template "{rev}: {latesttag % '{tag}+{distance},{changes} '}\n"
2867 $ hg log --template "{rev}: {latesttag % '{tag}+{distance},{changes} '}\n"
2856 10: t5+5,5
2868 10: t5+5,5
2857 9: t5+4,4
2869 9: t5+4,4
2858 8: t5+3,3
2870 8: t5+3,3
2859 7: t5+2,2
2871 7: t5+2,2
2860 6: t5+1,1
2872 6: t5+1,1
2861 5: t5+0,0
2873 5: t5+0,0
2862 4: at3+1,1 t3+1,1
2874 4: at3+1,1 t3+1,1
2863 3: at3+0,0 t3+0,0
2875 3: at3+0,0 t3+0,0
2864 2: t2+0,0
2876 2: t2+0,0
2865 1: t1+0,0
2877 1: t1+0,0
2866 0: null+1,1
2878 0: null+1,1
2867
2879
2868 $ hg log --template "{rev}: {latesttag('re:^t[13]$') % '{tag}, C: {changes}, D: {distance}'}\n"
2880 $ hg log --template "{rev}: {latesttag('re:^t[13]$') % '{tag}, C: {changes}, D: {distance}'}\n"
2869 10: t3, C: 8, D: 7
2881 10: t3, C: 8, D: 7
2870 9: t3, C: 7, D: 6
2882 9: t3, C: 7, D: 6
2871 8: t3, C: 6, D: 5
2883 8: t3, C: 6, D: 5
2872 7: t3, C: 5, D: 4
2884 7: t3, C: 5, D: 4
2873 6: t3, C: 4, D: 3
2885 6: t3, C: 4, D: 3
2874 5: t3, C: 3, D: 2
2886 5: t3, C: 3, D: 2
2875 4: t3, C: 1, D: 1
2887 4: t3, C: 1, D: 1
2876 3: t3, C: 0, D: 0
2888 3: t3, C: 0, D: 0
2877 2: t1, C: 1, D: 1
2889 2: t1, C: 1, D: 1
2878 1: t1, C: 0, D: 0
2890 1: t1, C: 0, D: 0
2879 0: null, C: 1, D: 1
2891 0: null, C: 1, D: 1
2880
2892
2881 $ cd ..
2893 $ cd ..
2882
2894
2883
2895
2884 Style path expansion: issue1948 - ui.style option doesn't work on OSX
2896 Style path expansion: issue1948 - ui.style option doesn't work on OSX
2885 if it is a relative path
2897 if it is a relative path
2886
2898
2887 $ mkdir -p home/styles
2899 $ mkdir -p home/styles
2888
2900
2889 $ cat > home/styles/teststyle <<EOF
2901 $ cat > home/styles/teststyle <<EOF
2890 > changeset = 'test {rev}:{node|short}\n'
2902 > changeset = 'test {rev}:{node|short}\n'
2891 > EOF
2903 > EOF
2892
2904
2893 $ HOME=`pwd`/home; export HOME
2905 $ HOME=`pwd`/home; export HOME
2894
2906
2895 $ cat > latesttag/.hg/hgrc <<EOF
2907 $ cat > latesttag/.hg/hgrc <<EOF
2896 > [ui]
2908 > [ui]
2897 > style = ~/styles/teststyle
2909 > style = ~/styles/teststyle
2898 > EOF
2910 > EOF
2899
2911
2900 $ hg -R latesttag tip
2912 $ hg -R latesttag tip
2901 test 10:9b4a630e5f5f
2913 test 10:9b4a630e5f5f
2902
2914
2903 Test recursive showlist template (issue1989):
2915 Test recursive showlist template (issue1989):
2904
2916
2905 $ cat > style1989 <<EOF
2917 $ cat > style1989 <<EOF
2906 > changeset = '{file_mods}{manifest}{extras}'
2918 > changeset = '{file_mods}{manifest}{extras}'
2907 > file_mod = 'M|{author|person}\n'
2919 > file_mod = 'M|{author|person}\n'
2908 > manifest = '{rev},{author}\n'
2920 > manifest = '{rev},{author}\n'
2909 > extra = '{key}: {author}\n'
2921 > extra = '{key}: {author}\n'
2910 > EOF
2922 > EOF
2911
2923
2912 $ hg -R latesttag log -r tip --style=style1989
2924 $ hg -R latesttag log -r tip --style=style1989
2913 M|test
2925 M|test
2914 10,test
2926 10,test
2915 branch: test
2927 branch: test
2916
2928
2917 Test new-style inline templating:
2929 Test new-style inline templating:
2918
2930
2919 $ hg log -R latesttag -r tip --template 'modified files: {file_mods % " {file}\n"}\n'
2931 $ hg log -R latesttag -r tip --template 'modified files: {file_mods % " {file}\n"}\n'
2920 modified files: .hgtags
2932 modified files: .hgtags
2921
2933
2922
2934
2923 $ hg log -R latesttag -r tip -T '{rev % "a"}\n'
2935 $ hg log -R latesttag -r tip -T '{rev % "a"}\n'
2924 hg: parse error: keyword 'rev' is not iterable
2936 hg: parse error: keyword 'rev' is not iterable
2925 [255]
2937 [255]
2926 $ hg log -R latesttag -r tip -T '{get(extras, "unknown") % "a"}\n'
2938 $ hg log -R latesttag -r tip -T '{get(extras, "unknown") % "a"}\n'
2927 hg: parse error: None is not iterable
2939 hg: parse error: None is not iterable
2928 [255]
2940 [255]
2929
2941
2930 Test the sub function of templating for expansion:
2942 Test the sub function of templating for expansion:
2931
2943
2932 $ hg log -R latesttag -r 10 --template '{sub("[0-9]", "x", "{rev}")}\n'
2944 $ hg log -R latesttag -r 10 --template '{sub("[0-9]", "x", "{rev}")}\n'
2933 xx
2945 xx
2934
2946
2935 $ hg log -R latesttag -r 10 -T '{sub("[", "x", rev)}\n'
2947 $ hg log -R latesttag -r 10 -T '{sub("[", "x", rev)}\n'
2936 hg: parse error: sub got an invalid pattern: [
2948 hg: parse error: sub got an invalid pattern: [
2937 [255]
2949 [255]
2938 $ hg log -R latesttag -r 10 -T '{sub("[0-9]", r"\1", rev)}\n'
2950 $ hg log -R latesttag -r 10 -T '{sub("[0-9]", r"\1", rev)}\n'
2939 hg: parse error: sub got an invalid replacement: \1
2951 hg: parse error: sub got an invalid replacement: \1
2940 [255]
2952 [255]
2941
2953
2942 Test the strip function with chars specified:
2954 Test the strip function with chars specified:
2943
2955
2944 $ hg log -R latesttag --template '{desc}\n'
2956 $ hg log -R latesttag --template '{desc}\n'
2945 at3
2957 at3
2946 t5
2958 t5
2947 t3
2959 t3
2948 t2
2960 t2
2949 t1
2961 t1
2950 merge
2962 merge
2951 h2e
2963 h2e
2952 h2d
2964 h2d
2953 h1c
2965 h1c
2954 b
2966 b
2955 a
2967 a
2956
2968
2957 $ hg log -R latesttag --template '{strip(desc, "te")}\n'
2969 $ hg log -R latesttag --template '{strip(desc, "te")}\n'
2958 at3
2970 at3
2959 5
2971 5
2960 3
2972 3
2961 2
2973 2
2962 1
2974 1
2963 merg
2975 merg
2964 h2
2976 h2
2965 h2d
2977 h2d
2966 h1c
2978 h1c
2967 b
2979 b
2968 a
2980 a
2969
2981
2970 Test date format:
2982 Test date format:
2971
2983
2972 $ hg log -R latesttag --template 'date: {date(date, "%y %m %d %S %z")}\n'
2984 $ hg log -R latesttag --template 'date: {date(date, "%y %m %d %S %z")}\n'
2973 date: 70 01 01 10 +0000
2985 date: 70 01 01 10 +0000
2974 date: 70 01 01 09 +0000
2986 date: 70 01 01 09 +0000
2975 date: 70 01 01 08 +0000
2987 date: 70 01 01 08 +0000
2976 date: 70 01 01 07 +0000
2988 date: 70 01 01 07 +0000
2977 date: 70 01 01 06 +0000
2989 date: 70 01 01 06 +0000
2978 date: 70 01 01 05 +0100
2990 date: 70 01 01 05 +0100
2979 date: 70 01 01 04 +0000
2991 date: 70 01 01 04 +0000
2980 date: 70 01 01 03 +0000
2992 date: 70 01 01 03 +0000
2981 date: 70 01 01 02 +0000
2993 date: 70 01 01 02 +0000
2982 date: 70 01 01 01 +0000
2994 date: 70 01 01 01 +0000
2983 date: 70 01 01 00 +0000
2995 date: 70 01 01 00 +0000
2984
2996
2985 Test invalid date:
2997 Test invalid date:
2986
2998
2987 $ hg log -R latesttag -T '{date(rev)}\n'
2999 $ hg log -R latesttag -T '{date(rev)}\n'
2988 hg: parse error: date expects a date information
3000 hg: parse error: date expects a date information
2989 [255]
3001 [255]
2990
3002
2991 Test integer literal:
3003 Test integer literal:
2992
3004
2993 $ hg debugtemplate -v '{(0)}\n'
3005 $ hg debugtemplate -v '{(0)}\n'
2994 (template
3006 (template
2995 (group
3007 (group
2996 ('integer', '0'))
3008 ('integer', '0'))
2997 ('string', '\n'))
3009 ('string', '\n'))
2998 0
3010 0
2999 $ hg debugtemplate -v '{(123)}\n'
3011 $ hg debugtemplate -v '{(123)}\n'
3000 (template
3012 (template
3001 (group
3013 (group
3002 ('integer', '123'))
3014 ('integer', '123'))
3003 ('string', '\n'))
3015 ('string', '\n'))
3004 123
3016 123
3005 $ hg debugtemplate -v '{(-4)}\n'
3017 $ hg debugtemplate -v '{(-4)}\n'
3006 (template
3018 (template
3007 (group
3019 (group
3008 (negate
3020 (negate
3009 ('integer', '4')))
3021 ('integer', '4')))
3010 ('string', '\n'))
3022 ('string', '\n'))
3011 -4
3023 -4
3012 $ hg debugtemplate '{(-)}\n'
3024 $ hg debugtemplate '{(-)}\n'
3013 hg: parse error at 3: not a prefix: )
3025 hg: parse error at 3: not a prefix: )
3014 [255]
3026 [255]
3015 $ hg debugtemplate '{(-a)}\n'
3027 $ hg debugtemplate '{(-a)}\n'
3016 hg: parse error: negation needs an integer argument
3028 hg: parse error: negation needs an integer argument
3017 [255]
3029 [255]
3018
3030
3019 top-level integer literal is interpreted as symbol (i.e. variable name):
3031 top-level integer literal is interpreted as symbol (i.e. variable name):
3020
3032
3021 $ hg debugtemplate -D 1=one -v '{1}\n'
3033 $ hg debugtemplate -D 1=one -v '{1}\n'
3022 (template
3034 (template
3023 ('integer', '1')
3035 ('integer', '1')
3024 ('string', '\n'))
3036 ('string', '\n'))
3025 one
3037 one
3026 $ hg debugtemplate -D 1=one -v '{if("t", "{1}")}\n'
3038 $ hg debugtemplate -D 1=one -v '{if("t", "{1}")}\n'
3027 (template
3039 (template
3028 (func
3040 (func
3029 ('symbol', 'if')
3041 ('symbol', 'if')
3030 (list
3042 (list
3031 ('string', 't')
3043 ('string', 't')
3032 (template
3044 (template
3033 ('integer', '1'))))
3045 ('integer', '1'))))
3034 ('string', '\n'))
3046 ('string', '\n'))
3035 one
3047 one
3036 $ hg debugtemplate -D 1=one -v '{1|stringify}\n'
3048 $ hg debugtemplate -D 1=one -v '{1|stringify}\n'
3037 (template
3049 (template
3038 (|
3050 (|
3039 ('integer', '1')
3051 ('integer', '1')
3040 ('symbol', 'stringify'))
3052 ('symbol', 'stringify'))
3041 ('string', '\n'))
3053 ('string', '\n'))
3042 one
3054 one
3043
3055
3044 unless explicit symbol is expected:
3056 unless explicit symbol is expected:
3045
3057
3046 $ hg log -Ra -r0 -T '{desc|1}\n'
3058 $ hg log -Ra -r0 -T '{desc|1}\n'
3047 hg: parse error: expected a symbol, got 'integer'
3059 hg: parse error: expected a symbol, got 'integer'
3048 [255]
3060 [255]
3049 $ hg log -Ra -r0 -T '{1()}\n'
3061 $ hg log -Ra -r0 -T '{1()}\n'
3050 hg: parse error: expected a symbol, got 'integer'
3062 hg: parse error: expected a symbol, got 'integer'
3051 [255]
3063 [255]
3052
3064
3053 Test string literal:
3065 Test string literal:
3054
3066
3055 $ hg debugtemplate -Ra -r0 -v '{"string with no template fragment"}\n'
3067 $ hg debugtemplate -Ra -r0 -v '{"string with no template fragment"}\n'
3056 (template
3068 (template
3057 ('string', 'string with no template fragment')
3069 ('string', 'string with no template fragment')
3058 ('string', '\n'))
3070 ('string', '\n'))
3059 string with no template fragment
3071 string with no template fragment
3060 $ hg debugtemplate -Ra -r0 -v '{"template: {rev}"}\n'
3072 $ hg debugtemplate -Ra -r0 -v '{"template: {rev}"}\n'
3061 (template
3073 (template
3062 (template
3074 (template
3063 ('string', 'template: ')
3075 ('string', 'template: ')
3064 ('symbol', 'rev'))
3076 ('symbol', 'rev'))
3065 ('string', '\n'))
3077 ('string', '\n'))
3066 template: 0
3078 template: 0
3067 $ hg debugtemplate -Ra -r0 -v '{r"rawstring: {rev}"}\n'
3079 $ hg debugtemplate -Ra -r0 -v '{r"rawstring: {rev}"}\n'
3068 (template
3080 (template
3069 ('string', 'rawstring: {rev}')
3081 ('string', 'rawstring: {rev}')
3070 ('string', '\n'))
3082 ('string', '\n'))
3071 rawstring: {rev}
3083 rawstring: {rev}
3072 $ hg debugtemplate -Ra -r0 -v '{files % r"rawstring: {file}"}\n'
3084 $ hg debugtemplate -Ra -r0 -v '{files % r"rawstring: {file}"}\n'
3073 (template
3085 (template
3074 (%
3086 (%
3075 ('symbol', 'files')
3087 ('symbol', 'files')
3076 ('string', 'rawstring: {file}'))
3088 ('string', 'rawstring: {file}'))
3077 ('string', '\n'))
3089 ('string', '\n'))
3078 rawstring: {file}
3090 rawstring: {file}
3079
3091
3080 Test string escaping:
3092 Test string escaping:
3081
3093
3082 $ hg log -R latesttag -r 0 --template '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
3094 $ hg log -R latesttag -r 0 --template '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
3083 >
3095 >
3084 <>\n<[>
3096 <>\n<[>
3085 <>\n<]>
3097 <>\n<]>
3086 <>\n<
3098 <>\n<
3087
3099
3088 $ hg log -R latesttag -r 0 \
3100 $ hg log -R latesttag -r 0 \
3089 > --config ui.logtemplate='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
3101 > --config ui.logtemplate='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
3090 >
3102 >
3091 <>\n<[>
3103 <>\n<[>
3092 <>\n<]>
3104 <>\n<]>
3093 <>\n<
3105 <>\n<
3094
3106
3095 $ hg log -R latesttag -r 0 -T esc \
3107 $ hg log -R latesttag -r 0 -T esc \
3096 > --config templates.esc='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
3108 > --config templates.esc='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
3097 >
3109 >
3098 <>\n<[>
3110 <>\n<[>
3099 <>\n<]>
3111 <>\n<]>
3100 <>\n<
3112 <>\n<
3101
3113
3102 $ cat <<'EOF' > esctmpl
3114 $ cat <<'EOF' > esctmpl
3103 > changeset = '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
3115 > changeset = '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
3104 > EOF
3116 > EOF
3105 $ hg log -R latesttag -r 0 --style ./esctmpl
3117 $ hg log -R latesttag -r 0 --style ./esctmpl
3106 >
3118 >
3107 <>\n<[>
3119 <>\n<[>
3108 <>\n<]>
3120 <>\n<]>
3109 <>\n<
3121 <>\n<
3110
3122
3111 Test string escaping of quotes:
3123 Test string escaping of quotes:
3112
3124
3113 $ hg log -Ra -r0 -T '{"\""}\n'
3125 $ hg log -Ra -r0 -T '{"\""}\n'
3114 "
3126 "
3115 $ hg log -Ra -r0 -T '{"\\\""}\n'
3127 $ hg log -Ra -r0 -T '{"\\\""}\n'
3116 \"
3128 \"
3117 $ hg log -Ra -r0 -T '{r"\""}\n'
3129 $ hg log -Ra -r0 -T '{r"\""}\n'
3118 \"
3130 \"
3119 $ hg log -Ra -r0 -T '{r"\\\""}\n'
3131 $ hg log -Ra -r0 -T '{r"\\\""}\n'
3120 \\\"
3132 \\\"
3121
3133
3122
3134
3123 $ hg log -Ra -r0 -T '{"\""}\n'
3135 $ hg log -Ra -r0 -T '{"\""}\n'
3124 "
3136 "
3125 $ hg log -Ra -r0 -T '{"\\\""}\n'
3137 $ hg log -Ra -r0 -T '{"\\\""}\n'
3126 \"
3138 \"
3127 $ hg log -Ra -r0 -T '{r"\""}\n'
3139 $ hg log -Ra -r0 -T '{r"\""}\n'
3128 \"
3140 \"
3129 $ hg log -Ra -r0 -T '{r"\\\""}\n'
3141 $ hg log -Ra -r0 -T '{r"\\\""}\n'
3130 \\\"
3142 \\\"
3131
3143
3132 Test exception in quoted template. single backslash before quotation mark is
3144 Test exception in quoted template. single backslash before quotation mark is
3133 stripped before parsing:
3145 stripped before parsing:
3134
3146
3135 $ cat <<'EOF' > escquotetmpl
3147 $ cat <<'EOF' > escquotetmpl
3136 > changeset = "\" \\" \\\" \\\\" {files % \"{file}\"}\n"
3148 > changeset = "\" \\" \\\" \\\\" {files % \"{file}\"}\n"
3137 > EOF
3149 > EOF
3138 $ cd latesttag
3150 $ cd latesttag
3139 $ hg log -r 2 --style ../escquotetmpl
3151 $ hg log -r 2 --style ../escquotetmpl
3140 " \" \" \\" head1
3152 " \" \" \\" head1
3141
3153
3142 $ hg log -r 2 -T esc --config templates.esc='"{\"valid\"}\n"'
3154 $ hg log -r 2 -T esc --config templates.esc='"{\"valid\"}\n"'
3143 valid
3155 valid
3144 $ hg log -r 2 -T esc --config templates.esc="'"'{\'"'"'valid\'"'"'}\n'"'"
3156 $ hg log -r 2 -T esc --config templates.esc="'"'{\'"'"'valid\'"'"'}\n'"'"
3145 valid
3157 valid
3146
3158
3147 Test compatibility with 2.9.2-3.4 of escaped quoted strings in nested
3159 Test compatibility with 2.9.2-3.4 of escaped quoted strings in nested
3148 _evalifliteral() templates (issue4733):
3160 _evalifliteral() templates (issue4733):
3149
3161
3150 $ hg log -r 2 -T '{if(rev, "\"{rev}")}\n'
3162 $ hg log -r 2 -T '{if(rev, "\"{rev}")}\n'
3151 "2
3163 "2
3152 $ hg log -r 2 -T '{if(rev, "{if(rev, \"\\\"{rev}\")}")}\n'
3164 $ hg log -r 2 -T '{if(rev, "{if(rev, \"\\\"{rev}\")}")}\n'
3153 "2
3165 "2
3154 $ hg log -r 2 -T '{if(rev, "{if(rev, \"{if(rev, \\\"\\\\\\\"{rev}\\\")}\")}")}\n'
3166 $ hg log -r 2 -T '{if(rev, "{if(rev, \"{if(rev, \\\"\\\\\\\"{rev}\\\")}\")}")}\n'
3155 "2
3167 "2
3156
3168
3157 $ hg log -r 2 -T '{if(rev, "\\\"")}\n'
3169 $ hg log -r 2 -T '{if(rev, "\\\"")}\n'
3158 \"
3170 \"
3159 $ hg log -r 2 -T '{if(rev, "{if(rev, \"\\\\\\\"\")}")}\n'
3171 $ hg log -r 2 -T '{if(rev, "{if(rev, \"\\\\\\\"\")}")}\n'
3160 \"
3172 \"
3161 $ hg log -r 2 -T '{if(rev, "{if(rev, \"{if(rev, \\\"\\\\\\\\\\\\\\\"\\\")}\")}")}\n'
3173 $ hg log -r 2 -T '{if(rev, "{if(rev, \"{if(rev, \\\"\\\\\\\\\\\\\\\"\\\")}\")}")}\n'
3162 \"
3174 \"
3163
3175
3164 $ hg log -r 2 -T '{if(rev, r"\\\"")}\n'
3176 $ hg log -r 2 -T '{if(rev, r"\\\"")}\n'
3165 \\\"
3177 \\\"
3166 $ hg log -r 2 -T '{if(rev, "{if(rev, r\"\\\\\\\"\")}")}\n'
3178 $ hg log -r 2 -T '{if(rev, "{if(rev, r\"\\\\\\\"\")}")}\n'
3167 \\\"
3179 \\\"
3168 $ hg log -r 2 -T '{if(rev, "{if(rev, \"{if(rev, r\\\"\\\\\\\\\\\\\\\"\\\")}\")}")}\n'
3180 $ hg log -r 2 -T '{if(rev, "{if(rev, \"{if(rev, r\\\"\\\\\\\\\\\\\\\"\\\")}\")}")}\n'
3169 \\\"
3181 \\\"
3170
3182
3171 escaped single quotes and errors:
3183 escaped single quotes and errors:
3172
3184
3173 $ hg log -r 2 -T "{if(rev, '{if(rev, \'foo\')}')}"'\n'
3185 $ hg log -r 2 -T "{if(rev, '{if(rev, \'foo\')}')}"'\n'
3174 foo
3186 foo
3175 $ hg log -r 2 -T "{if(rev, '{if(rev, r\'foo\')}')}"'\n'
3187 $ hg log -r 2 -T "{if(rev, '{if(rev, r\'foo\')}')}"'\n'
3176 foo
3188 foo
3177 $ hg log -r 2 -T '{if(rev, "{if(rev, \")}")}\n'
3189 $ hg log -r 2 -T '{if(rev, "{if(rev, \")}")}\n'
3178 hg: parse error at 21: unterminated string
3190 hg: parse error at 21: unterminated string
3179 [255]
3191 [255]
3180 $ hg log -r 2 -T '{if(rev, \"\\"")}\n'
3192 $ hg log -r 2 -T '{if(rev, \"\\"")}\n'
3181 hg: parse error: trailing \ in string
3193 hg: parse error: trailing \ in string
3182 [255]
3194 [255]
3183 $ hg log -r 2 -T '{if(rev, r\"\\"")}\n'
3195 $ hg log -r 2 -T '{if(rev, r\"\\"")}\n'
3184 hg: parse error: trailing \ in string
3196 hg: parse error: trailing \ in string
3185 [255]
3197 [255]
3186
3198
3187 $ cd ..
3199 $ cd ..
3188
3200
3189 Test leading backslashes:
3201 Test leading backslashes:
3190
3202
3191 $ cd latesttag
3203 $ cd latesttag
3192 $ hg log -r 2 -T '\{rev} {files % "\{file}"}\n'
3204 $ hg log -r 2 -T '\{rev} {files % "\{file}"}\n'
3193 {rev} {file}
3205 {rev} {file}
3194 $ hg log -r 2 -T '\\{rev} {files % "\\{file}"}\n'
3206 $ hg log -r 2 -T '\\{rev} {files % "\\{file}"}\n'
3195 \2 \head1
3207 \2 \head1
3196 $ hg log -r 2 -T '\\\{rev} {files % "\\\{file}"}\n'
3208 $ hg log -r 2 -T '\\\{rev} {files % "\\\{file}"}\n'
3197 \{rev} \{file}
3209 \{rev} \{file}
3198 $ cd ..
3210 $ cd ..
3199
3211
3200 Test leading backslashes in "if" expression (issue4714):
3212 Test leading backslashes in "if" expression (issue4714):
3201
3213
3202 $ cd latesttag
3214 $ cd latesttag
3203 $ hg log -r 2 -T '{if("1", "\{rev}")} {if("1", r"\{rev}")}\n'
3215 $ hg log -r 2 -T '{if("1", "\{rev}")} {if("1", r"\{rev}")}\n'
3204 {rev} \{rev}
3216 {rev} \{rev}
3205 $ hg log -r 2 -T '{if("1", "\\{rev}")} {if("1", r"\\{rev}")}\n'
3217 $ hg log -r 2 -T '{if("1", "\\{rev}")} {if("1", r"\\{rev}")}\n'
3206 \2 \\{rev}
3218 \2 \\{rev}
3207 $ hg log -r 2 -T '{if("1", "\\\{rev}")} {if("1", r"\\\{rev}")}\n'
3219 $ hg log -r 2 -T '{if("1", "\\\{rev}")} {if("1", r"\\\{rev}")}\n'
3208 \{rev} \\\{rev}
3220 \{rev} \\\{rev}
3209 $ cd ..
3221 $ cd ..
3210
3222
3211 "string-escape"-ed "\x5c\x786e" becomes r"\x6e" (once) or r"n" (twice)
3223 "string-escape"-ed "\x5c\x786e" becomes r"\x6e" (once) or r"n" (twice)
3212
3224
3213 $ hg log -R a -r 0 --template '{if("1", "\x5c\x786e", "NG")}\n'
3225 $ hg log -R a -r 0 --template '{if("1", "\x5c\x786e", "NG")}\n'
3214 \x6e
3226 \x6e
3215 $ hg log -R a -r 0 --template '{if("1", r"\x5c\x786e", "NG")}\n'
3227 $ hg log -R a -r 0 --template '{if("1", r"\x5c\x786e", "NG")}\n'
3216 \x5c\x786e
3228 \x5c\x786e
3217 $ hg log -R a -r 0 --template '{if("", "NG", "\x5c\x786e")}\n'
3229 $ hg log -R a -r 0 --template '{if("", "NG", "\x5c\x786e")}\n'
3218 \x6e
3230 \x6e
3219 $ hg log -R a -r 0 --template '{if("", "NG", r"\x5c\x786e")}\n'
3231 $ hg log -R a -r 0 --template '{if("", "NG", r"\x5c\x786e")}\n'
3220 \x5c\x786e
3232 \x5c\x786e
3221
3233
3222 $ hg log -R a -r 2 --template '{ifeq("no perso\x6e", desc, "\x5c\x786e", "NG")}\n'
3234 $ hg log -R a -r 2 --template '{ifeq("no perso\x6e", desc, "\x5c\x786e", "NG")}\n'
3223 \x6e
3235 \x6e
3224 $ hg log -R a -r 2 --template '{ifeq(r"no perso\x6e", desc, "NG", r"\x5c\x786e")}\n'
3236 $ hg log -R a -r 2 --template '{ifeq(r"no perso\x6e", desc, "NG", r"\x5c\x786e")}\n'
3225 \x5c\x786e
3237 \x5c\x786e
3226 $ hg log -R a -r 2 --template '{ifeq(desc, "no perso\x6e", "\x5c\x786e", "NG")}\n'
3238 $ hg log -R a -r 2 --template '{ifeq(desc, "no perso\x6e", "\x5c\x786e", "NG")}\n'
3227 \x6e
3239 \x6e
3228 $ hg log -R a -r 2 --template '{ifeq(desc, r"no perso\x6e", "NG", r"\x5c\x786e")}\n'
3240 $ hg log -R a -r 2 --template '{ifeq(desc, r"no perso\x6e", "NG", r"\x5c\x786e")}\n'
3229 \x5c\x786e
3241 \x5c\x786e
3230
3242
3231 $ hg log -R a -r 8 --template '{join(files, "\n")}\n'
3243 $ hg log -R a -r 8 --template '{join(files, "\n")}\n'
3232 fourth
3244 fourth
3233 second
3245 second
3234 third
3246 third
3235 $ hg log -R a -r 8 --template '{join(files, r"\n")}\n'
3247 $ hg log -R a -r 8 --template '{join(files, r"\n")}\n'
3236 fourth\nsecond\nthird
3248 fourth\nsecond\nthird
3237
3249
3238 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", "htm\x6c")}'
3250 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", "htm\x6c")}'
3239 <p>
3251 <p>
3240 1st
3252 1st
3241 </p>
3253 </p>
3242 <p>
3254 <p>
3243 2nd
3255 2nd
3244 </p>
3256 </p>
3245 $ hg log -R a -r 2 --template '{rstdoc(r"1st\n\n2nd", "html")}'
3257 $ hg log -R a -r 2 --template '{rstdoc(r"1st\n\n2nd", "html")}'
3246 <p>
3258 <p>
3247 1st\n\n2nd
3259 1st\n\n2nd
3248 </p>
3260 </p>
3249 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", r"htm\x6c")}'
3261 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", r"htm\x6c")}'
3250 1st
3262 1st
3251
3263
3252 2nd
3264 2nd
3253
3265
3254 $ hg log -R a -r 2 --template '{strip(desc, "\x6e")}\n'
3266 $ hg log -R a -r 2 --template '{strip(desc, "\x6e")}\n'
3255 o perso
3267 o perso
3256 $ hg log -R a -r 2 --template '{strip(desc, r"\x6e")}\n'
3268 $ hg log -R a -r 2 --template '{strip(desc, r"\x6e")}\n'
3257 no person
3269 no person
3258 $ hg log -R a -r 2 --template '{strip("no perso\x6e", "\x6e")}\n'
3270 $ hg log -R a -r 2 --template '{strip("no perso\x6e", "\x6e")}\n'
3259 o perso
3271 o perso
3260 $ hg log -R a -r 2 --template '{strip(r"no perso\x6e", r"\x6e")}\n'
3272 $ hg log -R a -r 2 --template '{strip(r"no perso\x6e", r"\x6e")}\n'
3261 no perso
3273 no perso
3262
3274
3263 $ hg log -R a -r 2 --template '{sub("\\x6e", "\x2d", desc)}\n'
3275 $ hg log -R a -r 2 --template '{sub("\\x6e", "\x2d", desc)}\n'
3264 -o perso-
3276 -o perso-
3265 $ hg log -R a -r 2 --template '{sub(r"\\x6e", "-", desc)}\n'
3277 $ hg log -R a -r 2 --template '{sub(r"\\x6e", "-", desc)}\n'
3266 no person
3278 no person
3267 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", desc)}\n'
3279 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", desc)}\n'
3268 \x2do perso\x2d
3280 \x2do perso\x2d
3269 $ hg log -R a -r 2 --template '{sub("n", "\x2d", "no perso\x6e")}\n'
3281 $ hg log -R a -r 2 --template '{sub("n", "\x2d", "no perso\x6e")}\n'
3270 -o perso-
3282 -o perso-
3271 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", r"no perso\x6e")}\n'
3283 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", r"no perso\x6e")}\n'
3272 \x2do perso\x6e
3284 \x2do perso\x6e
3273
3285
3274 $ hg log -R a -r 8 --template '{files % "{file}\n"}'
3286 $ hg log -R a -r 8 --template '{files % "{file}\n"}'
3275 fourth
3287 fourth
3276 second
3288 second
3277 third
3289 third
3278
3290
3279 Test string escaping in nested expression:
3291 Test string escaping in nested expression:
3280
3292
3281 $ hg log -R a -r 8 --template '{ifeq(r"\x6e", if("1", "\x5c\x786e"), join(files, "\x5c\x786e"))}\n'
3293 $ hg log -R a -r 8 --template '{ifeq(r"\x6e", if("1", "\x5c\x786e"), join(files, "\x5c\x786e"))}\n'
3282 fourth\x6esecond\x6ethird
3294 fourth\x6esecond\x6ethird
3283 $ hg log -R a -r 8 --template '{ifeq(if("1", r"\x6e"), "\x5c\x786e", join(files, "\x5c\x786e"))}\n'
3295 $ hg log -R a -r 8 --template '{ifeq(if("1", r"\x6e"), "\x5c\x786e", join(files, "\x5c\x786e"))}\n'
3284 fourth\x6esecond\x6ethird
3296 fourth\x6esecond\x6ethird
3285
3297
3286 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", "\x5c\x786e"))}\n'
3298 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", "\x5c\x786e"))}\n'
3287 fourth\x6esecond\x6ethird
3299 fourth\x6esecond\x6ethird
3288 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", r"\x5c\x786e"))}\n'
3300 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", r"\x5c\x786e"))}\n'
3289 fourth\x5c\x786esecond\x5c\x786ethird
3301 fourth\x5c\x786esecond\x5c\x786ethird
3290
3302
3291 $ hg log -R a -r 3:4 --template '{rev}:{sub(if("1", "\x6e"), ifeq(branch, "foo", r"\x5c\x786e", "\x5c\x786e"), desc)}\n'
3303 $ hg log -R a -r 3:4 --template '{rev}:{sub(if("1", "\x6e"), ifeq(branch, "foo", r"\x5c\x786e", "\x5c\x786e"), desc)}\n'
3292 3:\x6eo user, \x6eo domai\x6e
3304 3:\x6eo user, \x6eo domai\x6e
3293 4:\x5c\x786eew bra\x5c\x786ech
3305 4:\x5c\x786eew bra\x5c\x786ech
3294
3306
3295 Test quotes in nested expression are evaluated just like a $(command)
3307 Test quotes in nested expression are evaluated just like a $(command)
3296 substitution in POSIX shells:
3308 substitution in POSIX shells:
3297
3309
3298 $ hg log -R a -r 8 -T '{"{"{rev}:{node|short}"}"}\n'
3310 $ hg log -R a -r 8 -T '{"{"{rev}:{node|short}"}"}\n'
3299 8:95c24699272e
3311 8:95c24699272e
3300 $ hg log -R a -r 8 -T '{"{"\{{rev}} \"{node|short}\""}"}\n'
3312 $ hg log -R a -r 8 -T '{"{"\{{rev}} \"{node|short}\""}"}\n'
3301 {8} "95c24699272e"
3313 {8} "95c24699272e"
3302
3314
3303 Test recursive evaluation:
3315 Test recursive evaluation:
3304
3316
3305 $ hg init r
3317 $ hg init r
3306 $ cd r
3318 $ cd r
3307 $ echo a > a
3319 $ echo a > a
3308 $ hg ci -Am '{rev}'
3320 $ hg ci -Am '{rev}'
3309 adding a
3321 adding a
3310 $ hg log -r 0 --template '{if(rev, desc)}\n'
3322 $ hg log -r 0 --template '{if(rev, desc)}\n'
3311 {rev}
3323 {rev}
3312 $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n'
3324 $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n'
3313 test 0
3325 test 0
3314
3326
3315 $ hg branch -q 'text.{rev}'
3327 $ hg branch -q 'text.{rev}'
3316 $ echo aa >> aa
3328 $ echo aa >> aa
3317 $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
3329 $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
3318
3330
3319 $ hg log -l1 --template '{fill(desc, "20", author, branch)}'
3331 $ hg log -l1 --template '{fill(desc, "20", author, branch)}'
3320 {node|short}desc to
3332 {node|short}desc to
3321 text.{rev}be wrapped
3333 text.{rev}be wrapped
3322 text.{rev}desc to be
3334 text.{rev}desc to be
3323 text.{rev}wrapped (no-eol)
3335 text.{rev}wrapped (no-eol)
3324 $ hg log -l1 --template '{fill(desc, "20", "{node|short}:", "text.{rev}:")}'
3336 $ hg log -l1 --template '{fill(desc, "20", "{node|short}:", "text.{rev}:")}'
3325 bcc7ff960b8e:desc to
3337 bcc7ff960b8e:desc to
3326 text.1:be wrapped
3338 text.1:be wrapped
3327 text.1:desc to be
3339 text.1:desc to be
3328 text.1:wrapped (no-eol)
3340 text.1:wrapped (no-eol)
3329 $ hg log -l1 -T '{fill(desc, date, "", "")}\n'
3341 $ hg log -l1 -T '{fill(desc, date, "", "")}\n'
3330 hg: parse error: fill expects an integer width
3342 hg: parse error: fill expects an integer width
3331 [255]
3343 [255]
3332
3344
3333 $ COLUMNS=25 hg log -l1 --template '{fill(desc, termwidth, "{node|short}:", "termwidth.{rev}:")}'
3345 $ COLUMNS=25 hg log -l1 --template '{fill(desc, termwidth, "{node|short}:", "termwidth.{rev}:")}'
3334 bcc7ff960b8e:desc to be
3346 bcc7ff960b8e:desc to be
3335 termwidth.1:wrapped desc
3347 termwidth.1:wrapped desc
3336 termwidth.1:to be wrapped (no-eol)
3348 termwidth.1:to be wrapped (no-eol)
3337
3349
3338 $ hg log -l 1 --template '{sub(r"[0-9]", "-", author)}'
3350 $ hg log -l 1 --template '{sub(r"[0-9]", "-", author)}'
3339 {node|short} (no-eol)
3351 {node|short} (no-eol)
3340 $ hg log -l 1 --template '{sub(r"[0-9]", "-", "{node|short}")}'
3352 $ hg log -l 1 --template '{sub(r"[0-9]", "-", "{node|short}")}'
3341 bcc-ff---b-e (no-eol)
3353 bcc-ff---b-e (no-eol)
3342
3354
3343 $ cat >> .hg/hgrc <<EOF
3355 $ cat >> .hg/hgrc <<EOF
3344 > [extensions]
3356 > [extensions]
3345 > color=
3357 > color=
3346 > [color]
3358 > [color]
3347 > mode=ansi
3359 > mode=ansi
3348 > text.{rev} = red
3360 > text.{rev} = red
3349 > text.1 = green
3361 > text.1 = green
3350 > EOF
3362 > EOF
3351 $ hg log --color=always -l 1 --template '{label(branch, "text\n")}'
3363 $ hg log --color=always -l 1 --template '{label(branch, "text\n")}'
3352 \x1b[0;31mtext\x1b[0m (esc)
3364 \x1b[0;31mtext\x1b[0m (esc)
3353 $ hg log --color=always -l 1 --template '{label("text.{rev}", "text\n")}'
3365 $ hg log --color=always -l 1 --template '{label("text.{rev}", "text\n")}'
3354 \x1b[0;32mtext\x1b[0m (esc)
3366 \x1b[0;32mtext\x1b[0m (esc)
3355
3367
3356 color effect can be specified without quoting:
3368 color effect can be specified without quoting:
3357
3369
3358 $ hg log --color=always -l 1 --template '{label(red, "text\n")}'
3370 $ hg log --color=always -l 1 --template '{label(red, "text\n")}'
3359 \x1b[0;31mtext\x1b[0m (esc)
3371 \x1b[0;31mtext\x1b[0m (esc)
3360
3372
3361 color effects can be nested (issue5413)
3373 color effects can be nested (issue5413)
3362
3374
3363 $ hg debugtemplate --color=always \
3375 $ hg debugtemplate --color=always \
3364 > '{label(red, "red{label(magenta, "ma{label(cyan, "cyan")}{label(yellow, "yellow")}genta")}")}\n'
3376 > '{label(red, "red{label(magenta, "ma{label(cyan, "cyan")}{label(yellow, "yellow")}genta")}")}\n'
3365 \x1b[0;31mred\x1b[0;35mma\x1b[0;36mcyan\x1b[0m\x1b[0;31m\x1b[0;35m\x1b[0;33myellow\x1b[0m\x1b[0;31m\x1b[0;35mgenta\x1b[0m (esc)
3377 \x1b[0;31mred\x1b[0;35mma\x1b[0;36mcyan\x1b[0m\x1b[0;31m\x1b[0;35m\x1b[0;33myellow\x1b[0m\x1b[0;31m\x1b[0;35mgenta\x1b[0m (esc)
3366
3378
3367 pad() should interact well with color codes (issue5416)
3379 pad() should interact well with color codes (issue5416)
3368
3380
3369 $ hg debugtemplate --color=always \
3381 $ hg debugtemplate --color=always \
3370 > '{pad(label(red, "red"), 5, label(cyan, "-"))}\n'
3382 > '{pad(label(red, "red"), 5, label(cyan, "-"))}\n'
3371 \x1b[0;31mred\x1b[0m\x1b[0;36m-\x1b[0m\x1b[0;36m-\x1b[0m (esc)
3383 \x1b[0;31mred\x1b[0m\x1b[0;36m-\x1b[0m\x1b[0;36m-\x1b[0m (esc)
3372
3384
3373 label should be no-op if color is disabled:
3385 label should be no-op if color is disabled:
3374
3386
3375 $ hg log --color=never -l 1 --template '{label(red, "text\n")}'
3387 $ hg log --color=never -l 1 --template '{label(red, "text\n")}'
3376 text
3388 text
3377 $ hg log --config extensions.color=! -l 1 --template '{label(red, "text\n")}'
3389 $ hg log --config extensions.color=! -l 1 --template '{label(red, "text\n")}'
3378 text
3390 text
3379
3391
3380 Test branches inside if statement:
3392 Test branches inside if statement:
3381
3393
3382 $ hg log -r 0 --template '{if(branches, "yes", "no")}\n'
3394 $ hg log -r 0 --template '{if(branches, "yes", "no")}\n'
3383 no
3395 no
3384
3396
3385 Test get function:
3397 Test get function:
3386
3398
3387 $ hg log -r 0 --template '{get(extras, "branch")}\n'
3399 $ hg log -r 0 --template '{get(extras, "branch")}\n'
3388 default
3400 default
3389 $ hg log -r 0 --template '{get(extras, "br{"anch"}")}\n'
3401 $ hg log -r 0 --template '{get(extras, "br{"anch"}")}\n'
3390 default
3402 default
3391 $ hg log -r 0 --template '{get(files, "should_fail")}\n'
3403 $ hg log -r 0 --template '{get(files, "should_fail")}\n'
3392 hg: parse error: get() expects a dict as first argument
3404 hg: parse error: get() expects a dict as first argument
3393 [255]
3405 [255]
3394
3406
3395 Test json filter applied to hybrid object:
3407 Test json filter applied to hybrid object:
3396
3408
3397 $ hg log -r0 -T '{files|json}\n'
3409 $ hg log -r0 -T '{files|json}\n'
3398 ["a"]
3410 ["a"]
3399 $ hg log -r0 -T '{extras|json}\n'
3411 $ hg log -r0 -T '{extras|json}\n'
3400 {"branch": "default"}
3412 {"branch": "default"}
3401
3413
3402 Test localdate(date, tz) function:
3414 Test localdate(date, tz) function:
3403
3415
3404 $ TZ=JST-09 hg log -r0 -T '{date|localdate|isodate}\n'
3416 $ TZ=JST-09 hg log -r0 -T '{date|localdate|isodate}\n'
3405 1970-01-01 09:00 +0900
3417 1970-01-01 09:00 +0900
3406 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "UTC")|isodate}\n'
3418 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "UTC")|isodate}\n'
3407 1970-01-01 00:00 +0000
3419 1970-01-01 00:00 +0000
3408 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "blahUTC")|isodate}\n'
3420 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "blahUTC")|isodate}\n'
3409 hg: parse error: localdate expects a timezone
3421 hg: parse error: localdate expects a timezone
3410 [255]
3422 [255]
3411 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "+0200")|isodate}\n'
3423 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "+0200")|isodate}\n'
3412 1970-01-01 02:00 +0200
3424 1970-01-01 02:00 +0200
3413 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "0")|isodate}\n'
3425 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "0")|isodate}\n'
3414 1970-01-01 00:00 +0000
3426 1970-01-01 00:00 +0000
3415 $ TZ=JST-09 hg log -r0 -T '{localdate(date, 0)|isodate}\n'
3427 $ TZ=JST-09 hg log -r0 -T '{localdate(date, 0)|isodate}\n'
3416 1970-01-01 00:00 +0000
3428 1970-01-01 00:00 +0000
3417 $ hg log -r0 -T '{localdate(date, "invalid")|isodate}\n'
3429 $ hg log -r0 -T '{localdate(date, "invalid")|isodate}\n'
3418 hg: parse error: localdate expects a timezone
3430 hg: parse error: localdate expects a timezone
3419 [255]
3431 [255]
3420 $ hg log -r0 -T '{localdate(date, date)|isodate}\n'
3432 $ hg log -r0 -T '{localdate(date, date)|isodate}\n'
3421 hg: parse error: localdate expects a timezone
3433 hg: parse error: localdate expects a timezone
3422 [255]
3434 [255]
3423
3435
3424 Test shortest(node) function:
3436 Test shortest(node) function:
3425
3437
3426 $ echo b > b
3438 $ echo b > b
3427 $ hg ci -qAm b
3439 $ hg ci -qAm b
3428 $ hg log --template '{shortest(node)}\n'
3440 $ hg log --template '{shortest(node)}\n'
3429 e777
3441 e777
3430 bcc7
3442 bcc7
3431 f776
3443 f776
3432 $ hg log --template '{shortest(node, 10)}\n'
3444 $ hg log --template '{shortest(node, 10)}\n'
3433 e777603221
3445 e777603221
3434 bcc7ff960b
3446 bcc7ff960b
3435 f7769ec2ab
3447 f7769ec2ab
3436 $ hg log --template '{node|shortest}\n' -l1
3448 $ hg log --template '{node|shortest}\n' -l1
3437 e777
3449 e777
3438
3450
3439 $ hg log -r 0 -T '{shortest(node, "1{"0"}")}\n'
3451 $ hg log -r 0 -T '{shortest(node, "1{"0"}")}\n'
3440 f7769ec2ab
3452 f7769ec2ab
3441 $ hg log -r 0 -T '{shortest(node, "not an int")}\n'
3453 $ hg log -r 0 -T '{shortest(node, "not an int")}\n'
3442 hg: parse error: shortest() expects an integer minlength
3454 hg: parse error: shortest() expects an integer minlength
3443 [255]
3455 [255]
3444
3456
3445 $ cd ..
3457 $ cd ..
3446
3458
3447 Test shortest(node) with the repo having short hash collision:
3459 Test shortest(node) with the repo having short hash collision:
3448
3460
3449 $ hg init hashcollision
3461 $ hg init hashcollision
3450 $ cd hashcollision
3462 $ cd hashcollision
3451 $ cat <<EOF >> .hg/hgrc
3463 $ cat <<EOF >> .hg/hgrc
3452 > [experimental]
3464 > [experimental]
3453 > evolution = createmarkers
3465 > evolution = createmarkers
3454 > EOF
3466 > EOF
3455 $ echo 0 > a
3467 $ echo 0 > a
3456 $ hg ci -qAm 0
3468 $ hg ci -qAm 0
3457 $ for i in 17 129 248 242 480 580 617 1057 2857 4025; do
3469 $ for i in 17 129 248 242 480 580 617 1057 2857 4025; do
3458 > hg up -q 0
3470 > hg up -q 0
3459 > echo $i > a
3471 > echo $i > a
3460 > hg ci -qm $i
3472 > hg ci -qm $i
3461 > done
3473 > done
3462 $ hg up -q null
3474 $ hg up -q null
3463 $ hg log -r0: -T '{rev}:{node}\n'
3475 $ hg log -r0: -T '{rev}:{node}\n'
3464 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a
3476 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a
3465 1:11424df6dc1dd4ea255eae2b58eaca7831973bbc
3477 1:11424df6dc1dd4ea255eae2b58eaca7831973bbc
3466 2:11407b3f1b9c3e76a79c1ec5373924df096f0499
3478 2:11407b3f1b9c3e76a79c1ec5373924df096f0499
3467 3:11dd92fe0f39dfdaacdaa5f3997edc533875cfc4
3479 3:11dd92fe0f39dfdaacdaa5f3997edc533875cfc4
3468 4:10776689e627b465361ad5c296a20a487e153ca4
3480 4:10776689e627b465361ad5c296a20a487e153ca4
3469 5:a00be79088084cb3aff086ab799f8790e01a976b
3481 5:a00be79088084cb3aff086ab799f8790e01a976b
3470 6:a0b0acd79b4498d0052993d35a6a748dd51d13e6
3482 6:a0b0acd79b4498d0052993d35a6a748dd51d13e6
3471 7:a0457b3450b8e1b778f1163b31a435802987fe5d
3483 7:a0457b3450b8e1b778f1163b31a435802987fe5d
3472 8:c56256a09cd28e5764f32e8e2810d0f01e2e357a
3484 8:c56256a09cd28e5764f32e8e2810d0f01e2e357a
3473 9:c5623987d205cd6d9d8389bfc40fff9dbb670b48
3485 9:c5623987d205cd6d9d8389bfc40fff9dbb670b48
3474 10:c562ddd9c94164376c20b86b0b4991636a3bf84f
3486 10:c562ddd9c94164376c20b86b0b4991636a3bf84f
3475 $ hg debugobsolete a00be79088084cb3aff086ab799f8790e01a976b
3487 $ hg debugobsolete a00be79088084cb3aff086ab799f8790e01a976b
3476 $ hg debugobsolete c5623987d205cd6d9d8389bfc40fff9dbb670b48
3488 $ hg debugobsolete c5623987d205cd6d9d8389bfc40fff9dbb670b48
3477 $ hg debugobsolete c562ddd9c94164376c20b86b0b4991636a3bf84f
3489 $ hg debugobsolete c562ddd9c94164376c20b86b0b4991636a3bf84f
3478
3490
3479 nodes starting with '11' (we don't have the revision number '11' though)
3491 nodes starting with '11' (we don't have the revision number '11' though)
3480
3492
3481 $ hg log -r 1:3 -T '{rev}:{shortest(node, 0)}\n'
3493 $ hg log -r 1:3 -T '{rev}:{shortest(node, 0)}\n'
3482 1:1142
3494 1:1142
3483 2:1140
3495 2:1140
3484 3:11d
3496 3:11d
3485
3497
3486 '5:a00' is hidden, but still we have two nodes starting with 'a0'
3498 '5:a00' is hidden, but still we have two nodes starting with 'a0'
3487
3499
3488 $ hg log -r 6:7 -T '{rev}:{shortest(node, 0)}\n'
3500 $ hg log -r 6:7 -T '{rev}:{shortest(node, 0)}\n'
3489 6:a0b
3501 6:a0b
3490 7:a04
3502 7:a04
3491
3503
3492 node '10' conflicts with the revision number '10' even if it is hidden
3504 node '10' conflicts with the revision number '10' even if it is hidden
3493 (we could exclude hidden revision numbers, but currently we don't)
3505 (we could exclude hidden revision numbers, but currently we don't)
3494
3506
3495 $ hg log -r 4 -T '{rev}:{shortest(node, 0)}\n'
3507 $ hg log -r 4 -T '{rev}:{shortest(node, 0)}\n'
3496 4:107
3508 4:107
3497 $ hg log -r 4 -T '{rev}:{shortest(node, 0)}\n' --hidden
3509 $ hg log -r 4 -T '{rev}:{shortest(node, 0)}\n' --hidden
3498 4:107
3510 4:107
3499
3511
3500 node 'c562' should be unique if the other 'c562' nodes are hidden
3512 node 'c562' should be unique if the other 'c562' nodes are hidden
3501 (but we don't try the slow path to filter out hidden nodes for now)
3513 (but we don't try the slow path to filter out hidden nodes for now)
3502
3514
3503 $ hg log -r 8 -T '{rev}:{node|shortest}\n'
3515 $ hg log -r 8 -T '{rev}:{node|shortest}\n'
3504 8:c5625
3516 8:c5625
3505 $ hg log -r 8:10 -T '{rev}:{node|shortest}\n' --hidden
3517 $ hg log -r 8:10 -T '{rev}:{node|shortest}\n' --hidden
3506 8:c5625
3518 8:c5625
3507 9:c5623
3519 9:c5623
3508 10:c562d
3520 10:c562d
3509
3521
3510 $ cd ..
3522 $ cd ..
3511
3523
3512 Test pad function
3524 Test pad function
3513
3525
3514 $ cd r
3526 $ cd r
3515
3527
3516 $ hg log --template '{pad(rev, 20)} {author|user}\n'
3528 $ hg log --template '{pad(rev, 20)} {author|user}\n'
3517 2 test
3529 2 test
3518 1 {node|short}
3530 1 {node|short}
3519 0 test
3531 0 test
3520
3532
3521 $ hg log --template '{pad(rev, 20, " ", True)} {author|user}\n'
3533 $ hg log --template '{pad(rev, 20, " ", True)} {author|user}\n'
3522 2 test
3534 2 test
3523 1 {node|short}
3535 1 {node|short}
3524 0 test
3536 0 test
3525
3537
3526 $ hg log --template '{pad(rev, 20, "-", False)} {author|user}\n'
3538 $ hg log --template '{pad(rev, 20, "-", False)} {author|user}\n'
3527 2------------------- test
3539 2------------------- test
3528 1------------------- {node|short}
3540 1------------------- {node|short}
3529 0------------------- test
3541 0------------------- test
3530
3542
3531 Test template string in pad function
3543 Test template string in pad function
3532
3544
3533 $ hg log -r 0 -T '{pad("\{{rev}}", 10)} {author|user}\n'
3545 $ hg log -r 0 -T '{pad("\{{rev}}", 10)} {author|user}\n'
3534 {0} test
3546 {0} test
3535
3547
3536 $ hg log -r 0 -T '{pad(r"\{rev}", 10)} {author|user}\n'
3548 $ hg log -r 0 -T '{pad(r"\{rev}", 10)} {author|user}\n'
3537 \{rev} test
3549 \{rev} test
3538
3550
3539 Test width argument passed to pad function
3551 Test width argument passed to pad function
3540
3552
3541 $ hg log -r 0 -T '{pad(rev, "1{"0"}")} {author|user}\n'
3553 $ hg log -r 0 -T '{pad(rev, "1{"0"}")} {author|user}\n'
3542 0 test
3554 0 test
3543 $ hg log -r 0 -T '{pad(rev, "not an int")}\n'
3555 $ hg log -r 0 -T '{pad(rev, "not an int")}\n'
3544 hg: parse error: pad() expects an integer width
3556 hg: parse error: pad() expects an integer width
3545 [255]
3557 [255]
3546
3558
3547 Test invalid fillchar passed to pad function
3559 Test invalid fillchar passed to pad function
3548
3560
3549 $ hg log -r 0 -T '{pad(rev, 10, "")}\n'
3561 $ hg log -r 0 -T '{pad(rev, 10, "")}\n'
3550 hg: parse error: pad() expects a single fill character
3562 hg: parse error: pad() expects a single fill character
3551 [255]
3563 [255]
3552 $ hg log -r 0 -T '{pad(rev, 10, "--")}\n'
3564 $ hg log -r 0 -T '{pad(rev, 10, "--")}\n'
3553 hg: parse error: pad() expects a single fill character
3565 hg: parse error: pad() expects a single fill character
3554 [255]
3566 [255]
3555
3567
3556 Test boolean argument passed to pad function
3568 Test boolean argument passed to pad function
3557
3569
3558 no crash
3570 no crash
3559
3571
3560 $ hg log -r 0 -T '{pad(rev, 10, "-", "f{"oo"}")}\n'
3572 $ hg log -r 0 -T '{pad(rev, 10, "-", "f{"oo"}")}\n'
3561 ---------0
3573 ---------0
3562
3574
3563 string/literal
3575 string/literal
3564
3576
3565 $ hg log -r 0 -T '{pad(rev, 10, "-", "false")}\n'
3577 $ hg log -r 0 -T '{pad(rev, 10, "-", "false")}\n'
3566 ---------0
3578 ---------0
3567 $ hg log -r 0 -T '{pad(rev, 10, "-", false)}\n'
3579 $ hg log -r 0 -T '{pad(rev, 10, "-", false)}\n'
3568 0---------
3580 0---------
3569 $ hg log -r 0 -T '{pad(rev, 10, "-", "")}\n'
3581 $ hg log -r 0 -T '{pad(rev, 10, "-", "")}\n'
3570 0---------
3582 0---------
3571
3583
3572 unknown keyword is evaluated to ''
3584 unknown keyword is evaluated to ''
3573
3585
3574 $ hg log -r 0 -T '{pad(rev, 10, "-", unknownkeyword)}\n'
3586 $ hg log -r 0 -T '{pad(rev, 10, "-", unknownkeyword)}\n'
3575 0---------
3587 0---------
3576
3588
3577 Test separate function
3589 Test separate function
3578
3590
3579 $ hg log -r 0 -T '{separate("-", "", "a", "b", "", "", "c", "")}\n'
3591 $ hg log -r 0 -T '{separate("-", "", "a", "b", "", "", "c", "")}\n'
3580 a-b-c
3592 a-b-c
3581 $ hg log -r 0 -T '{separate(" ", "{rev}:{node|short}", author|user, branch)}\n'
3593 $ hg log -r 0 -T '{separate(" ", "{rev}:{node|short}", author|user, branch)}\n'
3582 0:f7769ec2ab97 test default
3594 0:f7769ec2ab97 test default
3583 $ hg log -r 0 --color=always -T '{separate(" ", "a", label(red, "b"), "c", label(red, ""), "d")}\n'
3595 $ hg log -r 0 --color=always -T '{separate(" ", "a", label(red, "b"), "c", label(red, ""), "d")}\n'
3584 a \x1b[0;31mb\x1b[0m c d (esc)
3596 a \x1b[0;31mb\x1b[0m c d (esc)
3585
3597
3586 Test boolean expression/literal passed to if function
3598 Test boolean expression/literal passed to if function
3587
3599
3588 $ hg log -r 0 -T '{if(rev, "rev 0 is True")}\n'
3600 $ hg log -r 0 -T '{if(rev, "rev 0 is True")}\n'
3589 rev 0 is True
3601 rev 0 is True
3590 $ hg log -r 0 -T '{if(0, "literal 0 is True as well")}\n'
3602 $ hg log -r 0 -T '{if(0, "literal 0 is True as well")}\n'
3591 literal 0 is True as well
3603 literal 0 is True as well
3592 $ hg log -r 0 -T '{if("", "", "empty string is False")}\n'
3604 $ hg log -r 0 -T '{if("", "", "empty string is False")}\n'
3593 empty string is False
3605 empty string is False
3594 $ hg log -r 0 -T '{if(revset(r"0 - 0"), "", "empty list is False")}\n'
3606 $ hg log -r 0 -T '{if(revset(r"0 - 0"), "", "empty list is False")}\n'
3595 empty list is False
3607 empty list is False
3596 $ hg log -r 0 -T '{if(true, "true is True")}\n'
3608 $ hg log -r 0 -T '{if(true, "true is True")}\n'
3597 true is True
3609 true is True
3598 $ hg log -r 0 -T '{if(false, "", "false is False")}\n'
3610 $ hg log -r 0 -T '{if(false, "", "false is False")}\n'
3599 false is False
3611 false is False
3600 $ hg log -r 0 -T '{if("false", "non-empty string is True")}\n'
3612 $ hg log -r 0 -T '{if("false", "non-empty string is True")}\n'
3601 non-empty string is True
3613 non-empty string is True
3602
3614
3603 Test ifcontains function
3615 Test ifcontains function
3604
3616
3605 $ hg log --template '{rev} {ifcontains(rev, "2 two 0", "is in the string", "is not")}\n'
3617 $ hg log --template '{rev} {ifcontains(rev, "2 two 0", "is in the string", "is not")}\n'
3606 2 is in the string
3618 2 is in the string
3607 1 is not
3619 1 is not
3608 0 is in the string
3620 0 is in the string
3609
3621
3610 $ hg log -T '{rev} {ifcontains(rev, "2 two{" 0"}", "is in the string", "is not")}\n'
3622 $ hg log -T '{rev} {ifcontains(rev, "2 two{" 0"}", "is in the string", "is not")}\n'
3611 2 is in the string
3623 2 is in the string
3612 1 is not
3624 1 is not
3613 0 is in the string
3625 0 is in the string
3614
3626
3615 $ hg log --template '{rev} {ifcontains("a", file_adds, "added a", "did not add a")}\n'
3627 $ hg log --template '{rev} {ifcontains("a", file_adds, "added a", "did not add a")}\n'
3616 2 did not add a
3628 2 did not add a
3617 1 did not add a
3629 1 did not add a
3618 0 added a
3630 0 added a
3619
3631
3620 $ hg log --debug -T '{rev}{ifcontains(1, parents, " is parent of 1")}\n'
3632 $ hg log --debug -T '{rev}{ifcontains(1, parents, " is parent of 1")}\n'
3621 2 is parent of 1
3633 2 is parent of 1
3622 1
3634 1
3623 0
3635 0
3624
3636
3625 Test revset function
3637 Test revset function
3626
3638
3627 $ hg log --template '{rev} {ifcontains(rev, revset("."), "current rev", "not current rev")}\n'
3639 $ hg log --template '{rev} {ifcontains(rev, revset("."), "current rev", "not current rev")}\n'
3628 2 current rev
3640 2 current rev
3629 1 not current rev
3641 1 not current rev
3630 0 not current rev
3642 0 not current rev
3631
3643
3632 $ hg log --template '{rev} {ifcontains(rev, revset(". + .^"), "match rev", "not match rev")}\n'
3644 $ hg log --template '{rev} {ifcontains(rev, revset(". + .^"), "match rev", "not match rev")}\n'
3633 2 match rev
3645 2 match rev
3634 1 match rev
3646 1 match rev
3635 0 not match rev
3647 0 not match rev
3636
3648
3637 $ hg log --template '{rev} Parents: {revset("parents(%s)", rev)}\n'
3649 $ hg log --template '{rev} Parents: {revset("parents(%s)", rev)}\n'
3638 2 Parents: 1
3650 2 Parents: 1
3639 1 Parents: 0
3651 1 Parents: 0
3640 0 Parents:
3652 0 Parents:
3641
3653
3642 $ cat >> .hg/hgrc <<EOF
3654 $ cat >> .hg/hgrc <<EOF
3643 > [revsetalias]
3655 > [revsetalias]
3644 > myparents(\$1) = parents(\$1)
3656 > myparents(\$1) = parents(\$1)
3645 > EOF
3657 > EOF
3646 $ hg log --template '{rev} Parents: {revset("myparents(%s)", rev)}\n'
3658 $ hg log --template '{rev} Parents: {revset("myparents(%s)", rev)}\n'
3647 2 Parents: 1
3659 2 Parents: 1
3648 1 Parents: 0
3660 1 Parents: 0
3649 0 Parents:
3661 0 Parents:
3650
3662
3651 $ hg log --template 'Rev: {rev}\n{revset("::%s", rev) % "Ancestor: {revision}\n"}\n'
3663 $ hg log --template 'Rev: {rev}\n{revset("::%s", rev) % "Ancestor: {revision}\n"}\n'
3652 Rev: 2
3664 Rev: 2
3653 Ancestor: 0
3665 Ancestor: 0
3654 Ancestor: 1
3666 Ancestor: 1
3655 Ancestor: 2
3667 Ancestor: 2
3656
3668
3657 Rev: 1
3669 Rev: 1
3658 Ancestor: 0
3670 Ancestor: 0
3659 Ancestor: 1
3671 Ancestor: 1
3660
3672
3661 Rev: 0
3673 Rev: 0
3662 Ancestor: 0
3674 Ancestor: 0
3663
3675
3664 $ hg log --template '{revset("TIP"|lower)}\n' -l1
3676 $ hg log --template '{revset("TIP"|lower)}\n' -l1
3665 2
3677 2
3666
3678
3667 $ hg log -T '{revset("%s", "t{"ip"}")}\n' -l1
3679 $ hg log -T '{revset("%s", "t{"ip"}")}\n' -l1
3668 2
3680 2
3669
3681
3670 a list template is evaluated for each item of revset/parents
3682 a list template is evaluated for each item of revset/parents
3671
3683
3672 $ hg log -T '{rev} p: {revset("p1(%s)", rev) % "{rev}:{node|short}"}\n'
3684 $ hg log -T '{rev} p: {revset("p1(%s)", rev) % "{rev}:{node|short}"}\n'
3673 2 p: 1:bcc7ff960b8e
3685 2 p: 1:bcc7ff960b8e
3674 1 p: 0:f7769ec2ab97
3686 1 p: 0:f7769ec2ab97
3675 0 p:
3687 0 p:
3676
3688
3677 $ hg log --debug -T '{rev} p:{parents % " {rev}:{node|short}"}\n'
3689 $ hg log --debug -T '{rev} p:{parents % " {rev}:{node|short}"}\n'
3678 2 p: 1:bcc7ff960b8e -1:000000000000
3690 2 p: 1:bcc7ff960b8e -1:000000000000
3679 1 p: 0:f7769ec2ab97 -1:000000000000
3691 1 p: 0:f7769ec2ab97 -1:000000000000
3680 0 p: -1:000000000000 -1:000000000000
3692 0 p: -1:000000000000 -1:000000000000
3681
3693
3682 therefore, 'revcache' should be recreated for each rev
3694 therefore, 'revcache' should be recreated for each rev
3683
3695
3684 $ hg log -T '{rev} {file_adds}\np {revset("p1(%s)", rev) % "{file_adds}"}\n'
3696 $ hg log -T '{rev} {file_adds}\np {revset("p1(%s)", rev) % "{file_adds}"}\n'
3685 2 aa b
3697 2 aa b
3686 p
3698 p
3687 1
3699 1
3688 p a
3700 p a
3689 0 a
3701 0 a
3690 p
3702 p
3691
3703
3692 $ hg log --debug -T '{rev} {file_adds}\np {parents % "{file_adds}"}\n'
3704 $ hg log --debug -T '{rev} {file_adds}\np {parents % "{file_adds}"}\n'
3693 2 aa b
3705 2 aa b
3694 p
3706 p
3695 1
3707 1
3696 p a
3708 p a
3697 0 a
3709 0 a
3698 p
3710 p
3699
3711
3700 a revset item must be evaluated as an integer revision, not an offset from tip
3712 a revset item must be evaluated as an integer revision, not an offset from tip
3701
3713
3702 $ hg log -l 1 -T '{revset("null") % "{rev}:{node|short}"}\n'
3714 $ hg log -l 1 -T '{revset("null") % "{rev}:{node|short}"}\n'
3703 -1:000000000000
3715 -1:000000000000
3704 $ hg log -l 1 -T '{revset("%s", "null") % "{rev}:{node|short}"}\n'
3716 $ hg log -l 1 -T '{revset("%s", "null") % "{rev}:{node|short}"}\n'
3705 -1:000000000000
3717 -1:000000000000
3706
3718
3707 join() should pick '{rev}' from revset items:
3719 join() should pick '{rev}' from revset items:
3708
3720
3709 $ hg log -R ../a -T '{join(revset("parents(%d)", rev), ", ")}\n' -r6
3721 $ hg log -R ../a -T '{join(revset("parents(%d)", rev), ", ")}\n' -r6
3710 4, 5
3722 4, 5
3711
3723
3712 on the other hand, parents are formatted as '{rev}:{node|formatnode}' by
3724 on the other hand, parents are formatted as '{rev}:{node|formatnode}' by
3713 default. join() should agree with the default formatting:
3725 default. join() should agree with the default formatting:
3714
3726
3715 $ hg log -R ../a -T '{join(parents, ", ")}\n' -r6
3727 $ hg log -R ../a -T '{join(parents, ", ")}\n' -r6
3716 5:13207e5a10d9, 4:bbe44766e73d
3728 5:13207e5a10d9, 4:bbe44766e73d
3717
3729
3718 $ hg log -R ../a -T '{join(parents, ",\n")}\n' -r6 --debug
3730 $ hg log -R ../a -T '{join(parents, ",\n")}\n' -r6 --debug
3719 5:13207e5a10d9fd28ec424934298e176197f2c67f,
3731 5:13207e5a10d9fd28ec424934298e176197f2c67f,
3720 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
3732 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
3721
3733
3722 Test files function
3734 Test files function
3723
3735
3724 $ hg log -T "{rev}\n{join(files('*'), '\n')}\n"
3736 $ hg log -T "{rev}\n{join(files('*'), '\n')}\n"
3725 2
3737 2
3726 a
3738 a
3727 aa
3739 aa
3728 b
3740 b
3729 1
3741 1
3730 a
3742 a
3731 0
3743 0
3732 a
3744 a
3733
3745
3734 $ hg log -T "{rev}\n{join(files('aa'), '\n')}\n"
3746 $ hg log -T "{rev}\n{join(files('aa'), '\n')}\n"
3735 2
3747 2
3736 aa
3748 aa
3737 1
3749 1
3738
3750
3739 0
3751 0
3740
3752
3741
3753
3742 Test relpath function
3754 Test relpath function
3743
3755
3744 $ hg log -r0 -T '{files % "{file|relpath}\n"}'
3756 $ hg log -r0 -T '{files % "{file|relpath}\n"}'
3745 a
3757 a
3746 $ cd ..
3758 $ cd ..
3747 $ hg log -R r -r0 -T '{files % "{file|relpath}\n"}'
3759 $ hg log -R r -r0 -T '{files % "{file|relpath}\n"}'
3748 r/a
3760 r/a
3749 $ cd r
3761 $ cd r
3750
3762
3751 Test active bookmark templating
3763 Test active bookmark templating
3752
3764
3753 $ hg book foo
3765 $ hg book foo
3754 $ hg book bar
3766 $ hg book bar
3755 $ hg log --template "{rev} {bookmarks % '{bookmark}{ifeq(bookmark, active, \"*\")} '}\n"
3767 $ hg log --template "{rev} {bookmarks % '{bookmark}{ifeq(bookmark, active, \"*\")} '}\n"
3756 2 bar* foo
3768 2 bar* foo
3757 1
3769 1
3758 0
3770 0
3759 $ hg log --template "{rev} {activebookmark}\n"
3771 $ hg log --template "{rev} {activebookmark}\n"
3760 2 bar
3772 2 bar
3761 1
3773 1
3762 0
3774 0
3763 $ hg bookmarks --inactive bar
3775 $ hg bookmarks --inactive bar
3764 $ hg log --template "{rev} {activebookmark}\n"
3776 $ hg log --template "{rev} {activebookmark}\n"
3765 2
3777 2
3766 1
3778 1
3767 0
3779 0
3768 $ hg book -r1 baz
3780 $ hg book -r1 baz
3769 $ hg log --template "{rev} {join(bookmarks, ' ')}\n"
3781 $ hg log --template "{rev} {join(bookmarks, ' ')}\n"
3770 2 bar foo
3782 2 bar foo
3771 1 baz
3783 1 baz
3772 0
3784 0
3773 $ hg log --template "{rev} {ifcontains('foo', bookmarks, 't', 'f')}\n"
3785 $ hg log --template "{rev} {ifcontains('foo', bookmarks, 't', 'f')}\n"
3774 2 t
3786 2 t
3775 1 f
3787 1 f
3776 0 f
3788 0 f
3777
3789
3778 Test namespaces dict
3790 Test namespaces dict
3779
3791
3780 $ hg log -T '{rev}{namespaces % " {namespace}={join(names, ",")}"}\n'
3792 $ hg log -T '{rev}{namespaces % " {namespace}={join(names, ",")}"}\n'
3781 2 bookmarks=bar,foo tags=tip branches=text.{rev}
3793 2 bookmarks=bar,foo tags=tip branches=text.{rev}
3782 1 bookmarks=baz tags= branches=text.{rev}
3794 1 bookmarks=baz tags= branches=text.{rev}
3783 0 bookmarks= tags= branches=default
3795 0 bookmarks= tags= branches=default
3784 $ hg log -r2 -T '{namespaces % "{namespace}: {names}\n"}'
3796 $ hg log -r2 -T '{namespaces % "{namespace}: {names}\n"}'
3785 bookmarks: bar foo
3797 bookmarks: bar foo
3786 tags: tip
3798 tags: tip
3787 branches: text.{rev}
3799 branches: text.{rev}
3788 $ hg log -r2 -T '{namespaces % "{namespace}:\n{names % " {name}\n"}"}'
3800 $ hg log -r2 -T '{namespaces % "{namespace}:\n{names % " {name}\n"}"}'
3789 bookmarks:
3801 bookmarks:
3790 bar
3802 bar
3791 foo
3803 foo
3792 tags:
3804 tags:
3793 tip
3805 tip
3794 branches:
3806 branches:
3795 text.{rev}
3807 text.{rev}
3796 $ hg log -r2 -T '{get(namespaces, "bookmarks") % "{name}\n"}'
3808 $ hg log -r2 -T '{get(namespaces, "bookmarks") % "{name}\n"}'
3797 bar
3809 bar
3798 foo
3810 foo
3799
3811
3800 Test stringify on sub expressions
3812 Test stringify on sub expressions
3801
3813
3802 $ cd ..
3814 $ cd ..
3803 $ hg log -R a -r 8 --template '{join(files, if("1", if("1", ", ")))}\n'
3815 $ hg log -R a -r 8 --template '{join(files, if("1", if("1", ", ")))}\n'
3804 fourth, second, third
3816 fourth, second, third
3805 $ hg log -R a -r 8 --template '{strip(if("1", if("1", "-abc-")), if("1", if("1", "-")))}\n'
3817 $ hg log -R a -r 8 --template '{strip(if("1", if("1", "-abc-")), if("1", if("1", "-")))}\n'
3806 abc
3818 abc
3807
3819
3808 Test splitlines
3820 Test splitlines
3809
3821
3810 $ hg log -Gv -R a --template "{splitlines(desc) % 'foo {line}\n'}"
3822 $ hg log -Gv -R a --template "{splitlines(desc) % 'foo {line}\n'}"
3811 @ foo Modify, add, remove, rename
3823 @ foo Modify, add, remove, rename
3812 |
3824 |
3813 o foo future
3825 o foo future
3814 |
3826 |
3815 o foo third
3827 o foo third
3816 |
3828 |
3817 o foo second
3829 o foo second
3818
3830
3819 o foo merge
3831 o foo merge
3820 |\
3832 |\
3821 | o foo new head
3833 | o foo new head
3822 | |
3834 | |
3823 o | foo new branch
3835 o | foo new branch
3824 |/
3836 |/
3825 o foo no user, no domain
3837 o foo no user, no domain
3826 |
3838 |
3827 o foo no person
3839 o foo no person
3828 |
3840 |
3829 o foo other 1
3841 o foo other 1
3830 | foo other 2
3842 | foo other 2
3831 | foo
3843 | foo
3832 | foo other 3
3844 | foo other 3
3833 o foo line 1
3845 o foo line 1
3834 foo line 2
3846 foo line 2
3835
3847
3836 Test startswith
3848 Test startswith
3837 $ hg log -Gv -R a --template "{startswith(desc)}"
3849 $ hg log -Gv -R a --template "{startswith(desc)}"
3838 hg: parse error: startswith expects two arguments
3850 hg: parse error: startswith expects two arguments
3839 [255]
3851 [255]
3840
3852
3841 $ hg log -Gv -R a --template "{startswith('line', desc)}"
3853 $ hg log -Gv -R a --template "{startswith('line', desc)}"
3842 @
3854 @
3843 |
3855 |
3844 o
3856 o
3845 |
3857 |
3846 o
3858 o
3847 |
3859 |
3848 o
3860 o
3849
3861
3850 o
3862 o
3851 |\
3863 |\
3852 | o
3864 | o
3853 | |
3865 | |
3854 o |
3866 o |
3855 |/
3867 |/
3856 o
3868 o
3857 |
3869 |
3858 o
3870 o
3859 |
3871 |
3860 o
3872 o
3861 |
3873 |
3862 o line 1
3874 o line 1
3863 line 2
3875 line 2
3864
3876
3865 Test bad template with better error message
3877 Test bad template with better error message
3866
3878
3867 $ hg log -Gv -R a --template '{desc|user()}'
3879 $ hg log -Gv -R a --template '{desc|user()}'
3868 hg: parse error: expected a symbol, got 'func'
3880 hg: parse error: expected a symbol, got 'func'
3869 [255]
3881 [255]
3870
3882
3871 Test word function (including index out of bounds graceful failure)
3883 Test word function (including index out of bounds graceful failure)
3872
3884
3873 $ hg log -Gv -R a --template "{word('1', desc)}"
3885 $ hg log -Gv -R a --template "{word('1', desc)}"
3874 @ add,
3886 @ add,
3875 |
3887 |
3876 o
3888 o
3877 |
3889 |
3878 o
3890 o
3879 |
3891 |
3880 o
3892 o
3881
3893
3882 o
3894 o
3883 |\
3895 |\
3884 | o head
3896 | o head
3885 | |
3897 | |
3886 o | branch
3898 o | branch
3887 |/
3899 |/
3888 o user,
3900 o user,
3889 |
3901 |
3890 o person
3902 o person
3891 |
3903 |
3892 o 1
3904 o 1
3893 |
3905 |
3894 o 1
3906 o 1
3895
3907
3896
3908
3897 Test word third parameter used as splitter
3909 Test word third parameter used as splitter
3898
3910
3899 $ hg log -Gv -R a --template "{word('0', desc, 'o')}"
3911 $ hg log -Gv -R a --template "{word('0', desc, 'o')}"
3900 @ M
3912 @ M
3901 |
3913 |
3902 o future
3914 o future
3903 |
3915 |
3904 o third
3916 o third
3905 |
3917 |
3906 o sec
3918 o sec
3907
3919
3908 o merge
3920 o merge
3909 |\
3921 |\
3910 | o new head
3922 | o new head
3911 | |
3923 | |
3912 o | new branch
3924 o | new branch
3913 |/
3925 |/
3914 o n
3926 o n
3915 |
3927 |
3916 o n
3928 o n
3917 |
3929 |
3918 o
3930 o
3919 |
3931 |
3920 o line 1
3932 o line 1
3921 line 2
3933 line 2
3922
3934
3923 Test word error messages for not enough and too many arguments
3935 Test word error messages for not enough and too many arguments
3924
3936
3925 $ hg log -Gv -R a --template "{word('0')}"
3937 $ hg log -Gv -R a --template "{word('0')}"
3926 hg: parse error: word expects two or three arguments, got 1
3938 hg: parse error: word expects two or three arguments, got 1
3927 [255]
3939 [255]
3928
3940
3929 $ hg log -Gv -R a --template "{word('0', desc, 'o', 'h', 'b', 'o', 'y')}"
3941 $ hg log -Gv -R a --template "{word('0', desc, 'o', 'h', 'b', 'o', 'y')}"
3930 hg: parse error: word expects two or three arguments, got 7
3942 hg: parse error: word expects two or three arguments, got 7
3931 [255]
3943 [255]
3932
3944
3933 Test word for integer literal
3945 Test word for integer literal
3934
3946
3935 $ hg log -R a --template "{word(2, desc)}\n" -r0
3947 $ hg log -R a --template "{word(2, desc)}\n" -r0
3936 line
3948 line
3937
3949
3938 Test word for invalid numbers
3950 Test word for invalid numbers
3939
3951
3940 $ hg log -Gv -R a --template "{word('a', desc)}"
3952 $ hg log -Gv -R a --template "{word('a', desc)}"
3941 hg: parse error: word expects an integer index
3953 hg: parse error: word expects an integer index
3942 [255]
3954 [255]
3943
3955
3944 Test word for out of range
3956 Test word for out of range
3945
3957
3946 $ hg log -R a --template "{word(10000, desc)}"
3958 $ hg log -R a --template "{word(10000, desc)}"
3947 $ hg log -R a --template "{word(-10000, desc)}"
3959 $ hg log -R a --template "{word(-10000, desc)}"
3948
3960
3949 Test indent and not adding to empty lines
3961 Test indent and not adding to empty lines
3950
3962
3951 $ hg log -T "-----\n{indent(desc, '>> ', ' > ')}\n" -r 0:1 -R a
3963 $ hg log -T "-----\n{indent(desc, '>> ', ' > ')}\n" -r 0:1 -R a
3952 -----
3964 -----
3953 > line 1
3965 > line 1
3954 >> line 2
3966 >> line 2
3955 -----
3967 -----
3956 > other 1
3968 > other 1
3957 >> other 2
3969 >> other 2
3958
3970
3959 >> other 3
3971 >> other 3
3960
3972
3961 Test with non-strings like dates
3973 Test with non-strings like dates
3962
3974
3963 $ hg log -T "{indent(date, ' ')}\n" -r 2:3 -R a
3975 $ hg log -T "{indent(date, ' ')}\n" -r 2:3 -R a
3964 1200000.00
3976 1200000.00
3965 1300000.00
3977 1300000.00
3966
3978
3967 Test broken string escapes:
3979 Test broken string escapes:
3968
3980
3969 $ hg log -T "bogus\\" -R a
3981 $ hg log -T "bogus\\" -R a
3970 hg: parse error: trailing \ in string
3982 hg: parse error: trailing \ in string
3971 [255]
3983 [255]
3972 $ hg log -T "\\xy" -R a
3984 $ hg log -T "\\xy" -R a
3973 hg: parse error: invalid \x escape
3985 hg: parse error: invalid \x escape
3974 [255]
3986 [255]
3975
3987
3976 json filter should escape HTML tags so that the output can be embedded in hgweb:
3988 json filter should escape HTML tags so that the output can be embedded in hgweb:
3977
3989
3978 $ hg log -T "{'<foo@example.org>'|json}\n" -R a -l1
3990 $ hg log -T "{'<foo@example.org>'|json}\n" -R a -l1
3979 "\u003cfoo@example.org\u003e"
3991 "\u003cfoo@example.org\u003e"
3980
3992
3981 Templater supports aliases of symbol and func() styles:
3993 Templater supports aliases of symbol and func() styles:
3982
3994
3983 $ hg clone -q a aliases
3995 $ hg clone -q a aliases
3984 $ cd aliases
3996 $ cd aliases
3985 $ cat <<EOF >> .hg/hgrc
3997 $ cat <<EOF >> .hg/hgrc
3986 > [templatealias]
3998 > [templatealias]
3987 > r = rev
3999 > r = rev
3988 > rn = "{r}:{node|short}"
4000 > rn = "{r}:{node|short}"
3989 > status(c, files) = files % "{c} {file}\n"
4001 > status(c, files) = files % "{c} {file}\n"
3990 > utcdate(d) = localdate(d, "UTC")
4002 > utcdate(d) = localdate(d, "UTC")
3991 > EOF
4003 > EOF
3992
4004
3993 $ hg debugtemplate -vr0 '{rn} {utcdate(date)|isodate}\n'
4005 $ hg debugtemplate -vr0 '{rn} {utcdate(date)|isodate}\n'
3994 (template
4006 (template
3995 ('symbol', 'rn')
4007 ('symbol', 'rn')
3996 ('string', ' ')
4008 ('string', ' ')
3997 (|
4009 (|
3998 (func
4010 (func
3999 ('symbol', 'utcdate')
4011 ('symbol', 'utcdate')
4000 ('symbol', 'date'))
4012 ('symbol', 'date'))
4001 ('symbol', 'isodate'))
4013 ('symbol', 'isodate'))
4002 ('string', '\n'))
4014 ('string', '\n'))
4003 * expanded:
4015 * expanded:
4004 (template
4016 (template
4005 (template
4017 (template
4006 ('symbol', 'rev')
4018 ('symbol', 'rev')
4007 ('string', ':')
4019 ('string', ':')
4008 (|
4020 (|
4009 ('symbol', 'node')
4021 ('symbol', 'node')
4010 ('symbol', 'short')))
4022 ('symbol', 'short')))
4011 ('string', ' ')
4023 ('string', ' ')
4012 (|
4024 (|
4013 (func
4025 (func
4014 ('symbol', 'localdate')
4026 ('symbol', 'localdate')
4015 (list
4027 (list
4016 ('symbol', 'date')
4028 ('symbol', 'date')
4017 ('string', 'UTC')))
4029 ('string', 'UTC')))
4018 ('symbol', 'isodate'))
4030 ('symbol', 'isodate'))
4019 ('string', '\n'))
4031 ('string', '\n'))
4020 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
4032 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
4021
4033
4022 $ hg debugtemplate -vr0 '{status("A", file_adds)}'
4034 $ hg debugtemplate -vr0 '{status("A", file_adds)}'
4023 (template
4035 (template
4024 (func
4036 (func
4025 ('symbol', 'status')
4037 ('symbol', 'status')
4026 (list
4038 (list
4027 ('string', 'A')
4039 ('string', 'A')
4028 ('symbol', 'file_adds'))))
4040 ('symbol', 'file_adds'))))
4029 * expanded:
4041 * expanded:
4030 (template
4042 (template
4031 (%
4043 (%
4032 ('symbol', 'file_adds')
4044 ('symbol', 'file_adds')
4033 (template
4045 (template
4034 ('string', 'A')
4046 ('string', 'A')
4035 ('string', ' ')
4047 ('string', ' ')
4036 ('symbol', 'file')
4048 ('symbol', 'file')
4037 ('string', '\n'))))
4049 ('string', '\n'))))
4038 A a
4050 A a
4039
4051
4040 A unary function alias can be called as a filter:
4052 A unary function alias can be called as a filter:
4041
4053
4042 $ hg debugtemplate -vr0 '{date|utcdate|isodate}\n'
4054 $ hg debugtemplate -vr0 '{date|utcdate|isodate}\n'
4043 (template
4055 (template
4044 (|
4056 (|
4045 (|
4057 (|
4046 ('symbol', 'date')
4058 ('symbol', 'date')
4047 ('symbol', 'utcdate'))
4059 ('symbol', 'utcdate'))
4048 ('symbol', 'isodate'))
4060 ('symbol', 'isodate'))
4049 ('string', '\n'))
4061 ('string', '\n'))
4050 * expanded:
4062 * expanded:
4051 (template
4063 (template
4052 (|
4064 (|
4053 (func
4065 (func
4054 ('symbol', 'localdate')
4066 ('symbol', 'localdate')
4055 (list
4067 (list
4056 ('symbol', 'date')
4068 ('symbol', 'date')
4057 ('string', 'UTC')))
4069 ('string', 'UTC')))
4058 ('symbol', 'isodate'))
4070 ('symbol', 'isodate'))
4059 ('string', '\n'))
4071 ('string', '\n'))
4060 1970-01-12 13:46 +0000
4072 1970-01-12 13:46 +0000
4061
4073
4062 Aliases should be applied only to command arguments and templates in hgrc.
4074 Aliases should be applied only to command arguments and templates in hgrc.
4063 Otherwise, our stock styles and web templates could be corrupted:
4075 Otherwise, our stock styles and web templates could be corrupted:
4064
4076
4065 $ hg log -r0 -T '{rn} {utcdate(date)|isodate}\n'
4077 $ hg log -r0 -T '{rn} {utcdate(date)|isodate}\n'
4066 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
4078 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
4067
4079
4068 $ hg log -r0 --config ui.logtemplate='"{rn} {utcdate(date)|isodate}\n"'
4080 $ hg log -r0 --config ui.logtemplate='"{rn} {utcdate(date)|isodate}\n"'
4069 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
4081 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
4070
4082
4071 $ cat <<EOF > tmpl
4083 $ cat <<EOF > tmpl
4072 > changeset = 'nothing expanded:{rn}\n'
4084 > changeset = 'nothing expanded:{rn}\n'
4073 > EOF
4085 > EOF
4074 $ hg log -r0 --style ./tmpl
4086 $ hg log -r0 --style ./tmpl
4075 nothing expanded:
4087 nothing expanded:
4076
4088
4077 Aliases in formatter:
4089 Aliases in formatter:
4078
4090
4079 $ hg branches -T '{pad(branch, 7)} {rn}\n'
4091 $ hg branches -T '{pad(branch, 7)} {rn}\n'
4080 default 6:d41e714fe50d
4092 default 6:d41e714fe50d
4081 foo 4:bbe44766e73d
4093 foo 4:bbe44766e73d
4082
4094
4083 Aliases should honor HGPLAIN:
4095 Aliases should honor HGPLAIN:
4084
4096
4085 $ HGPLAIN= hg log -r0 -T 'nothing expanded:{rn}\n'
4097 $ HGPLAIN= hg log -r0 -T 'nothing expanded:{rn}\n'
4086 nothing expanded:
4098 nothing expanded:
4087 $ HGPLAINEXCEPT=templatealias hg log -r0 -T '{rn}\n'
4099 $ HGPLAINEXCEPT=templatealias hg log -r0 -T '{rn}\n'
4088 0:1e4e1b8f71e0
4100 0:1e4e1b8f71e0
4089
4101
4090 Unparsable alias:
4102 Unparsable alias:
4091
4103
4092 $ hg debugtemplate --config templatealias.bad='x(' -v '{bad}'
4104 $ hg debugtemplate --config templatealias.bad='x(' -v '{bad}'
4093 (template
4105 (template
4094 ('symbol', 'bad'))
4106 ('symbol', 'bad'))
4095 abort: bad definition of template alias "bad": at 2: not a prefix: end
4107 abort: bad definition of template alias "bad": at 2: not a prefix: end
4096 [255]
4108 [255]
4097 $ hg log --config templatealias.bad='x(' -T '{bad}'
4109 $ hg log --config templatealias.bad='x(' -T '{bad}'
4098 abort: bad definition of template alias "bad": at 2: not a prefix: end
4110 abort: bad definition of template alias "bad": at 2: not a prefix: end
4099 [255]
4111 [255]
4100
4112
4101 $ cd ..
4113 $ cd ..
4102
4114
4103 Set up repository for non-ascii encoding tests:
4115 Set up repository for non-ascii encoding tests:
4104
4116
4105 $ hg init nonascii
4117 $ hg init nonascii
4106 $ cd nonascii
4118 $ cd nonascii
4107 $ python <<EOF
4119 $ python <<EOF
4108 > open('latin1', 'w').write('\xe9')
4120 > open('latin1', 'w').write('\xe9')
4109 > open('utf-8', 'w').write('\xc3\xa9')
4121 > open('utf-8', 'w').write('\xc3\xa9')
4110 > EOF
4122 > EOF
4111 $ HGENCODING=utf-8 hg branch -q `cat utf-8`
4123 $ HGENCODING=utf-8 hg branch -q `cat utf-8`
4112 $ HGENCODING=utf-8 hg ci -qAm "non-ascii branch: `cat utf-8`" utf-8
4124 $ HGENCODING=utf-8 hg ci -qAm "non-ascii branch: `cat utf-8`" utf-8
4113
4125
4114 json filter should try round-trip conversion to utf-8:
4126 json filter should try round-trip conversion to utf-8:
4115
4127
4116 $ HGENCODING=ascii hg log -T "{branch|json}\n" -r0
4128 $ HGENCODING=ascii hg log -T "{branch|json}\n" -r0
4117 "\u00e9"
4129 "\u00e9"
4118 $ HGENCODING=ascii hg log -T "{desc|json}\n" -r0
4130 $ HGENCODING=ascii hg log -T "{desc|json}\n" -r0
4119 "non-ascii branch: \u00e9"
4131 "non-ascii branch: \u00e9"
4120
4132
4121 json filter takes input as utf-8b:
4133 json filter takes input as utf-8b:
4122
4134
4123 $ HGENCODING=ascii hg log -T "{'`cat utf-8`'|json}\n" -l1
4135 $ HGENCODING=ascii hg log -T "{'`cat utf-8`'|json}\n" -l1
4124 "\u00e9"
4136 "\u00e9"
4125 $ HGENCODING=ascii hg log -T "{'`cat latin1`'|json}\n" -l1
4137 $ HGENCODING=ascii hg log -T "{'`cat latin1`'|json}\n" -l1
4126 "\udce9"
4138 "\udce9"
4127
4139
4128 utf8 filter:
4140 utf8 filter:
4129
4141
4130 $ HGENCODING=ascii hg log -T "round-trip: {branch|utf8|hex}\n" -r0
4142 $ HGENCODING=ascii hg log -T "round-trip: {branch|utf8|hex}\n" -r0
4131 round-trip: c3a9
4143 round-trip: c3a9
4132 $ HGENCODING=latin1 hg log -T "decoded: {'`cat latin1`'|utf8|hex}\n" -l1
4144 $ HGENCODING=latin1 hg log -T "decoded: {'`cat latin1`'|utf8|hex}\n" -l1
4133 decoded: c3a9
4145 decoded: c3a9
4134 $ HGENCODING=ascii hg log -T "replaced: {'`cat latin1`'|utf8|hex}\n" -l1
4146 $ HGENCODING=ascii hg log -T "replaced: {'`cat latin1`'|utf8|hex}\n" -l1
4135 abort: decoding near * (glob)
4147 abort: decoding near * (glob)
4136 [255]
4148 [255]
4137 $ hg log -T "invalid type: {rev|utf8}\n" -r0
4149 $ hg log -T "invalid type: {rev|utf8}\n" -r0
4138 abort: template filter 'utf8' is not compatible with keyword 'rev'
4150 abort: template filter 'utf8' is not compatible with keyword 'rev'
4139 [255]
4151 [255]
4140
4152
4141 pad width:
4153 pad width:
4142
4154
4143 $ HGENCODING=utf-8 hg debugtemplate "{pad('`cat utf-8`', 2, '-')}\n"
4155 $ HGENCODING=utf-8 hg debugtemplate "{pad('`cat utf-8`', 2, '-')}\n"
4144 \xc3\xa9- (esc)
4156 \xc3\xa9- (esc)
4145
4157
4146 $ cd ..
4158 $ cd ..
4147
4159
4148 Test that template function in extension is registered as expected
4160 Test that template function in extension is registered as expected
4149
4161
4150 $ cd a
4162 $ cd a
4151
4163
4152 $ cat <<EOF > $TESTTMP/customfunc.py
4164 $ cat <<EOF > $TESTTMP/customfunc.py
4153 > from mercurial import registrar
4165 > from mercurial import registrar
4154 >
4166 >
4155 > templatefunc = registrar.templatefunc()
4167 > templatefunc = registrar.templatefunc()
4156 >
4168 >
4157 > @templatefunc('custom()')
4169 > @templatefunc('custom()')
4158 > def custom(context, mapping, args):
4170 > def custom(context, mapping, args):
4159 > return 'custom'
4171 > return 'custom'
4160 > EOF
4172 > EOF
4161 $ cat <<EOF > .hg/hgrc
4173 $ cat <<EOF > .hg/hgrc
4162 > [extensions]
4174 > [extensions]
4163 > customfunc = $TESTTMP/customfunc.py
4175 > customfunc = $TESTTMP/customfunc.py
4164 > EOF
4176 > EOF
4165
4177
4166 $ hg log -r . -T "{custom()}\n" --config customfunc.enabled=true
4178 $ hg log -r . -T "{custom()}\n" --config customfunc.enabled=true
4167 custom
4179 custom
4168
4180
4169 $ cd ..
4181 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now