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