##// END OF EJS Templates
templater: do not preprocess template string in "if" expression (issue4714)...
Yuya Nishihara -
r25471:7298da81 stable
parent child Browse files
Show More
@@ -1,810 +1,811 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 i18n import _
8 from i18n import _
9 import os, re
9 import os, re
10 import util, config, templatefilters, templatekw, parser, error
10 import util, config, templatefilters, templatekw, parser, error
11 import revset as revsetmod
11 import revset as revsetmod
12 import types
12 import types
13 import minirst
13 import minirst
14
14
15 # template parsing
15 # template parsing
16
16
17 elements = {
17 elements = {
18 "(": (20, ("group", 1, ")"), ("func", 1, ")")),
18 "(": (20, ("group", 1, ")"), ("func", 1, ")")),
19 ",": (2, None, ("list", 2)),
19 ",": (2, None, ("list", 2)),
20 "|": (5, None, ("|", 5)),
20 "|": (5, None, ("|", 5)),
21 "%": (6, None, ("%", 6)),
21 "%": (6, None, ("%", 6)),
22 ")": (0, None, None),
22 ")": (0, None, None),
23 "symbol": (0, ("symbol",), None),
23 "symbol": (0, ("symbol",), None),
24 "string": (0, ("string",), None),
24 "string": (0, ("string",), None),
25 "rawstring": (0, ("rawstring",), None),
25 "rawstring": (0, ("rawstring",), None),
26 "end": (0, None, None),
26 "end": (0, None, None),
27 }
27 }
28
28
29 def tokenizer(data):
29 def tokenizer(data):
30 program, start, end = data
30 program, start, end = data
31 pos = start
31 pos = start
32 while pos < end:
32 while pos < end:
33 c = program[pos]
33 c = program[pos]
34 if c.isspace(): # skip inter-token whitespace
34 if c.isspace(): # skip inter-token whitespace
35 pass
35 pass
36 elif c in "(,)%|": # handle simple operators
36 elif c in "(,)%|": # handle simple operators
37 yield (c, None, pos)
37 yield (c, None, pos)
38 elif (c in '"\'' or c == 'r' and
38 elif (c in '"\'' or c == 'r' and
39 program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
39 program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
40 if c == 'r':
40 if c == 'r':
41 pos += 1
41 pos += 1
42 c = program[pos]
42 c = program[pos]
43 decode = False
43 decode = False
44 else:
44 else:
45 decode = True
45 decode = True
46 pos += 1
46 pos += 1
47 s = pos
47 s = pos
48 while pos < end: # find closing quote
48 while pos < end: # find closing quote
49 d = program[pos]
49 d = program[pos]
50 if decode and d == '\\': # skip over escaped characters
50 if decode and d == '\\': # skip over escaped characters
51 pos += 2
51 pos += 2
52 continue
52 continue
53 if d == c:
53 if d == c:
54 if not decode:
54 if not decode:
55 yield ('rawstring', program[s:pos], s)
55 yield ('rawstring', program[s:pos], s)
56 break
56 break
57 yield ('string', program[s:pos], s)
57 yield ('string', program[s:pos], s)
58 break
58 break
59 pos += 1
59 pos += 1
60 else:
60 else:
61 raise error.ParseError(_("unterminated string"), s)
61 raise error.ParseError(_("unterminated string"), s)
62 elif c.isalnum() or c in '_':
62 elif c.isalnum() or c in '_':
63 s = pos
63 s = pos
64 pos += 1
64 pos += 1
65 while pos < end: # find end of symbol
65 while pos < end: # find end of symbol
66 d = program[pos]
66 d = program[pos]
67 if not (d.isalnum() or d == "_"):
67 if not (d.isalnum() or d == "_"):
68 break
68 break
69 pos += 1
69 pos += 1
70 sym = program[s:pos]
70 sym = program[s:pos]
71 yield ('symbol', sym, s)
71 yield ('symbol', sym, s)
72 pos -= 1
72 pos -= 1
73 elif c == '}':
73 elif c == '}':
74 pos += 1
74 pos += 1
75 break
75 break
76 else:
76 else:
77 raise error.ParseError(_("syntax error"), pos)
77 raise error.ParseError(_("syntax error"), pos)
78 pos += 1
78 pos += 1
79 yield ('end', None, pos)
79 yield ('end', None, pos)
80
80
81 def compiletemplate(tmpl, context, strtoken="string"):
81 def compiletemplate(tmpl, context, strtoken="string"):
82 parsed = []
82 parsed = []
83 pos, stop = 0, len(tmpl)
83 pos, stop = 0, len(tmpl)
84 p = parser.parser(tokenizer, elements)
84 p = parser.parser(tokenizer, elements)
85 while pos < stop:
85 while pos < stop:
86 n = tmpl.find('{', pos)
86 n = tmpl.find('{', pos)
87 if n < 0:
87 if n < 0:
88 parsed.append((strtoken, tmpl[pos:]))
88 parsed.append((strtoken, tmpl[pos:]))
89 break
89 break
90 bs = (n - pos) - len(tmpl[pos:n].rstrip('\\'))
90 bs = (n - pos) - len(tmpl[pos:n].rstrip('\\'))
91 if strtoken == 'string' and bs % 2 == 1:
91 if strtoken == 'string' and bs % 2 == 1:
92 # escaped (e.g. '\{', '\\\{', but not '\\{' nor r'\{')
92 # escaped (e.g. '\{', '\\\{', but not '\\{' nor r'\{')
93 parsed.append((strtoken, (tmpl[pos:n - 1] + "{")))
93 parsed.append((strtoken, (tmpl[pos:n - 1] + "{")))
94 pos = n + 1
94 pos = n + 1
95 continue
95 continue
96 if n > pos:
96 if n > pos:
97 parsed.append((strtoken, tmpl[pos:n]))
97 parsed.append((strtoken, tmpl[pos:n]))
98
98
99 pd = [tmpl, n + 1, stop]
99 pd = [tmpl, n + 1, stop]
100 parseres, pos = p.parse(pd)
100 parseres, pos = p.parse(pd)
101 parsed.append(parseres)
101 parsed.append(parseres)
102
102
103 return [compileexp(e, context) for e in parsed]
103 return [compileexp(e, context) for e in parsed]
104
104
105 def compileexp(exp, context):
105 def compileexp(exp, context):
106 t = exp[0]
106 t = exp[0]
107 if t in methods:
107 if t in methods:
108 return methods[t](exp, context)
108 return methods[t](exp, context)
109 raise error.ParseError(_("unknown method '%s'") % t)
109 raise error.ParseError(_("unknown method '%s'") % t)
110
110
111 # template evaluation
111 # template evaluation
112
112
113 def getsymbol(exp):
113 def getsymbol(exp):
114 if exp[0] == 'symbol':
114 if exp[0] == 'symbol':
115 return exp[1]
115 return exp[1]
116 raise error.ParseError(_("expected a symbol, got '%s'") % exp[0])
116 raise error.ParseError(_("expected a symbol, got '%s'") % exp[0])
117
117
118 def getlist(x):
118 def getlist(x):
119 if not x:
119 if not x:
120 return []
120 return []
121 if x[0] == 'list':
121 if x[0] == 'list':
122 return getlist(x[1]) + [x[2]]
122 return getlist(x[1]) + [x[2]]
123 return [x]
123 return [x]
124
124
125 def getfilter(exp, context):
125 def getfilter(exp, context):
126 f = getsymbol(exp)
126 f = getsymbol(exp)
127 if f not in context._filters:
127 if f not in context._filters:
128 raise error.ParseError(_("unknown function '%s'") % f)
128 raise error.ParseError(_("unknown function '%s'") % f)
129 return context._filters[f]
129 return context._filters[f]
130
130
131 def gettemplate(exp, context):
131 def gettemplate(exp, context):
132 if exp[0] == 'string' or exp[0] == 'rawstring':
132 if exp[0] == 'string' or exp[0] == 'rawstring':
133 return compiletemplate(exp[1], context, strtoken=exp[0])
133 return compiletemplate(exp[1], context, strtoken=exp[0])
134 if exp[0] == 'symbol':
134 if exp[0] == 'symbol':
135 return context._load(exp[1])
135 return context._load(exp[1])
136 raise error.ParseError(_("expected template specifier"))
136 raise error.ParseError(_("expected template specifier"))
137
137
138 def runstring(context, mapping, data):
138 def runstring(context, mapping, data):
139 return data.decode("string-escape")
139 return data.decode("string-escape")
140
140
141 def runrawstring(context, mapping, data):
141 def runrawstring(context, mapping, data):
142 return data
142 return data
143
143
144 def runsymbol(context, mapping, key):
144 def runsymbol(context, mapping, key):
145 v = mapping.get(key)
145 v = mapping.get(key)
146 if v is None:
146 if v is None:
147 v = context._defaults.get(key)
147 v = context._defaults.get(key)
148 if v is None:
148 if v is None:
149 try:
149 try:
150 v = context.process(key, mapping)
150 v = context.process(key, mapping)
151 except TemplateNotFound:
151 except TemplateNotFound:
152 v = ''
152 v = ''
153 if callable(v):
153 if callable(v):
154 return v(**mapping)
154 return v(**mapping)
155 if isinstance(v, types.GeneratorType):
155 if isinstance(v, types.GeneratorType):
156 v = list(v)
156 v = list(v)
157 return v
157 return v
158
158
159 def buildfilter(exp, context):
159 def buildfilter(exp, context):
160 func, data = compileexp(exp[1], context)
160 func, data = compileexp(exp[1], context)
161 filt = getfilter(exp[2], context)
161 filt = getfilter(exp[2], context)
162 return (runfilter, (func, data, filt))
162 return (runfilter, (func, data, filt))
163
163
164 def runfilter(context, mapping, data):
164 def runfilter(context, mapping, data):
165 func, data, filt = data
165 func, data, filt = data
166 # func() may return string, generator of strings or arbitrary object such
166 # func() may return string, generator of strings or arbitrary object such
167 # as date tuple, but filter does not want generator.
167 # as date tuple, but filter does not want generator.
168 thing = func(context, mapping, data)
168 thing = func(context, mapping, data)
169 if isinstance(thing, types.GeneratorType):
169 if isinstance(thing, types.GeneratorType):
170 thing = stringify(thing)
170 thing = stringify(thing)
171 try:
171 try:
172 return filt(thing)
172 return filt(thing)
173 except (ValueError, AttributeError, TypeError):
173 except (ValueError, AttributeError, TypeError):
174 if isinstance(data, tuple):
174 if isinstance(data, tuple):
175 dt = data[1]
175 dt = data[1]
176 else:
176 else:
177 dt = data
177 dt = data
178 raise util.Abort(_("template filter '%s' is not compatible with "
178 raise util.Abort(_("template filter '%s' is not compatible with "
179 "keyword '%s'") % (filt.func_name, dt))
179 "keyword '%s'") % (filt.func_name, dt))
180
180
181 def buildmap(exp, context):
181 def buildmap(exp, context):
182 func, data = compileexp(exp[1], context)
182 func, data = compileexp(exp[1], context)
183 ctmpl = gettemplate(exp[2], context)
183 ctmpl = gettemplate(exp[2], context)
184 return (runmap, (func, data, ctmpl))
184 return (runmap, (func, data, ctmpl))
185
185
186 def runtemplate(context, mapping, template):
186 def runtemplate(context, mapping, template):
187 for func, data in template:
187 for func, data in template:
188 yield func(context, mapping, data)
188 yield func(context, mapping, data)
189
189
190 def runmap(context, mapping, data):
190 def runmap(context, mapping, data):
191 func, data, ctmpl = data
191 func, data, ctmpl = data
192 d = func(context, mapping, data)
192 d = func(context, mapping, data)
193 if callable(d):
193 if callable(d):
194 d = d()
194 d = d()
195
195
196 lm = mapping.copy()
196 lm = mapping.copy()
197
197
198 for i in d:
198 for i in d:
199 if isinstance(i, dict):
199 if isinstance(i, dict):
200 lm.update(i)
200 lm.update(i)
201 lm['originalnode'] = mapping.get('node')
201 lm['originalnode'] = mapping.get('node')
202 yield runtemplate(context, lm, ctmpl)
202 yield runtemplate(context, lm, ctmpl)
203 else:
203 else:
204 # v is not an iterable of dicts, this happen when 'key'
204 # v is not an iterable of dicts, this happen when 'key'
205 # has been fully expanded already and format is useless.
205 # has been fully expanded already and format is useless.
206 # If so, return the expanded value.
206 # If so, return the expanded value.
207 yield i
207 yield i
208
208
209 def buildfunc(exp, context):
209 def buildfunc(exp, context):
210 n = getsymbol(exp[1])
210 n = getsymbol(exp[1])
211 args = [compileexp(x, context) for x in getlist(exp[2])]
211 args = [compileexp(x, context) for x in getlist(exp[2])]
212 if n in funcs:
212 if n in funcs:
213 f = funcs[n]
213 f = funcs[n]
214 return (f, args)
214 return (f, args)
215 if n in context._filters:
215 if n in context._filters:
216 if len(args) != 1:
216 if len(args) != 1:
217 raise error.ParseError(_("filter %s expects one argument") % n)
217 raise error.ParseError(_("filter %s expects one argument") % n)
218 f = context._filters[n]
218 f = context._filters[n]
219 return (runfilter, (args[0][0], args[0][1], f))
219 return (runfilter, (args[0][0], args[0][1], f))
220 raise error.ParseError(_("unknown function '%s'") % n)
220 raise error.ParseError(_("unknown function '%s'") % n)
221
221
222 def date(context, mapping, args):
222 def date(context, mapping, args):
223 """:date(date[, fmt]): Format a date. See :hg:`help dates` for formatting
223 """:date(date[, fmt]): Format a date. See :hg:`help dates` for formatting
224 strings."""
224 strings."""
225 if not (1 <= len(args) <= 2):
225 if not (1 <= len(args) <= 2):
226 # i18n: "date" is a keyword
226 # i18n: "date" is a keyword
227 raise error.ParseError(_("date expects one or two arguments"))
227 raise error.ParseError(_("date expects one or two arguments"))
228
228
229 date = args[0][0](context, mapping, args[0][1])
229 date = args[0][0](context, mapping, args[0][1])
230 fmt = None
230 fmt = None
231 if len(args) == 2:
231 if len(args) == 2:
232 fmt = stringify(args[1][0](context, mapping, args[1][1]))
232 fmt = stringify(args[1][0](context, mapping, args[1][1]))
233 try:
233 try:
234 if fmt is None:
234 if fmt is None:
235 return util.datestr(date)
235 return util.datestr(date)
236 else:
236 else:
237 return util.datestr(date, fmt)
237 return util.datestr(date, fmt)
238 except (TypeError, ValueError):
238 except (TypeError, ValueError):
239 # i18n: "date" is a keyword
239 # i18n: "date" is a keyword
240 raise error.ParseError(_("date expects a date information"))
240 raise error.ParseError(_("date expects a date information"))
241
241
242 def diff(context, mapping, args):
242 def diff(context, mapping, args):
243 """:diff([includepattern [, excludepattern]]): Show a diff, optionally
243 """:diff([includepattern [, excludepattern]]): Show a diff, optionally
244 specifying files to include or exclude."""
244 specifying files to include or exclude."""
245 if len(args) > 2:
245 if len(args) > 2:
246 # i18n: "diff" is a keyword
246 # i18n: "diff" is a keyword
247 raise error.ParseError(_("diff expects one, two or no arguments"))
247 raise error.ParseError(_("diff expects one, two or no arguments"))
248
248
249 def getpatterns(i):
249 def getpatterns(i):
250 if i < len(args):
250 if i < len(args):
251 s = args[i][1].strip()
251 s = args[i][1].strip()
252 if s:
252 if s:
253 return [s]
253 return [s]
254 return []
254 return []
255
255
256 ctx = mapping['ctx']
256 ctx = mapping['ctx']
257 chunks = ctx.diff(match=ctx.match([], getpatterns(0), getpatterns(1)))
257 chunks = ctx.diff(match=ctx.match([], getpatterns(0), getpatterns(1)))
258
258
259 return ''.join(chunks)
259 return ''.join(chunks)
260
260
261 def fill(context, mapping, args):
261 def fill(context, mapping, args):
262 """:fill(text[, width[, initialident[, hangindent]]]): Fill many
262 """:fill(text[, width[, initialident[, hangindent]]]): Fill many
263 paragraphs with optional indentation. See the "fill" filter."""
263 paragraphs with optional indentation. See the "fill" filter."""
264 if not (1 <= len(args) <= 4):
264 if not (1 <= len(args) <= 4):
265 # i18n: "fill" is a keyword
265 # i18n: "fill" is a keyword
266 raise error.ParseError(_("fill expects one to four arguments"))
266 raise error.ParseError(_("fill expects one to four arguments"))
267
267
268 text = stringify(args[0][0](context, mapping, args[0][1]))
268 text = stringify(args[0][0](context, mapping, args[0][1]))
269 width = 76
269 width = 76
270 initindent = ''
270 initindent = ''
271 hangindent = ''
271 hangindent = ''
272 if 2 <= len(args) <= 4:
272 if 2 <= len(args) <= 4:
273 try:
273 try:
274 width = int(stringify(args[1][0](context, mapping, args[1][1])))
274 width = int(stringify(args[1][0](context, mapping, args[1][1])))
275 except ValueError:
275 except ValueError:
276 # i18n: "fill" is a keyword
276 # i18n: "fill" is a keyword
277 raise error.ParseError(_("fill expects an integer width"))
277 raise error.ParseError(_("fill expects an integer width"))
278 try:
278 try:
279 initindent = stringify(_evalifliteral(args[2], context, mapping))
279 initindent = stringify(_evalifliteral(args[2], context, mapping))
280 hangindent = stringify(_evalifliteral(args[3], context, mapping))
280 hangindent = stringify(_evalifliteral(args[3], context, mapping))
281 except IndexError:
281 except IndexError:
282 pass
282 pass
283
283
284 return templatefilters.fill(text, width, initindent, hangindent)
284 return templatefilters.fill(text, width, initindent, hangindent)
285
285
286 def pad(context, mapping, args):
286 def pad(context, mapping, args):
287 """:pad(text, width[, fillchar=' '[, right=False]]): Pad text with a
287 """:pad(text, width[, fillchar=' '[, right=False]]): Pad text with a
288 fill character."""
288 fill character."""
289 if not (2 <= len(args) <= 4):
289 if not (2 <= len(args) <= 4):
290 # i18n: "pad" is a keyword
290 # i18n: "pad" is a keyword
291 raise error.ParseError(_("pad() expects two to four arguments"))
291 raise error.ParseError(_("pad() expects two to four arguments"))
292
292
293 width = int(args[1][1])
293 width = int(args[1][1])
294
294
295 text = stringify(args[0][0](context, mapping, args[0][1]))
295 text = stringify(args[0][0](context, mapping, args[0][1]))
296 if args[0][0] == runstring:
296 if args[0][0] == runstring:
297 text = stringify(runtemplate(context, mapping,
297 text = stringify(runtemplate(context, mapping,
298 compiletemplate(text, context)))
298 compiletemplate(text, context)))
299
299
300 right = False
300 right = False
301 fillchar = ' '
301 fillchar = ' '
302 if len(args) > 2:
302 if len(args) > 2:
303 fillchar = stringify(args[2][0](context, mapping, args[2][1]))
303 fillchar = stringify(args[2][0](context, mapping, args[2][1]))
304 if len(args) > 3:
304 if len(args) > 3:
305 right = util.parsebool(args[3][1])
305 right = util.parsebool(args[3][1])
306
306
307 if right:
307 if right:
308 return text.rjust(width, fillchar)
308 return text.rjust(width, fillchar)
309 else:
309 else:
310 return text.ljust(width, fillchar)
310 return text.ljust(width, fillchar)
311
311
312 def get(context, mapping, args):
312 def get(context, mapping, args):
313 """:get(dict, key): Get an attribute/key from an object. Some keywords
313 """:get(dict, key): Get an attribute/key from an object. Some keywords
314 are complex types. This function allows you to obtain the value of an
314 are complex types. This function allows you to obtain the value of an
315 attribute on these type."""
315 attribute on these type."""
316 if len(args) != 2:
316 if len(args) != 2:
317 # i18n: "get" is a keyword
317 # i18n: "get" is a keyword
318 raise error.ParseError(_("get() expects two arguments"))
318 raise error.ParseError(_("get() expects two arguments"))
319
319
320 dictarg = args[0][0](context, mapping, args[0][1])
320 dictarg = args[0][0](context, mapping, args[0][1])
321 if not util.safehasattr(dictarg, 'get'):
321 if not util.safehasattr(dictarg, 'get'):
322 # i18n: "get" is a keyword
322 # i18n: "get" is a keyword
323 raise error.ParseError(_("get() expects a dict as first argument"))
323 raise error.ParseError(_("get() expects a dict as first argument"))
324
324
325 key = args[1][0](context, mapping, args[1][1])
325 key = args[1][0](context, mapping, args[1][1])
326 yield dictarg.get(key)
326 yield dictarg.get(key)
327
327
328 def _evalifliteral(arg, context, mapping):
328 def _evalifliteral(arg, context, mapping):
329 t = stringify(arg[0](context, mapping, arg[1]))
329 # get back to token tag to reinterpret string as template
330 if arg[0] == runstring or arg[0] == runrawstring:
330 strtoken = {runstring: 'string', runrawstring: 'rawstring'}.get(arg[0])
331 if strtoken:
331 yield runtemplate(context, mapping,
332 yield runtemplate(context, mapping,
332 compiletemplate(t, context, strtoken='rawstring'))
333 compiletemplate(arg[1], context, strtoken))
333 else:
334 else:
334 yield t
335 yield stringify(arg[0](context, mapping, arg[1]))
335
336
336 def if_(context, mapping, args):
337 def if_(context, mapping, args):
337 """:if(expr, then[, else]): Conditionally execute based on the result of
338 """:if(expr, then[, else]): Conditionally execute based on the result of
338 an expression."""
339 an expression."""
339 if not (2 <= len(args) <= 3):
340 if not (2 <= len(args) <= 3):
340 # i18n: "if" is a keyword
341 # i18n: "if" is a keyword
341 raise error.ParseError(_("if expects two or three arguments"))
342 raise error.ParseError(_("if expects two or three arguments"))
342
343
343 test = stringify(args[0][0](context, mapping, args[0][1]))
344 test = stringify(args[0][0](context, mapping, args[0][1]))
344 if test:
345 if test:
345 yield _evalifliteral(args[1], context, mapping)
346 yield _evalifliteral(args[1], context, mapping)
346 elif len(args) == 3:
347 elif len(args) == 3:
347 yield _evalifliteral(args[2], context, mapping)
348 yield _evalifliteral(args[2], context, mapping)
348
349
349 def ifcontains(context, mapping, args):
350 def ifcontains(context, mapping, args):
350 """:ifcontains(search, thing, then[, else]): Conditionally execute based
351 """:ifcontains(search, thing, then[, else]): Conditionally execute based
351 on whether the item "search" is in "thing"."""
352 on whether the item "search" is in "thing"."""
352 if not (3 <= len(args) <= 4):
353 if not (3 <= len(args) <= 4):
353 # i18n: "ifcontains" is a keyword
354 # i18n: "ifcontains" is a keyword
354 raise error.ParseError(_("ifcontains expects three or four arguments"))
355 raise error.ParseError(_("ifcontains expects three or four arguments"))
355
356
356 item = stringify(args[0][0](context, mapping, args[0][1]))
357 item = stringify(args[0][0](context, mapping, args[0][1]))
357 items = args[1][0](context, mapping, args[1][1])
358 items = args[1][0](context, mapping, args[1][1])
358
359
359 if item in items:
360 if item in items:
360 yield _evalifliteral(args[2], context, mapping)
361 yield _evalifliteral(args[2], context, mapping)
361 elif len(args) == 4:
362 elif len(args) == 4:
362 yield _evalifliteral(args[3], context, mapping)
363 yield _evalifliteral(args[3], context, mapping)
363
364
364 def ifeq(context, mapping, args):
365 def ifeq(context, mapping, args):
365 """:ifeq(expr1, expr2, then[, else]): Conditionally execute based on
366 """:ifeq(expr1, expr2, then[, else]): Conditionally execute based on
366 whether 2 items are equivalent."""
367 whether 2 items are equivalent."""
367 if not (3 <= len(args) <= 4):
368 if not (3 <= len(args) <= 4):
368 # i18n: "ifeq" is a keyword
369 # i18n: "ifeq" is a keyword
369 raise error.ParseError(_("ifeq expects three or four arguments"))
370 raise error.ParseError(_("ifeq expects three or four arguments"))
370
371
371 test = stringify(args[0][0](context, mapping, args[0][1]))
372 test = stringify(args[0][0](context, mapping, args[0][1]))
372 match = stringify(args[1][0](context, mapping, args[1][1]))
373 match = stringify(args[1][0](context, mapping, args[1][1]))
373 if test == match:
374 if test == match:
374 yield _evalifliteral(args[2], context, mapping)
375 yield _evalifliteral(args[2], context, mapping)
375 elif len(args) == 4:
376 elif len(args) == 4:
376 yield _evalifliteral(args[3], context, mapping)
377 yield _evalifliteral(args[3], context, mapping)
377
378
378 def join(context, mapping, args):
379 def join(context, mapping, args):
379 """:join(list, sep): Join items in a list with a delimiter."""
380 """:join(list, sep): Join items in a list with a delimiter."""
380 if not (1 <= len(args) <= 2):
381 if not (1 <= len(args) <= 2):
381 # i18n: "join" is a keyword
382 # i18n: "join" is a keyword
382 raise error.ParseError(_("join expects one or two arguments"))
383 raise error.ParseError(_("join expects one or two arguments"))
383
384
384 joinset = args[0][0](context, mapping, args[0][1])
385 joinset = args[0][0](context, mapping, args[0][1])
385 if callable(joinset):
386 if callable(joinset):
386 jf = joinset.joinfmt
387 jf = joinset.joinfmt
387 joinset = [jf(x) for x in joinset()]
388 joinset = [jf(x) for x in joinset()]
388
389
389 joiner = " "
390 joiner = " "
390 if len(args) > 1:
391 if len(args) > 1:
391 joiner = stringify(args[1][0](context, mapping, args[1][1]))
392 joiner = stringify(args[1][0](context, mapping, args[1][1]))
392
393
393 first = True
394 first = True
394 for x in joinset:
395 for x in joinset:
395 if first:
396 if first:
396 first = False
397 first = False
397 else:
398 else:
398 yield joiner
399 yield joiner
399 yield x
400 yield x
400
401
401 def label(context, mapping, args):
402 def label(context, mapping, args):
402 """:label(label, expr): Apply a label to generated content. Content with
403 """:label(label, expr): Apply a label to generated content. Content with
403 a label applied can result in additional post-processing, such as
404 a label applied can result in additional post-processing, such as
404 automatic colorization."""
405 automatic colorization."""
405 if len(args) != 2:
406 if len(args) != 2:
406 # i18n: "label" is a keyword
407 # i18n: "label" is a keyword
407 raise error.ParseError(_("label expects two arguments"))
408 raise error.ParseError(_("label expects two arguments"))
408
409
409 # ignore args[0] (the label string) since this is supposed to be a a no-op
410 # ignore args[0] (the label string) since this is supposed to be a a no-op
410 yield _evalifliteral(args[1], context, mapping)
411 yield _evalifliteral(args[1], context, mapping)
411
412
412 def revset(context, mapping, args):
413 def revset(context, mapping, args):
413 """:revset(query[, formatargs...]): Execute a revision set query. See
414 """:revset(query[, formatargs...]): Execute a revision set query. See
414 :hg:`help revset`."""
415 :hg:`help revset`."""
415 if not len(args) > 0:
416 if not len(args) > 0:
416 # i18n: "revset" is a keyword
417 # i18n: "revset" is a keyword
417 raise error.ParseError(_("revset expects one or more arguments"))
418 raise error.ParseError(_("revset expects one or more arguments"))
418
419
419 raw = args[0][1]
420 raw = args[0][1]
420 ctx = mapping['ctx']
421 ctx = mapping['ctx']
421 repo = ctx.repo()
422 repo = ctx.repo()
422
423
423 def query(expr):
424 def query(expr):
424 m = revsetmod.match(repo.ui, expr)
425 m = revsetmod.match(repo.ui, expr)
425 return m(repo)
426 return m(repo)
426
427
427 if len(args) > 1:
428 if len(args) > 1:
428 formatargs = list([a[0](context, mapping, a[1]) for a in args[1:]])
429 formatargs = list([a[0](context, mapping, a[1]) for a in args[1:]])
429 revs = query(revsetmod.formatspec(raw, *formatargs))
430 revs = query(revsetmod.formatspec(raw, *formatargs))
430 revs = list([str(r) for r in revs])
431 revs = list([str(r) for r in revs])
431 else:
432 else:
432 revsetcache = mapping['cache'].setdefault("revsetcache", {})
433 revsetcache = mapping['cache'].setdefault("revsetcache", {})
433 if raw in revsetcache:
434 if raw in revsetcache:
434 revs = revsetcache[raw]
435 revs = revsetcache[raw]
435 else:
436 else:
436 revs = query(raw)
437 revs = query(raw)
437 revs = list([str(r) for r in revs])
438 revs = list([str(r) for r in revs])
438 revsetcache[raw] = revs
439 revsetcache[raw] = revs
439
440
440 return templatekw.showlist("revision", revs, **mapping)
441 return templatekw.showlist("revision", revs, **mapping)
441
442
442 def rstdoc(context, mapping, args):
443 def rstdoc(context, mapping, args):
443 """:rstdoc(text, style): Format ReStructuredText."""
444 """:rstdoc(text, style): Format ReStructuredText."""
444 if len(args) != 2:
445 if len(args) != 2:
445 # i18n: "rstdoc" is a keyword
446 # i18n: "rstdoc" is a keyword
446 raise error.ParseError(_("rstdoc expects two arguments"))
447 raise error.ParseError(_("rstdoc expects two arguments"))
447
448
448 text = stringify(args[0][0](context, mapping, args[0][1]))
449 text = stringify(args[0][0](context, mapping, args[0][1]))
449 style = stringify(args[1][0](context, mapping, args[1][1]))
450 style = stringify(args[1][0](context, mapping, args[1][1]))
450
451
451 return minirst.format(text, style=style, keep=['verbose'])
452 return minirst.format(text, style=style, keep=['verbose'])
452
453
453 def shortest(context, mapping, args):
454 def shortest(context, mapping, args):
454 """:shortest(node, minlength=4): Obtain the shortest representation of
455 """:shortest(node, minlength=4): Obtain the shortest representation of
455 a node."""
456 a node."""
456 if not (1 <= len(args) <= 2):
457 if not (1 <= len(args) <= 2):
457 # i18n: "shortest" is a keyword
458 # i18n: "shortest" is a keyword
458 raise error.ParseError(_("shortest() expects one or two arguments"))
459 raise error.ParseError(_("shortest() expects one or two arguments"))
459
460
460 node = stringify(args[0][0](context, mapping, args[0][1]))
461 node = stringify(args[0][0](context, mapping, args[0][1]))
461
462
462 minlength = 4
463 minlength = 4
463 if len(args) > 1:
464 if len(args) > 1:
464 minlength = int(args[1][1])
465 minlength = int(args[1][1])
465
466
466 cl = mapping['ctx']._repo.changelog
467 cl = mapping['ctx']._repo.changelog
467 def isvalid(test):
468 def isvalid(test):
468 try:
469 try:
469 try:
470 try:
470 cl.index.partialmatch(test)
471 cl.index.partialmatch(test)
471 except AttributeError:
472 except AttributeError:
472 # Pure mercurial doesn't support partialmatch on the index.
473 # Pure mercurial doesn't support partialmatch on the index.
473 # Fallback to the slow way.
474 # Fallback to the slow way.
474 if cl._partialmatch(test) is None:
475 if cl._partialmatch(test) is None:
475 return False
476 return False
476
477
477 try:
478 try:
478 i = int(test)
479 i = int(test)
479 # if we are a pure int, then starting with zero will not be
480 # if we are a pure int, then starting with zero will not be
480 # confused as a rev; or, obviously, if the int is larger than
481 # confused as a rev; or, obviously, if the int is larger than
481 # the value of the tip rev
482 # the value of the tip rev
482 if test[0] == '0' or i > len(cl):
483 if test[0] == '0' or i > len(cl):
483 return True
484 return True
484 return False
485 return False
485 except ValueError:
486 except ValueError:
486 return True
487 return True
487 except error.RevlogError:
488 except error.RevlogError:
488 return False
489 return False
489
490
490 shortest = node
491 shortest = node
491 startlength = max(6, minlength)
492 startlength = max(6, minlength)
492 length = startlength
493 length = startlength
493 while True:
494 while True:
494 test = node[:length]
495 test = node[:length]
495 if isvalid(test):
496 if isvalid(test):
496 shortest = test
497 shortest = test
497 if length == minlength or length > startlength:
498 if length == minlength or length > startlength:
498 return shortest
499 return shortest
499 length -= 1
500 length -= 1
500 else:
501 else:
501 length += 1
502 length += 1
502 if len(shortest) <= length:
503 if len(shortest) <= length:
503 return shortest
504 return shortest
504
505
505 def strip(context, mapping, args):
506 def strip(context, mapping, args):
506 """:strip(text[, chars]): Strip characters from a string."""
507 """:strip(text[, chars]): Strip characters from a string."""
507 if not (1 <= len(args) <= 2):
508 if not (1 <= len(args) <= 2):
508 # i18n: "strip" is a keyword
509 # i18n: "strip" is a keyword
509 raise error.ParseError(_("strip expects one or two arguments"))
510 raise error.ParseError(_("strip expects one or two arguments"))
510
511
511 text = stringify(args[0][0](context, mapping, args[0][1]))
512 text = stringify(args[0][0](context, mapping, args[0][1]))
512 if len(args) == 2:
513 if len(args) == 2:
513 chars = stringify(args[1][0](context, mapping, args[1][1]))
514 chars = stringify(args[1][0](context, mapping, args[1][1]))
514 return text.strip(chars)
515 return text.strip(chars)
515 return text.strip()
516 return text.strip()
516
517
517 def sub(context, mapping, args):
518 def sub(context, mapping, args):
518 """:sub(pattern, replacement, expression): Perform text substitution
519 """:sub(pattern, replacement, expression): Perform text substitution
519 using regular expressions."""
520 using regular expressions."""
520 if len(args) != 3:
521 if len(args) != 3:
521 # i18n: "sub" is a keyword
522 # i18n: "sub" is a keyword
522 raise error.ParseError(_("sub expects three arguments"))
523 raise error.ParseError(_("sub expects three arguments"))
523
524
524 pat = stringify(args[0][0](context, mapping, args[0][1]))
525 pat = stringify(args[0][0](context, mapping, args[0][1]))
525 rpl = stringify(args[1][0](context, mapping, args[1][1]))
526 rpl = stringify(args[1][0](context, mapping, args[1][1]))
526 src = stringify(_evalifliteral(args[2], context, mapping))
527 src = stringify(_evalifliteral(args[2], context, mapping))
527 yield re.sub(pat, rpl, src)
528 yield re.sub(pat, rpl, src)
528
529
529 def startswith(context, mapping, args):
530 def startswith(context, mapping, args):
530 """:startswith(pattern, text): Returns the value from the "text" argument
531 """:startswith(pattern, text): Returns the value from the "text" argument
531 if it begins with the content from the "pattern" argument."""
532 if it begins with the content from the "pattern" argument."""
532 if len(args) != 2:
533 if len(args) != 2:
533 # i18n: "startswith" is a keyword
534 # i18n: "startswith" is a keyword
534 raise error.ParseError(_("startswith expects two arguments"))
535 raise error.ParseError(_("startswith expects two arguments"))
535
536
536 patn = stringify(args[0][0](context, mapping, args[0][1]))
537 patn = stringify(args[0][0](context, mapping, args[0][1]))
537 text = stringify(args[1][0](context, mapping, args[1][1]))
538 text = stringify(args[1][0](context, mapping, args[1][1]))
538 if text.startswith(patn):
539 if text.startswith(patn):
539 return text
540 return text
540 return ''
541 return ''
541
542
542
543
543 def word(context, mapping, args):
544 def word(context, mapping, args):
544 """:word(number, text[, separator]): Return the nth word from a string."""
545 """:word(number, text[, separator]): Return the nth word from a string."""
545 if not (2 <= len(args) <= 3):
546 if not (2 <= len(args) <= 3):
546 # i18n: "word" is a keyword
547 # i18n: "word" is a keyword
547 raise error.ParseError(_("word expects two or three arguments, got %d")
548 raise error.ParseError(_("word expects two or three arguments, got %d")
548 % len(args))
549 % len(args))
549
550
550 try:
551 try:
551 num = int(stringify(args[0][0](context, mapping, args[0][1])))
552 num = int(stringify(args[0][0](context, mapping, args[0][1])))
552 except ValueError:
553 except ValueError:
553 # i18n: "word" is a keyword
554 # i18n: "word" is a keyword
554 raise error.ParseError(
555 raise error.ParseError(
555 _("Use strings like '3' for numbers passed to word function"))
556 _("Use strings like '3' for numbers passed to word function"))
556 text = stringify(args[1][0](context, mapping, args[1][1]))
557 text = stringify(args[1][0](context, mapping, args[1][1]))
557 if len(args) == 3:
558 if len(args) == 3:
558 splitter = stringify(args[2][0](context, mapping, args[2][1]))
559 splitter = stringify(args[2][0](context, mapping, args[2][1]))
559 else:
560 else:
560 splitter = None
561 splitter = None
561
562
562 tokens = text.split(splitter)
563 tokens = text.split(splitter)
563 if num >= len(tokens):
564 if num >= len(tokens):
564 return ''
565 return ''
565 else:
566 else:
566 return tokens[num]
567 return tokens[num]
567
568
568 methods = {
569 methods = {
569 "string": lambda e, c: (runstring, e[1]),
570 "string": lambda e, c: (runstring, e[1]),
570 "rawstring": lambda e, c: (runrawstring, e[1]),
571 "rawstring": lambda e, c: (runrawstring, e[1]),
571 "symbol": lambda e, c: (runsymbol, e[1]),
572 "symbol": lambda e, c: (runsymbol, e[1]),
572 "group": lambda e, c: compileexp(e[1], c),
573 "group": lambda e, c: compileexp(e[1], c),
573 # ".": buildmember,
574 # ".": buildmember,
574 "|": buildfilter,
575 "|": buildfilter,
575 "%": buildmap,
576 "%": buildmap,
576 "func": buildfunc,
577 "func": buildfunc,
577 }
578 }
578
579
579 funcs = {
580 funcs = {
580 "date": date,
581 "date": date,
581 "diff": diff,
582 "diff": diff,
582 "fill": fill,
583 "fill": fill,
583 "get": get,
584 "get": get,
584 "if": if_,
585 "if": if_,
585 "ifcontains": ifcontains,
586 "ifcontains": ifcontains,
586 "ifeq": ifeq,
587 "ifeq": ifeq,
587 "join": join,
588 "join": join,
588 "label": label,
589 "label": label,
589 "pad": pad,
590 "pad": pad,
590 "revset": revset,
591 "revset": revset,
591 "rstdoc": rstdoc,
592 "rstdoc": rstdoc,
592 "shortest": shortest,
593 "shortest": shortest,
593 "startswith": startswith,
594 "startswith": startswith,
594 "strip": strip,
595 "strip": strip,
595 "sub": sub,
596 "sub": sub,
596 "word": word,
597 "word": word,
597 }
598 }
598
599
599 # template engine
600 # template engine
600
601
601 stringify = templatefilters.stringify
602 stringify = templatefilters.stringify
602
603
603 def _flatten(thing):
604 def _flatten(thing):
604 '''yield a single stream from a possibly nested set of iterators'''
605 '''yield a single stream from a possibly nested set of iterators'''
605 if isinstance(thing, str):
606 if isinstance(thing, str):
606 yield thing
607 yield thing
607 elif not util.safehasattr(thing, '__iter__'):
608 elif not util.safehasattr(thing, '__iter__'):
608 if thing is not None:
609 if thing is not None:
609 yield str(thing)
610 yield str(thing)
610 else:
611 else:
611 for i in thing:
612 for i in thing:
612 if isinstance(i, str):
613 if isinstance(i, str):
613 yield i
614 yield i
614 elif not util.safehasattr(i, '__iter__'):
615 elif not util.safehasattr(i, '__iter__'):
615 if i is not None:
616 if i is not None:
616 yield str(i)
617 yield str(i)
617 elif i is not None:
618 elif i is not None:
618 for j in _flatten(i):
619 for j in _flatten(i):
619 yield j
620 yield j
620
621
621 def parsestring(s, quoted=True):
622 def parsestring(s, quoted=True):
622 '''unwrap quotes if quoted is True'''
623 '''unwrap quotes if quoted is True'''
623 if quoted:
624 if quoted:
624 if len(s) < 2 or s[0] != s[-1]:
625 if len(s) < 2 or s[0] != s[-1]:
625 raise SyntaxError(_('unmatched quotes'))
626 raise SyntaxError(_('unmatched quotes'))
626 return s[1:-1]
627 return s[1:-1]
627
628
628 return s
629 return s
629
630
630 class engine(object):
631 class engine(object):
631 '''template expansion engine.
632 '''template expansion engine.
632
633
633 template expansion works like this. a map file contains key=value
634 template expansion works like this. a map file contains key=value
634 pairs. if value is quoted, it is treated as string. otherwise, it
635 pairs. if value is quoted, it is treated as string. otherwise, it
635 is treated as name of template file.
636 is treated as name of template file.
636
637
637 templater is asked to expand a key in map. it looks up key, and
638 templater is asked to expand a key in map. it looks up key, and
638 looks for strings like this: {foo}. it expands {foo} by looking up
639 looks for strings like this: {foo}. it expands {foo} by looking up
639 foo in map, and substituting it. expansion is recursive: it stops
640 foo in map, and substituting it. expansion is recursive: it stops
640 when there is no more {foo} to replace.
641 when there is no more {foo} to replace.
641
642
642 expansion also allows formatting and filtering.
643 expansion also allows formatting and filtering.
643
644
644 format uses key to expand each item in list. syntax is
645 format uses key to expand each item in list. syntax is
645 {key%format}.
646 {key%format}.
646
647
647 filter uses function to transform value. syntax is
648 filter uses function to transform value. syntax is
648 {key|filter1|filter2|...}.'''
649 {key|filter1|filter2|...}.'''
649
650
650 def __init__(self, loader, filters={}, defaults={}):
651 def __init__(self, loader, filters={}, defaults={}):
651 self._loader = loader
652 self._loader = loader
652 self._filters = filters
653 self._filters = filters
653 self._defaults = defaults
654 self._defaults = defaults
654 self._cache = {}
655 self._cache = {}
655
656
656 def _load(self, t):
657 def _load(self, t):
657 '''load, parse, and cache a template'''
658 '''load, parse, and cache a template'''
658 if t not in self._cache:
659 if t not in self._cache:
659 self._cache[t] = compiletemplate(self._loader(t), self)
660 self._cache[t] = compiletemplate(self._loader(t), self)
660 return self._cache[t]
661 return self._cache[t]
661
662
662 def process(self, t, mapping):
663 def process(self, t, mapping):
663 '''Perform expansion. t is name of map element to expand.
664 '''Perform expansion. t is name of map element to expand.
664 mapping contains added elements for use during expansion. Is a
665 mapping contains added elements for use during expansion. Is a
665 generator.'''
666 generator.'''
666 return _flatten(runtemplate(self, mapping, self._load(t)))
667 return _flatten(runtemplate(self, mapping, self._load(t)))
667
668
668 engines = {'default': engine}
669 engines = {'default': engine}
669
670
670 def stylelist():
671 def stylelist():
671 paths = templatepaths()
672 paths = templatepaths()
672 if not paths:
673 if not paths:
673 return _('no templates found, try `hg debuginstall` for more info')
674 return _('no templates found, try `hg debuginstall` for more info')
674 dirlist = os.listdir(paths[0])
675 dirlist = os.listdir(paths[0])
675 stylelist = []
676 stylelist = []
676 for file in dirlist:
677 for file in dirlist:
677 split = file.split(".")
678 split = file.split(".")
678 if split[0] == "map-cmdline":
679 if split[0] == "map-cmdline":
679 stylelist.append(split[1])
680 stylelist.append(split[1])
680 return ", ".join(sorted(stylelist))
681 return ", ".join(sorted(stylelist))
681
682
682 class TemplateNotFound(util.Abort):
683 class TemplateNotFound(util.Abort):
683 pass
684 pass
684
685
685 class templater(object):
686 class templater(object):
686
687
687 def __init__(self, mapfile, filters={}, defaults={}, cache={},
688 def __init__(self, mapfile, filters={}, defaults={}, cache={},
688 minchunk=1024, maxchunk=65536):
689 minchunk=1024, maxchunk=65536):
689 '''set up template engine.
690 '''set up template engine.
690 mapfile is name of file to read map definitions from.
691 mapfile is name of file to read map definitions from.
691 filters is dict of functions. each transforms a value into another.
692 filters is dict of functions. each transforms a value into another.
692 defaults is dict of default map definitions.'''
693 defaults is dict of default map definitions.'''
693 self.mapfile = mapfile or 'template'
694 self.mapfile = mapfile or 'template'
694 self.cache = cache.copy()
695 self.cache = cache.copy()
695 self.map = {}
696 self.map = {}
696 if mapfile:
697 if mapfile:
697 self.base = os.path.dirname(mapfile)
698 self.base = os.path.dirname(mapfile)
698 else:
699 else:
699 self.base = ''
700 self.base = ''
700 self.filters = templatefilters.filters.copy()
701 self.filters = templatefilters.filters.copy()
701 self.filters.update(filters)
702 self.filters.update(filters)
702 self.defaults = defaults
703 self.defaults = defaults
703 self.minchunk, self.maxchunk = minchunk, maxchunk
704 self.minchunk, self.maxchunk = minchunk, maxchunk
704 self.ecache = {}
705 self.ecache = {}
705
706
706 if not mapfile:
707 if not mapfile:
707 return
708 return
708 if not os.path.exists(mapfile):
709 if not os.path.exists(mapfile):
709 raise util.Abort(_("style '%s' not found") % mapfile,
710 raise util.Abort(_("style '%s' not found") % mapfile,
710 hint=_("available styles: %s") % stylelist())
711 hint=_("available styles: %s") % stylelist())
711
712
712 conf = config.config()
713 conf = config.config()
713 conf.read(mapfile)
714 conf.read(mapfile)
714
715
715 for key, val in conf[''].items():
716 for key, val in conf[''].items():
716 if not val:
717 if not val:
717 raise SyntaxError(_('%s: missing value') % conf.source('', key))
718 raise SyntaxError(_('%s: missing value') % conf.source('', key))
718 if val[0] in "'\"":
719 if val[0] in "'\"":
719 try:
720 try:
720 self.cache[key] = parsestring(val)
721 self.cache[key] = parsestring(val)
721 except SyntaxError, inst:
722 except SyntaxError, inst:
722 raise SyntaxError('%s: %s' %
723 raise SyntaxError('%s: %s' %
723 (conf.source('', key), inst.args[0]))
724 (conf.source('', key), inst.args[0]))
724 else:
725 else:
725 val = 'default', val
726 val = 'default', val
726 if ':' in val[1]:
727 if ':' in val[1]:
727 val = val[1].split(':', 1)
728 val = val[1].split(':', 1)
728 self.map[key] = val[0], os.path.join(self.base, val[1])
729 self.map[key] = val[0], os.path.join(self.base, val[1])
729
730
730 def __contains__(self, key):
731 def __contains__(self, key):
731 return key in self.cache or key in self.map
732 return key in self.cache or key in self.map
732
733
733 def load(self, t):
734 def load(self, t):
734 '''Get the template for the given template name. Use a local cache.'''
735 '''Get the template for the given template name. Use a local cache.'''
735 if t not in self.cache:
736 if t not in self.cache:
736 try:
737 try:
737 self.cache[t] = util.readfile(self.map[t][1])
738 self.cache[t] = util.readfile(self.map[t][1])
738 except KeyError, inst:
739 except KeyError, inst:
739 raise TemplateNotFound(_('"%s" not in template map') %
740 raise TemplateNotFound(_('"%s" not in template map') %
740 inst.args[0])
741 inst.args[0])
741 except IOError, inst:
742 except IOError, inst:
742 raise IOError(inst.args[0], _('template file %s: %s') %
743 raise IOError(inst.args[0], _('template file %s: %s') %
743 (self.map[t][1], inst.args[1]))
744 (self.map[t][1], inst.args[1]))
744 return self.cache[t]
745 return self.cache[t]
745
746
746 def __call__(self, t, **mapping):
747 def __call__(self, t, **mapping):
747 ttype = t in self.map and self.map[t][0] or 'default'
748 ttype = t in self.map and self.map[t][0] or 'default'
748 if ttype not in self.ecache:
749 if ttype not in self.ecache:
749 self.ecache[ttype] = engines[ttype](self.load,
750 self.ecache[ttype] = engines[ttype](self.load,
750 self.filters, self.defaults)
751 self.filters, self.defaults)
751 proc = self.ecache[ttype]
752 proc = self.ecache[ttype]
752
753
753 stream = proc.process(t, mapping)
754 stream = proc.process(t, mapping)
754 if self.minchunk:
755 if self.minchunk:
755 stream = util.increasingchunks(stream, min=self.minchunk,
756 stream = util.increasingchunks(stream, min=self.minchunk,
756 max=self.maxchunk)
757 max=self.maxchunk)
757 return stream
758 return stream
758
759
759 def templatepaths():
760 def templatepaths():
760 '''return locations used for template files.'''
761 '''return locations used for template files.'''
761 pathsrel = ['templates']
762 pathsrel = ['templates']
762 paths = [os.path.normpath(os.path.join(util.datapath, f))
763 paths = [os.path.normpath(os.path.join(util.datapath, f))
763 for f in pathsrel]
764 for f in pathsrel]
764 return [p for p in paths if os.path.isdir(p)]
765 return [p for p in paths if os.path.isdir(p)]
765
766
766 def templatepath(name):
767 def templatepath(name):
767 '''return location of template file. returns None if not found.'''
768 '''return location of template file. returns None if not found.'''
768 for p in templatepaths():
769 for p in templatepaths():
769 f = os.path.join(p, name)
770 f = os.path.join(p, name)
770 if os.path.exists(f):
771 if os.path.exists(f):
771 return f
772 return f
772 return None
773 return None
773
774
774 def stylemap(styles, paths=None):
775 def stylemap(styles, paths=None):
775 """Return path to mapfile for a given style.
776 """Return path to mapfile for a given style.
776
777
777 Searches mapfile in the following locations:
778 Searches mapfile in the following locations:
778 1. templatepath/style/map
779 1. templatepath/style/map
779 2. templatepath/map-style
780 2. templatepath/map-style
780 3. templatepath/map
781 3. templatepath/map
781 """
782 """
782
783
783 if paths is None:
784 if paths is None:
784 paths = templatepaths()
785 paths = templatepaths()
785 elif isinstance(paths, str):
786 elif isinstance(paths, str):
786 paths = [paths]
787 paths = [paths]
787
788
788 if isinstance(styles, str):
789 if isinstance(styles, str):
789 styles = [styles]
790 styles = [styles]
790
791
791 for style in styles:
792 for style in styles:
792 # only plain name is allowed to honor template paths
793 # only plain name is allowed to honor template paths
793 if (not style
794 if (not style
794 or style in (os.curdir, os.pardir)
795 or style in (os.curdir, os.pardir)
795 or os.sep in style
796 or os.sep in style
796 or os.altsep and os.altsep in style):
797 or os.altsep and os.altsep in style):
797 continue
798 continue
798 locations = [os.path.join(style, 'map'), 'map-' + style]
799 locations = [os.path.join(style, 'map'), 'map-' + style]
799 locations.append('map')
800 locations.append('map')
800
801
801 for path in paths:
802 for path in paths:
802 for location in locations:
803 for location in locations:
803 mapfile = os.path.join(path, location)
804 mapfile = os.path.join(path, location)
804 if os.path.isfile(mapfile):
805 if os.path.isfile(mapfile):
805 return style, mapfile
806 return style, mapfile
806
807
807 raise RuntimeError("No hgweb templates found in %r" % paths)
808 raise RuntimeError("No hgweb templates found in %r" % paths)
808
809
809 # tell hggettext to extract docstrings from these functions:
810 # tell hggettext to extract docstrings from these functions:
810 i18nfunctions = funcs.values()
811 i18nfunctions = funcs.values()
@@ -1,2668 +1,2679 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 Quoting for ui.logtemplate
54 Quoting for ui.logtemplate
55
55
56 $ hg tip --config "ui.logtemplate={rev}\n"
56 $ hg tip --config "ui.logtemplate={rev}\n"
57 8
57 8
58 $ hg tip --config "ui.logtemplate='{rev}\n'"
58 $ hg tip --config "ui.logtemplate='{rev}\n'"
59 8
59 8
60 $ hg tip --config 'ui.logtemplate="{rev}\n"'
60 $ hg tip --config 'ui.logtemplate="{rev}\n"'
61 8
61 8
62
62
63 Make sure user/global hgrc does not affect tests
63 Make sure user/global hgrc does not affect tests
64
64
65 $ echo '[ui]' > .hg/hgrc
65 $ echo '[ui]' > .hg/hgrc
66 $ echo 'logtemplate =' >> .hg/hgrc
66 $ echo 'logtemplate =' >> .hg/hgrc
67 $ echo 'style =' >> .hg/hgrc
67 $ echo 'style =' >> .hg/hgrc
68
68
69 Add some simple styles to settings
69 Add some simple styles to settings
70
70
71 $ echo '[templates]' >> .hg/hgrc
71 $ echo '[templates]' >> .hg/hgrc
72 $ printf 'simple = "{rev}\\n"\n' >> .hg/hgrc
72 $ printf 'simple = "{rev}\\n"\n' >> .hg/hgrc
73 $ printf 'simple2 = {rev}\\n\n' >> .hg/hgrc
73 $ printf 'simple2 = {rev}\\n\n' >> .hg/hgrc
74
74
75 $ hg log -l1 -Tsimple
75 $ hg log -l1 -Tsimple
76 8
76 8
77 $ hg log -l1 -Tsimple2
77 $ hg log -l1 -Tsimple2
78 8
78 8
79
79
80 Test templates and style maps in files:
80 Test templates and style maps in files:
81
81
82 $ echo "{rev}" > tmpl
82 $ echo "{rev}" > tmpl
83 $ hg log -l1 -T./tmpl
83 $ hg log -l1 -T./tmpl
84 8
84 8
85 $ hg log -l1 -Tblah/blah
85 $ hg log -l1 -Tblah/blah
86 blah/blah (no-eol)
86 blah/blah (no-eol)
87
87
88 $ printf 'changeset = "{rev}\\n"\n' > map-simple
88 $ printf 'changeset = "{rev}\\n"\n' > map-simple
89 $ hg log -l1 -T./map-simple
89 $ hg log -l1 -T./map-simple
90 8
90 8
91
91
92 Template should precede style option
92 Template should precede style option
93
93
94 $ hg log -l1 --style default -T '{rev}\n'
94 $ hg log -l1 --style default -T '{rev}\n'
95 8
95 8
96
96
97 Add a commit with empty description, to ensure that the templates
97 Add a commit with empty description, to ensure that the templates
98 following below omit it properly.
98 following below omit it properly.
99
99
100 $ echo c >> c
100 $ echo c >> c
101 $ hg add c
101 $ hg add c
102 $ hg commit -qm ' '
102 $ hg commit -qm ' '
103
103
104 Default style is like normal output. Phases style should be the same
104 Default style is like normal output. Phases style should be the same
105 as default style, except for extra phase lines.
105 as default style, except for extra phase lines.
106
106
107 $ hg log > log.out
107 $ hg log > log.out
108 $ hg log --style default > style.out
108 $ hg log --style default > style.out
109 $ cmp log.out style.out || diff -u log.out style.out
109 $ cmp log.out style.out || diff -u log.out style.out
110 $ hg log -T phases > phases.out
110 $ hg log -T phases > phases.out
111 $ diff -u log.out phases.out | grep "phase:"
111 $ diff -u log.out phases.out | grep "phase:"
112 +phase: draft
112 +phase: draft
113 +phase: draft
113 +phase: draft
114 +phase: draft
114 +phase: draft
115 +phase: draft
115 +phase: draft
116 +phase: draft
116 +phase: draft
117 +phase: draft
117 +phase: draft
118 +phase: draft
118 +phase: draft
119 +phase: draft
119 +phase: draft
120 +phase: draft
120 +phase: draft
121 +phase: draft
121 +phase: draft
122
122
123 $ hg log -v > log.out
123 $ hg log -v > log.out
124 $ hg log -v --style default > style.out
124 $ hg log -v --style default > style.out
125 $ cmp log.out style.out || diff -u log.out style.out
125 $ cmp log.out style.out || diff -u log.out style.out
126 $ hg log -v -T phases > phases.out
126 $ hg log -v -T phases > phases.out
127 $ diff -u log.out phases.out | grep phase:
127 $ diff -u log.out phases.out | grep phase:
128 +phase: draft
128 +phase: draft
129 +phase: draft
129 +phase: draft
130 +phase: draft
130 +phase: draft
131 +phase: draft
131 +phase: draft
132 +phase: draft
132 +phase: draft
133 +phase: draft
133 +phase: draft
134 +phase: draft
134 +phase: draft
135 +phase: draft
135 +phase: draft
136 +phase: draft
136 +phase: draft
137 +phase: draft
137 +phase: draft
138
138
139 $ hg log -q > log.out
139 $ hg log -q > log.out
140 $ hg log -q --style default > style.out
140 $ hg log -q --style default > style.out
141 $ cmp log.out style.out || diff -u log.out style.out
141 $ cmp log.out style.out || diff -u log.out style.out
142 $ hg log -q -T phases > phases.out
142 $ hg log -q -T phases > phases.out
143 $ cmp log.out phases.out || diff -u log.out phases.out
143 $ cmp log.out phases.out || diff -u log.out phases.out
144
144
145 $ hg log --debug > log.out
145 $ hg log --debug > log.out
146 $ hg log --debug --style default > style.out
146 $ hg log --debug --style default > style.out
147 $ cmp log.out style.out || diff -u log.out style.out
147 $ cmp log.out style.out || diff -u log.out style.out
148 $ hg log --debug -T phases > phases.out
148 $ hg log --debug -T phases > phases.out
149 $ cmp log.out phases.out || diff -u log.out phases.out
149 $ cmp log.out phases.out || diff -u log.out phases.out
150
150
151 Default style should also preserve color information (issue2866):
151 Default style should also preserve color information (issue2866):
152
152
153 $ cp $HGRCPATH $HGRCPATH-bak
153 $ cp $HGRCPATH $HGRCPATH-bak
154 $ cat <<EOF >> $HGRCPATH
154 $ cat <<EOF >> $HGRCPATH
155 > [extensions]
155 > [extensions]
156 > color=
156 > color=
157 > EOF
157 > EOF
158
158
159 $ hg --color=debug log > log.out
159 $ hg --color=debug log > log.out
160 $ hg --color=debug log --style default > style.out
160 $ hg --color=debug log --style default > style.out
161 $ cmp log.out style.out || diff -u log.out style.out
161 $ cmp log.out style.out || diff -u log.out style.out
162 $ hg --color=debug log -T phases > phases.out
162 $ hg --color=debug log -T phases > phases.out
163 $ diff -u log.out phases.out | grep phase:
163 $ diff -u log.out phases.out | grep phase:
164 +[log.phase|phase: draft]
164 +[log.phase|phase: draft]
165 +[log.phase|phase: draft]
165 +[log.phase|phase: draft]
166 +[log.phase|phase: draft]
166 +[log.phase|phase: draft]
167 +[log.phase|phase: draft]
167 +[log.phase|phase: draft]
168 +[log.phase|phase: draft]
168 +[log.phase|phase: draft]
169 +[log.phase|phase: draft]
169 +[log.phase|phase: draft]
170 +[log.phase|phase: draft]
170 +[log.phase|phase: draft]
171 +[log.phase|phase: draft]
171 +[log.phase|phase: draft]
172 +[log.phase|phase: draft]
172 +[log.phase|phase: draft]
173 +[log.phase|phase: draft]
173 +[log.phase|phase: draft]
174
174
175 $ hg --color=debug -v log > log.out
175 $ hg --color=debug -v log > log.out
176 $ hg --color=debug -v log --style default > style.out
176 $ hg --color=debug -v log --style default > style.out
177 $ cmp log.out style.out || diff -u log.out style.out
177 $ cmp log.out style.out || diff -u log.out style.out
178 $ hg --color=debug -v log -T phases > phases.out
178 $ hg --color=debug -v log -T phases > phases.out
179 $ diff -u log.out phases.out | grep phase:
179 $ diff -u log.out phases.out | grep phase:
180 +[log.phase|phase: draft]
180 +[log.phase|phase: draft]
181 +[log.phase|phase: draft]
181 +[log.phase|phase: draft]
182 +[log.phase|phase: draft]
182 +[log.phase|phase: draft]
183 +[log.phase|phase: draft]
183 +[log.phase|phase: draft]
184 +[log.phase|phase: draft]
184 +[log.phase|phase: draft]
185 +[log.phase|phase: draft]
185 +[log.phase|phase: draft]
186 +[log.phase|phase: draft]
186 +[log.phase|phase: draft]
187 +[log.phase|phase: draft]
187 +[log.phase|phase: draft]
188 +[log.phase|phase: draft]
188 +[log.phase|phase: draft]
189 +[log.phase|phase: draft]
189 +[log.phase|phase: draft]
190
190
191 $ hg --color=debug -q log > log.out
191 $ hg --color=debug -q log > log.out
192 $ hg --color=debug -q log --style default > style.out
192 $ hg --color=debug -q log --style default > style.out
193 $ cmp log.out style.out || diff -u log.out style.out
193 $ cmp log.out style.out || diff -u log.out style.out
194 $ hg --color=debug -q log -T phases > phases.out
194 $ hg --color=debug -q log -T phases > phases.out
195 $ cmp log.out phases.out || diff -u log.out phases.out
195 $ cmp log.out phases.out || diff -u log.out phases.out
196
196
197 $ hg --color=debug --debug log > log.out
197 $ hg --color=debug --debug log > log.out
198 $ hg --color=debug --debug log --style default > style.out
198 $ hg --color=debug --debug log --style default > style.out
199 $ cmp log.out style.out || diff -u log.out style.out
199 $ cmp log.out style.out || diff -u log.out style.out
200 $ hg --color=debug --debug log -T phases > phases.out
200 $ hg --color=debug --debug log -T phases > phases.out
201 $ cmp log.out phases.out || diff -u log.out phases.out
201 $ cmp log.out phases.out || diff -u log.out phases.out
202
202
203 $ mv $HGRCPATH-bak $HGRCPATH
203 $ mv $HGRCPATH-bak $HGRCPATH
204
204
205 Remove commit with empty commit message, so as to not pollute further
205 Remove commit with empty commit message, so as to not pollute further
206 tests.
206 tests.
207
207
208 $ hg --config extensions.strip= strip -q .
208 $ hg --config extensions.strip= strip -q .
209
209
210 Revision with no copies (used to print a traceback):
210 Revision with no copies (used to print a traceback):
211
211
212 $ hg tip -v --template '\n'
212 $ hg tip -v --template '\n'
213
213
214
214
215 Compact style works:
215 Compact style works:
216
216
217 $ hg log -Tcompact
217 $ hg log -Tcompact
218 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
218 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
219 third
219 third
220
220
221 7:-1 29114dbae42b 1970-01-12 13:46 +0000 user
221 7:-1 29114dbae42b 1970-01-12 13:46 +0000 user
222 second
222 second
223
223
224 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
224 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
225 merge
225 merge
226
226
227 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
227 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
228 new head
228 new head
229
229
230 4 bbe44766e73d 1970-01-17 04:53 +0000 person
230 4 bbe44766e73d 1970-01-17 04:53 +0000 person
231 new branch
231 new branch
232
232
233 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
233 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
234 no user, no domain
234 no user, no domain
235
235
236 2 97054abb4ab8 1970-01-14 21:20 +0000 other
236 2 97054abb4ab8 1970-01-14 21:20 +0000 other
237 no person
237 no person
238
238
239 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
239 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
240 other 1
240 other 1
241
241
242 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
242 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
243 line 1
243 line 1
244
244
245
245
246 $ hg log -v --style compact
246 $ hg log -v --style compact
247 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
247 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
248 third
248 third
249
249
250 7:-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
250 7:-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
251 second
251 second
252
252
253 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
253 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
254 merge
254 merge
255
255
256 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
256 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
257 new head
257 new head
258
258
259 4 bbe44766e73d 1970-01-17 04:53 +0000 person
259 4 bbe44766e73d 1970-01-17 04:53 +0000 person
260 new branch
260 new branch
261
261
262 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
262 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
263 no user, no domain
263 no user, no domain
264
264
265 2 97054abb4ab8 1970-01-14 21:20 +0000 other@place
265 2 97054abb4ab8 1970-01-14 21:20 +0000 other@place
266 no person
266 no person
267
267
268 1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
268 1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
269 other 1
269 other 1
270 other 2
270 other 2
271
271
272 other 3
272 other 3
273
273
274 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
274 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
275 line 1
275 line 1
276 line 2
276 line 2
277
277
278
278
279 $ hg log --debug --style compact
279 $ hg log --debug --style compact
280 8[tip]:7,-1 95c24699272e 2020-01-01 10:01 +0000 test
280 8[tip]:7,-1 95c24699272e 2020-01-01 10:01 +0000 test
281 third
281 third
282
282
283 7:-1,-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
283 7:-1,-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
284 second
284 second
285
285
286 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
286 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
287 merge
287 merge
288
288
289 5:3,-1 13207e5a10d9 1970-01-18 08:40 +0000 person
289 5:3,-1 13207e5a10d9 1970-01-18 08:40 +0000 person
290 new head
290 new head
291
291
292 4:3,-1 bbe44766e73d 1970-01-17 04:53 +0000 person
292 4:3,-1 bbe44766e73d 1970-01-17 04:53 +0000 person
293 new branch
293 new branch
294
294
295 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
295 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
296 no user, no domain
296 no user, no domain
297
297
298 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other@place
298 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other@place
299 no person
299 no person
300
300
301 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
301 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
302 other 1
302 other 1
303 other 2
303 other 2
304
304
305 other 3
305 other 3
306
306
307 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
307 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
308 line 1
308 line 1
309 line 2
309 line 2
310
310
311
311
312 Test xml styles:
312 Test xml styles:
313
313
314 $ hg log --style xml
314 $ hg log --style xml
315 <?xml version="1.0"?>
315 <?xml version="1.0"?>
316 <log>
316 <log>
317 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
317 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
318 <tag>tip</tag>
318 <tag>tip</tag>
319 <author email="test">test</author>
319 <author email="test">test</author>
320 <date>2020-01-01T10:01:00+00:00</date>
320 <date>2020-01-01T10:01:00+00:00</date>
321 <msg xml:space="preserve">third</msg>
321 <msg xml:space="preserve">third</msg>
322 </logentry>
322 </logentry>
323 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
323 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
324 <parent revision="-1" node="0000000000000000000000000000000000000000" />
324 <parent revision="-1" node="0000000000000000000000000000000000000000" />
325 <author email="user@hostname">User Name</author>
325 <author email="user@hostname">User Name</author>
326 <date>1970-01-12T13:46:40+00:00</date>
326 <date>1970-01-12T13:46:40+00:00</date>
327 <msg xml:space="preserve">second</msg>
327 <msg xml:space="preserve">second</msg>
328 </logentry>
328 </logentry>
329 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
329 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
330 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
330 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
331 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
331 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
332 <author email="person">person</author>
332 <author email="person">person</author>
333 <date>1970-01-18T08:40:01+00:00</date>
333 <date>1970-01-18T08:40:01+00:00</date>
334 <msg xml:space="preserve">merge</msg>
334 <msg xml:space="preserve">merge</msg>
335 </logentry>
335 </logentry>
336 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
336 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
337 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
337 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
338 <author email="person">person</author>
338 <author email="person">person</author>
339 <date>1970-01-18T08:40:00+00:00</date>
339 <date>1970-01-18T08:40:00+00:00</date>
340 <msg xml:space="preserve">new head</msg>
340 <msg xml:space="preserve">new head</msg>
341 </logentry>
341 </logentry>
342 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
342 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
343 <branch>foo</branch>
343 <branch>foo</branch>
344 <author email="person">person</author>
344 <author email="person">person</author>
345 <date>1970-01-17T04:53:20+00:00</date>
345 <date>1970-01-17T04:53:20+00:00</date>
346 <msg xml:space="preserve">new branch</msg>
346 <msg xml:space="preserve">new branch</msg>
347 </logentry>
347 </logentry>
348 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
348 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
349 <author email="person">person</author>
349 <author email="person">person</author>
350 <date>1970-01-16T01:06:40+00:00</date>
350 <date>1970-01-16T01:06:40+00:00</date>
351 <msg xml:space="preserve">no user, no domain</msg>
351 <msg xml:space="preserve">no user, no domain</msg>
352 </logentry>
352 </logentry>
353 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
353 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
354 <author email="other@place">other</author>
354 <author email="other@place">other</author>
355 <date>1970-01-14T21:20:00+00:00</date>
355 <date>1970-01-14T21:20:00+00:00</date>
356 <msg xml:space="preserve">no person</msg>
356 <msg xml:space="preserve">no person</msg>
357 </logentry>
357 </logentry>
358 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
358 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
359 <author email="other@place">A. N. Other</author>
359 <author email="other@place">A. N. Other</author>
360 <date>1970-01-13T17:33:20+00:00</date>
360 <date>1970-01-13T17:33:20+00:00</date>
361 <msg xml:space="preserve">other 1
361 <msg xml:space="preserve">other 1
362 other 2
362 other 2
363
363
364 other 3</msg>
364 other 3</msg>
365 </logentry>
365 </logentry>
366 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
366 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
367 <author email="user@hostname">User Name</author>
367 <author email="user@hostname">User Name</author>
368 <date>1970-01-12T13:46:40+00:00</date>
368 <date>1970-01-12T13:46:40+00:00</date>
369 <msg xml:space="preserve">line 1
369 <msg xml:space="preserve">line 1
370 line 2</msg>
370 line 2</msg>
371 </logentry>
371 </logentry>
372 </log>
372 </log>
373
373
374 $ hg log -v --style xml
374 $ hg log -v --style xml
375 <?xml version="1.0"?>
375 <?xml version="1.0"?>
376 <log>
376 <log>
377 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
377 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
378 <tag>tip</tag>
378 <tag>tip</tag>
379 <author email="test">test</author>
379 <author email="test">test</author>
380 <date>2020-01-01T10:01:00+00:00</date>
380 <date>2020-01-01T10:01:00+00:00</date>
381 <msg xml:space="preserve">third</msg>
381 <msg xml:space="preserve">third</msg>
382 <paths>
382 <paths>
383 <path action="A">fourth</path>
383 <path action="A">fourth</path>
384 <path action="A">third</path>
384 <path action="A">third</path>
385 <path action="R">second</path>
385 <path action="R">second</path>
386 </paths>
386 </paths>
387 <copies>
387 <copies>
388 <copy source="second">fourth</copy>
388 <copy source="second">fourth</copy>
389 </copies>
389 </copies>
390 </logentry>
390 </logentry>
391 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
391 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
392 <parent revision="-1" node="0000000000000000000000000000000000000000" />
392 <parent revision="-1" node="0000000000000000000000000000000000000000" />
393 <author email="user@hostname">User Name</author>
393 <author email="user@hostname">User Name</author>
394 <date>1970-01-12T13:46:40+00:00</date>
394 <date>1970-01-12T13:46:40+00:00</date>
395 <msg xml:space="preserve">second</msg>
395 <msg xml:space="preserve">second</msg>
396 <paths>
396 <paths>
397 <path action="A">second</path>
397 <path action="A">second</path>
398 </paths>
398 </paths>
399 </logentry>
399 </logentry>
400 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
400 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
401 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
401 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
402 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
402 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
403 <author email="person">person</author>
403 <author email="person">person</author>
404 <date>1970-01-18T08:40:01+00:00</date>
404 <date>1970-01-18T08:40:01+00:00</date>
405 <msg xml:space="preserve">merge</msg>
405 <msg xml:space="preserve">merge</msg>
406 <paths>
406 <paths>
407 </paths>
407 </paths>
408 </logentry>
408 </logentry>
409 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
409 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
410 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
410 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
411 <author email="person">person</author>
411 <author email="person">person</author>
412 <date>1970-01-18T08:40:00+00:00</date>
412 <date>1970-01-18T08:40:00+00:00</date>
413 <msg xml:space="preserve">new head</msg>
413 <msg xml:space="preserve">new head</msg>
414 <paths>
414 <paths>
415 <path action="A">d</path>
415 <path action="A">d</path>
416 </paths>
416 </paths>
417 </logentry>
417 </logentry>
418 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
418 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
419 <branch>foo</branch>
419 <branch>foo</branch>
420 <author email="person">person</author>
420 <author email="person">person</author>
421 <date>1970-01-17T04:53:20+00:00</date>
421 <date>1970-01-17T04:53:20+00:00</date>
422 <msg xml:space="preserve">new branch</msg>
422 <msg xml:space="preserve">new branch</msg>
423 <paths>
423 <paths>
424 </paths>
424 </paths>
425 </logentry>
425 </logentry>
426 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
426 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
427 <author email="person">person</author>
427 <author email="person">person</author>
428 <date>1970-01-16T01:06:40+00:00</date>
428 <date>1970-01-16T01:06:40+00:00</date>
429 <msg xml:space="preserve">no user, no domain</msg>
429 <msg xml:space="preserve">no user, no domain</msg>
430 <paths>
430 <paths>
431 <path action="M">c</path>
431 <path action="M">c</path>
432 </paths>
432 </paths>
433 </logentry>
433 </logentry>
434 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
434 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
435 <author email="other@place">other</author>
435 <author email="other@place">other</author>
436 <date>1970-01-14T21:20:00+00:00</date>
436 <date>1970-01-14T21:20:00+00:00</date>
437 <msg xml:space="preserve">no person</msg>
437 <msg xml:space="preserve">no person</msg>
438 <paths>
438 <paths>
439 <path action="A">c</path>
439 <path action="A">c</path>
440 </paths>
440 </paths>
441 </logentry>
441 </logentry>
442 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
442 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
443 <author email="other@place">A. N. Other</author>
443 <author email="other@place">A. N. Other</author>
444 <date>1970-01-13T17:33:20+00:00</date>
444 <date>1970-01-13T17:33:20+00:00</date>
445 <msg xml:space="preserve">other 1
445 <msg xml:space="preserve">other 1
446 other 2
446 other 2
447
447
448 other 3</msg>
448 other 3</msg>
449 <paths>
449 <paths>
450 <path action="A">b</path>
450 <path action="A">b</path>
451 </paths>
451 </paths>
452 </logentry>
452 </logentry>
453 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
453 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
454 <author email="user@hostname">User Name</author>
454 <author email="user@hostname">User Name</author>
455 <date>1970-01-12T13:46:40+00:00</date>
455 <date>1970-01-12T13:46:40+00:00</date>
456 <msg xml:space="preserve">line 1
456 <msg xml:space="preserve">line 1
457 line 2</msg>
457 line 2</msg>
458 <paths>
458 <paths>
459 <path action="A">a</path>
459 <path action="A">a</path>
460 </paths>
460 </paths>
461 </logentry>
461 </logentry>
462 </log>
462 </log>
463
463
464 $ hg log --debug --style xml
464 $ hg log --debug --style xml
465 <?xml version="1.0"?>
465 <?xml version="1.0"?>
466 <log>
466 <log>
467 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
467 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
468 <tag>tip</tag>
468 <tag>tip</tag>
469 <parent revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453" />
469 <parent revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453" />
470 <parent revision="-1" node="0000000000000000000000000000000000000000" />
470 <parent revision="-1" node="0000000000000000000000000000000000000000" />
471 <author email="test">test</author>
471 <author email="test">test</author>
472 <date>2020-01-01T10:01:00+00:00</date>
472 <date>2020-01-01T10:01:00+00:00</date>
473 <msg xml:space="preserve">third</msg>
473 <msg xml:space="preserve">third</msg>
474 <paths>
474 <paths>
475 <path action="A">fourth</path>
475 <path action="A">fourth</path>
476 <path action="A">third</path>
476 <path action="A">third</path>
477 <path action="R">second</path>
477 <path action="R">second</path>
478 </paths>
478 </paths>
479 <copies>
479 <copies>
480 <copy source="second">fourth</copy>
480 <copy source="second">fourth</copy>
481 </copies>
481 </copies>
482 <extra key="branch">default</extra>
482 <extra key="branch">default</extra>
483 </logentry>
483 </logentry>
484 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
484 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
485 <parent revision="-1" node="0000000000000000000000000000000000000000" />
485 <parent revision="-1" node="0000000000000000000000000000000000000000" />
486 <parent revision="-1" node="0000000000000000000000000000000000000000" />
486 <parent revision="-1" node="0000000000000000000000000000000000000000" />
487 <author email="user@hostname">User Name</author>
487 <author email="user@hostname">User Name</author>
488 <date>1970-01-12T13:46:40+00:00</date>
488 <date>1970-01-12T13:46:40+00:00</date>
489 <msg xml:space="preserve">second</msg>
489 <msg xml:space="preserve">second</msg>
490 <paths>
490 <paths>
491 <path action="A">second</path>
491 <path action="A">second</path>
492 </paths>
492 </paths>
493 <extra key="branch">default</extra>
493 <extra key="branch">default</extra>
494 </logentry>
494 </logentry>
495 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
495 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
496 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
496 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
497 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
497 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
498 <author email="person">person</author>
498 <author email="person">person</author>
499 <date>1970-01-18T08:40:01+00:00</date>
499 <date>1970-01-18T08:40:01+00:00</date>
500 <msg xml:space="preserve">merge</msg>
500 <msg xml:space="preserve">merge</msg>
501 <paths>
501 <paths>
502 </paths>
502 </paths>
503 <extra key="branch">default</extra>
503 <extra key="branch">default</extra>
504 </logentry>
504 </logentry>
505 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
505 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
506 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
506 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
507 <parent revision="-1" node="0000000000000000000000000000000000000000" />
507 <parent revision="-1" node="0000000000000000000000000000000000000000" />
508 <author email="person">person</author>
508 <author email="person">person</author>
509 <date>1970-01-18T08:40:00+00:00</date>
509 <date>1970-01-18T08:40:00+00:00</date>
510 <msg xml:space="preserve">new head</msg>
510 <msg xml:space="preserve">new head</msg>
511 <paths>
511 <paths>
512 <path action="A">d</path>
512 <path action="A">d</path>
513 </paths>
513 </paths>
514 <extra key="branch">default</extra>
514 <extra key="branch">default</extra>
515 </logentry>
515 </logentry>
516 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
516 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
517 <branch>foo</branch>
517 <branch>foo</branch>
518 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
518 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
519 <parent revision="-1" node="0000000000000000000000000000000000000000" />
519 <parent revision="-1" node="0000000000000000000000000000000000000000" />
520 <author email="person">person</author>
520 <author email="person">person</author>
521 <date>1970-01-17T04:53:20+00:00</date>
521 <date>1970-01-17T04:53:20+00:00</date>
522 <msg xml:space="preserve">new branch</msg>
522 <msg xml:space="preserve">new branch</msg>
523 <paths>
523 <paths>
524 </paths>
524 </paths>
525 <extra key="branch">foo</extra>
525 <extra key="branch">foo</extra>
526 </logentry>
526 </logentry>
527 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
527 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
528 <parent revision="2" node="97054abb4ab824450e9164180baf491ae0078465" />
528 <parent revision="2" node="97054abb4ab824450e9164180baf491ae0078465" />
529 <parent revision="-1" node="0000000000000000000000000000000000000000" />
529 <parent revision="-1" node="0000000000000000000000000000000000000000" />
530 <author email="person">person</author>
530 <author email="person">person</author>
531 <date>1970-01-16T01:06:40+00:00</date>
531 <date>1970-01-16T01:06:40+00:00</date>
532 <msg xml:space="preserve">no user, no domain</msg>
532 <msg xml:space="preserve">no user, no domain</msg>
533 <paths>
533 <paths>
534 <path action="M">c</path>
534 <path action="M">c</path>
535 </paths>
535 </paths>
536 <extra key="branch">default</extra>
536 <extra key="branch">default</extra>
537 </logentry>
537 </logentry>
538 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
538 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
539 <parent revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965" />
539 <parent revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965" />
540 <parent revision="-1" node="0000000000000000000000000000000000000000" />
540 <parent revision="-1" node="0000000000000000000000000000000000000000" />
541 <author email="other@place">other</author>
541 <author email="other@place">other</author>
542 <date>1970-01-14T21:20:00+00:00</date>
542 <date>1970-01-14T21:20:00+00:00</date>
543 <msg xml:space="preserve">no person</msg>
543 <msg xml:space="preserve">no person</msg>
544 <paths>
544 <paths>
545 <path action="A">c</path>
545 <path action="A">c</path>
546 </paths>
546 </paths>
547 <extra key="branch">default</extra>
547 <extra key="branch">default</extra>
548 </logentry>
548 </logentry>
549 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
549 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
550 <parent revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f" />
550 <parent revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f" />
551 <parent revision="-1" node="0000000000000000000000000000000000000000" />
551 <parent revision="-1" node="0000000000000000000000000000000000000000" />
552 <author email="other@place">A. N. Other</author>
552 <author email="other@place">A. N. Other</author>
553 <date>1970-01-13T17:33:20+00:00</date>
553 <date>1970-01-13T17:33:20+00:00</date>
554 <msg xml:space="preserve">other 1
554 <msg xml:space="preserve">other 1
555 other 2
555 other 2
556
556
557 other 3</msg>
557 other 3</msg>
558 <paths>
558 <paths>
559 <path action="A">b</path>
559 <path action="A">b</path>
560 </paths>
560 </paths>
561 <extra key="branch">default</extra>
561 <extra key="branch">default</extra>
562 </logentry>
562 </logentry>
563 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
563 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
564 <parent revision="-1" node="0000000000000000000000000000000000000000" />
564 <parent revision="-1" node="0000000000000000000000000000000000000000" />
565 <parent revision="-1" node="0000000000000000000000000000000000000000" />
565 <parent revision="-1" node="0000000000000000000000000000000000000000" />
566 <author email="user@hostname">User Name</author>
566 <author email="user@hostname">User Name</author>
567 <date>1970-01-12T13:46:40+00:00</date>
567 <date>1970-01-12T13:46:40+00:00</date>
568 <msg xml:space="preserve">line 1
568 <msg xml:space="preserve">line 1
569 line 2</msg>
569 line 2</msg>
570 <paths>
570 <paths>
571 <path action="A">a</path>
571 <path action="A">a</path>
572 </paths>
572 </paths>
573 <extra key="branch">default</extra>
573 <extra key="branch">default</extra>
574 </logentry>
574 </logentry>
575 </log>
575 </log>
576
576
577
577
578 Test JSON style:
578 Test JSON style:
579
579
580 $ hg log -k nosuch -Tjson
580 $ hg log -k nosuch -Tjson
581 []
581 []
582
582
583 $ hg log -qr . -Tjson
583 $ hg log -qr . -Tjson
584 [
584 [
585 {
585 {
586 "rev": 8,
586 "rev": 8,
587 "node": "95c24699272ef57d062b8bccc32c878bf841784a"
587 "node": "95c24699272ef57d062b8bccc32c878bf841784a"
588 }
588 }
589 ]
589 ]
590
590
591 $ hg log -vpr . -Tjson --stat
591 $ hg log -vpr . -Tjson --stat
592 [
592 [
593 {
593 {
594 "rev": 8,
594 "rev": 8,
595 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
595 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
596 "branch": "default",
596 "branch": "default",
597 "phase": "draft",
597 "phase": "draft",
598 "user": "test",
598 "user": "test",
599 "date": [1577872860, 0],
599 "date": [1577872860, 0],
600 "desc": "third",
600 "desc": "third",
601 "bookmarks": [],
601 "bookmarks": [],
602 "tags": ["tip"],
602 "tags": ["tip"],
603 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
603 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
604 "files": ["fourth", "second", "third"],
604 "files": ["fourth", "second", "third"],
605 "diffstat": " fourth | 1 +\n second | 1 -\n third | 1 +\n 3 files changed, 2 insertions(+), 1 deletions(-)\n",
605 "diffstat": " fourth | 1 +\n second | 1 -\n third | 1 +\n 3 files changed, 2 insertions(+), 1 deletions(-)\n",
606 "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"
606 "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"
607 }
607 }
608 ]
608 ]
609
609
610 honor --git but not format-breaking diffopts
610 honor --git but not format-breaking diffopts
611 $ hg --config diff.noprefix=True log --git -vpr . -Tjson
611 $ hg --config diff.noprefix=True log --git -vpr . -Tjson
612 [
612 [
613 {
613 {
614 "rev": 8,
614 "rev": 8,
615 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
615 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
616 "branch": "default",
616 "branch": "default",
617 "phase": "draft",
617 "phase": "draft",
618 "user": "test",
618 "user": "test",
619 "date": [1577872860, 0],
619 "date": [1577872860, 0],
620 "desc": "third",
620 "desc": "third",
621 "bookmarks": [],
621 "bookmarks": [],
622 "tags": ["tip"],
622 "tags": ["tip"],
623 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
623 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
624 "files": ["fourth", "second", "third"],
624 "files": ["fourth", "second", "third"],
625 "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"
625 "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"
626 }
626 }
627 ]
627 ]
628
628
629 $ hg log -T json
629 $ hg log -T json
630 [
630 [
631 {
631 {
632 "rev": 8,
632 "rev": 8,
633 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
633 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
634 "branch": "default",
634 "branch": "default",
635 "phase": "draft",
635 "phase": "draft",
636 "user": "test",
636 "user": "test",
637 "date": [1577872860, 0],
637 "date": [1577872860, 0],
638 "desc": "third",
638 "desc": "third",
639 "bookmarks": [],
639 "bookmarks": [],
640 "tags": ["tip"],
640 "tags": ["tip"],
641 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"]
641 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"]
642 },
642 },
643 {
643 {
644 "rev": 7,
644 "rev": 7,
645 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
645 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
646 "branch": "default",
646 "branch": "default",
647 "phase": "draft",
647 "phase": "draft",
648 "user": "User Name <user@hostname>",
648 "user": "User Name <user@hostname>",
649 "date": [1000000, 0],
649 "date": [1000000, 0],
650 "desc": "second",
650 "desc": "second",
651 "bookmarks": [],
651 "bookmarks": [],
652 "tags": [],
652 "tags": [],
653 "parents": ["0000000000000000000000000000000000000000"]
653 "parents": ["0000000000000000000000000000000000000000"]
654 },
654 },
655 {
655 {
656 "rev": 6,
656 "rev": 6,
657 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
657 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
658 "branch": "default",
658 "branch": "default",
659 "phase": "draft",
659 "phase": "draft",
660 "user": "person",
660 "user": "person",
661 "date": [1500001, 0],
661 "date": [1500001, 0],
662 "desc": "merge",
662 "desc": "merge",
663 "bookmarks": [],
663 "bookmarks": [],
664 "tags": [],
664 "tags": [],
665 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"]
665 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"]
666 },
666 },
667 {
667 {
668 "rev": 5,
668 "rev": 5,
669 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
669 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
670 "branch": "default",
670 "branch": "default",
671 "phase": "draft",
671 "phase": "draft",
672 "user": "person",
672 "user": "person",
673 "date": [1500000, 0],
673 "date": [1500000, 0],
674 "desc": "new head",
674 "desc": "new head",
675 "bookmarks": [],
675 "bookmarks": [],
676 "tags": [],
676 "tags": [],
677 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
677 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
678 },
678 },
679 {
679 {
680 "rev": 4,
680 "rev": 4,
681 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
681 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
682 "branch": "foo",
682 "branch": "foo",
683 "phase": "draft",
683 "phase": "draft",
684 "user": "person",
684 "user": "person",
685 "date": [1400000, 0],
685 "date": [1400000, 0],
686 "desc": "new branch",
686 "desc": "new branch",
687 "bookmarks": [],
687 "bookmarks": [],
688 "tags": [],
688 "tags": [],
689 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
689 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
690 },
690 },
691 {
691 {
692 "rev": 3,
692 "rev": 3,
693 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
693 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
694 "branch": "default",
694 "branch": "default",
695 "phase": "draft",
695 "phase": "draft",
696 "user": "person",
696 "user": "person",
697 "date": [1300000, 0],
697 "date": [1300000, 0],
698 "desc": "no user, no domain",
698 "desc": "no user, no domain",
699 "bookmarks": [],
699 "bookmarks": [],
700 "tags": [],
700 "tags": [],
701 "parents": ["97054abb4ab824450e9164180baf491ae0078465"]
701 "parents": ["97054abb4ab824450e9164180baf491ae0078465"]
702 },
702 },
703 {
703 {
704 "rev": 2,
704 "rev": 2,
705 "node": "97054abb4ab824450e9164180baf491ae0078465",
705 "node": "97054abb4ab824450e9164180baf491ae0078465",
706 "branch": "default",
706 "branch": "default",
707 "phase": "draft",
707 "phase": "draft",
708 "user": "other@place",
708 "user": "other@place",
709 "date": [1200000, 0],
709 "date": [1200000, 0],
710 "desc": "no person",
710 "desc": "no person",
711 "bookmarks": [],
711 "bookmarks": [],
712 "tags": [],
712 "tags": [],
713 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"]
713 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"]
714 },
714 },
715 {
715 {
716 "rev": 1,
716 "rev": 1,
717 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
717 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
718 "branch": "default",
718 "branch": "default",
719 "phase": "draft",
719 "phase": "draft",
720 "user": "A. N. Other <other@place>",
720 "user": "A. N. Other <other@place>",
721 "date": [1100000, 0],
721 "date": [1100000, 0],
722 "desc": "other 1\nother 2\n\nother 3",
722 "desc": "other 1\nother 2\n\nother 3",
723 "bookmarks": [],
723 "bookmarks": [],
724 "tags": [],
724 "tags": [],
725 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"]
725 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"]
726 },
726 },
727 {
727 {
728 "rev": 0,
728 "rev": 0,
729 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
729 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
730 "branch": "default",
730 "branch": "default",
731 "phase": "draft",
731 "phase": "draft",
732 "user": "User Name <user@hostname>",
732 "user": "User Name <user@hostname>",
733 "date": [1000000, 0],
733 "date": [1000000, 0],
734 "desc": "line 1\nline 2",
734 "desc": "line 1\nline 2",
735 "bookmarks": [],
735 "bookmarks": [],
736 "tags": [],
736 "tags": [],
737 "parents": ["0000000000000000000000000000000000000000"]
737 "parents": ["0000000000000000000000000000000000000000"]
738 }
738 }
739 ]
739 ]
740
740
741 $ hg heads -v -Tjson
741 $ hg heads -v -Tjson
742 [
742 [
743 {
743 {
744 "rev": 8,
744 "rev": 8,
745 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
745 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
746 "branch": "default",
746 "branch": "default",
747 "phase": "draft",
747 "phase": "draft",
748 "user": "test",
748 "user": "test",
749 "date": [1577872860, 0],
749 "date": [1577872860, 0],
750 "desc": "third",
750 "desc": "third",
751 "bookmarks": [],
751 "bookmarks": [],
752 "tags": ["tip"],
752 "tags": ["tip"],
753 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
753 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
754 "files": ["fourth", "second", "third"]
754 "files": ["fourth", "second", "third"]
755 },
755 },
756 {
756 {
757 "rev": 6,
757 "rev": 6,
758 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
758 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
759 "branch": "default",
759 "branch": "default",
760 "phase": "draft",
760 "phase": "draft",
761 "user": "person",
761 "user": "person",
762 "date": [1500001, 0],
762 "date": [1500001, 0],
763 "desc": "merge",
763 "desc": "merge",
764 "bookmarks": [],
764 "bookmarks": [],
765 "tags": [],
765 "tags": [],
766 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
766 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
767 "files": []
767 "files": []
768 },
768 },
769 {
769 {
770 "rev": 4,
770 "rev": 4,
771 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
771 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
772 "branch": "foo",
772 "branch": "foo",
773 "phase": "draft",
773 "phase": "draft",
774 "user": "person",
774 "user": "person",
775 "date": [1400000, 0],
775 "date": [1400000, 0],
776 "desc": "new branch",
776 "desc": "new branch",
777 "bookmarks": [],
777 "bookmarks": [],
778 "tags": [],
778 "tags": [],
779 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
779 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
780 "files": []
780 "files": []
781 }
781 }
782 ]
782 ]
783
783
784 $ hg log --debug -Tjson
784 $ hg log --debug -Tjson
785 [
785 [
786 {
786 {
787 "rev": 8,
787 "rev": 8,
788 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
788 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
789 "branch": "default",
789 "branch": "default",
790 "phase": "draft",
790 "phase": "draft",
791 "user": "test",
791 "user": "test",
792 "date": [1577872860, 0],
792 "date": [1577872860, 0],
793 "desc": "third",
793 "desc": "third",
794 "bookmarks": [],
794 "bookmarks": [],
795 "tags": ["tip"],
795 "tags": ["tip"],
796 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
796 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
797 "manifest": "94961b75a2da554b4df6fb599e5bfc7d48de0c64",
797 "manifest": "94961b75a2da554b4df6fb599e5bfc7d48de0c64",
798 "extra": {"branch": "default"},
798 "extra": {"branch": "default"},
799 "modified": [],
799 "modified": [],
800 "added": ["fourth", "third"],
800 "added": ["fourth", "third"],
801 "removed": ["second"]
801 "removed": ["second"]
802 },
802 },
803 {
803 {
804 "rev": 7,
804 "rev": 7,
805 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
805 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
806 "branch": "default",
806 "branch": "default",
807 "phase": "draft",
807 "phase": "draft",
808 "user": "User Name <user@hostname>",
808 "user": "User Name <user@hostname>",
809 "date": [1000000, 0],
809 "date": [1000000, 0],
810 "desc": "second",
810 "desc": "second",
811 "bookmarks": [],
811 "bookmarks": [],
812 "tags": [],
812 "tags": [],
813 "parents": ["0000000000000000000000000000000000000000"],
813 "parents": ["0000000000000000000000000000000000000000"],
814 "manifest": "f2dbc354b94e5ec0b4f10680ee0cee816101d0bf",
814 "manifest": "f2dbc354b94e5ec0b4f10680ee0cee816101d0bf",
815 "extra": {"branch": "default"},
815 "extra": {"branch": "default"},
816 "modified": [],
816 "modified": [],
817 "added": ["second"],
817 "added": ["second"],
818 "removed": []
818 "removed": []
819 },
819 },
820 {
820 {
821 "rev": 6,
821 "rev": 6,
822 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
822 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
823 "branch": "default",
823 "branch": "default",
824 "phase": "draft",
824 "phase": "draft",
825 "user": "person",
825 "user": "person",
826 "date": [1500001, 0],
826 "date": [1500001, 0],
827 "desc": "merge",
827 "desc": "merge",
828 "bookmarks": [],
828 "bookmarks": [],
829 "tags": [],
829 "tags": [],
830 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
830 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
831 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
831 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
832 "extra": {"branch": "default"},
832 "extra": {"branch": "default"},
833 "modified": [],
833 "modified": [],
834 "added": [],
834 "added": [],
835 "removed": []
835 "removed": []
836 },
836 },
837 {
837 {
838 "rev": 5,
838 "rev": 5,
839 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
839 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
840 "branch": "default",
840 "branch": "default",
841 "phase": "draft",
841 "phase": "draft",
842 "user": "person",
842 "user": "person",
843 "date": [1500000, 0],
843 "date": [1500000, 0],
844 "desc": "new head",
844 "desc": "new head",
845 "bookmarks": [],
845 "bookmarks": [],
846 "tags": [],
846 "tags": [],
847 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
847 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
848 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
848 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
849 "extra": {"branch": "default"},
849 "extra": {"branch": "default"},
850 "modified": [],
850 "modified": [],
851 "added": ["d"],
851 "added": ["d"],
852 "removed": []
852 "removed": []
853 },
853 },
854 {
854 {
855 "rev": 4,
855 "rev": 4,
856 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
856 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
857 "branch": "foo",
857 "branch": "foo",
858 "phase": "draft",
858 "phase": "draft",
859 "user": "person",
859 "user": "person",
860 "date": [1400000, 0],
860 "date": [1400000, 0],
861 "desc": "new branch",
861 "desc": "new branch",
862 "bookmarks": [],
862 "bookmarks": [],
863 "tags": [],
863 "tags": [],
864 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
864 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
865 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
865 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
866 "extra": {"branch": "foo"},
866 "extra": {"branch": "foo"},
867 "modified": [],
867 "modified": [],
868 "added": [],
868 "added": [],
869 "removed": []
869 "removed": []
870 },
870 },
871 {
871 {
872 "rev": 3,
872 "rev": 3,
873 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
873 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
874 "branch": "default",
874 "branch": "default",
875 "phase": "draft",
875 "phase": "draft",
876 "user": "person",
876 "user": "person",
877 "date": [1300000, 0],
877 "date": [1300000, 0],
878 "desc": "no user, no domain",
878 "desc": "no user, no domain",
879 "bookmarks": [],
879 "bookmarks": [],
880 "tags": [],
880 "tags": [],
881 "parents": ["97054abb4ab824450e9164180baf491ae0078465"],
881 "parents": ["97054abb4ab824450e9164180baf491ae0078465"],
882 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
882 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
883 "extra": {"branch": "default"},
883 "extra": {"branch": "default"},
884 "modified": ["c"],
884 "modified": ["c"],
885 "added": [],
885 "added": [],
886 "removed": []
886 "removed": []
887 },
887 },
888 {
888 {
889 "rev": 2,
889 "rev": 2,
890 "node": "97054abb4ab824450e9164180baf491ae0078465",
890 "node": "97054abb4ab824450e9164180baf491ae0078465",
891 "branch": "default",
891 "branch": "default",
892 "phase": "draft",
892 "phase": "draft",
893 "user": "other@place",
893 "user": "other@place",
894 "date": [1200000, 0],
894 "date": [1200000, 0],
895 "desc": "no person",
895 "desc": "no person",
896 "bookmarks": [],
896 "bookmarks": [],
897 "tags": [],
897 "tags": [],
898 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"],
898 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"],
899 "manifest": "6e0e82995c35d0d57a52aca8da4e56139e06b4b1",
899 "manifest": "6e0e82995c35d0d57a52aca8da4e56139e06b4b1",
900 "extra": {"branch": "default"},
900 "extra": {"branch": "default"},
901 "modified": [],
901 "modified": [],
902 "added": ["c"],
902 "added": ["c"],
903 "removed": []
903 "removed": []
904 },
904 },
905 {
905 {
906 "rev": 1,
906 "rev": 1,
907 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
907 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
908 "branch": "default",
908 "branch": "default",
909 "phase": "draft",
909 "phase": "draft",
910 "user": "A. N. Other <other@place>",
910 "user": "A. N. Other <other@place>",
911 "date": [1100000, 0],
911 "date": [1100000, 0],
912 "desc": "other 1\nother 2\n\nother 3",
912 "desc": "other 1\nother 2\n\nother 3",
913 "bookmarks": [],
913 "bookmarks": [],
914 "tags": [],
914 "tags": [],
915 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"],
915 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"],
916 "manifest": "4e8d705b1e53e3f9375e0e60dc7b525d8211fe55",
916 "manifest": "4e8d705b1e53e3f9375e0e60dc7b525d8211fe55",
917 "extra": {"branch": "default"},
917 "extra": {"branch": "default"},
918 "modified": [],
918 "modified": [],
919 "added": ["b"],
919 "added": ["b"],
920 "removed": []
920 "removed": []
921 },
921 },
922 {
922 {
923 "rev": 0,
923 "rev": 0,
924 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
924 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
925 "branch": "default",
925 "branch": "default",
926 "phase": "draft",
926 "phase": "draft",
927 "user": "User Name <user@hostname>",
927 "user": "User Name <user@hostname>",
928 "date": [1000000, 0],
928 "date": [1000000, 0],
929 "desc": "line 1\nline 2",
929 "desc": "line 1\nline 2",
930 "bookmarks": [],
930 "bookmarks": [],
931 "tags": [],
931 "tags": [],
932 "parents": ["0000000000000000000000000000000000000000"],
932 "parents": ["0000000000000000000000000000000000000000"],
933 "manifest": "a0c8bcbbb45c63b90b70ad007bf38961f64f2af0",
933 "manifest": "a0c8bcbbb45c63b90b70ad007bf38961f64f2af0",
934 "extra": {"branch": "default"},
934 "extra": {"branch": "default"},
935 "modified": [],
935 "modified": [],
936 "added": ["a"],
936 "added": ["a"],
937 "removed": []
937 "removed": []
938 }
938 }
939 ]
939 ]
940
940
941 Error if style not readable:
941 Error if style not readable:
942
942
943 #if unix-permissions no-root
943 #if unix-permissions no-root
944 $ touch q
944 $ touch q
945 $ chmod 0 q
945 $ chmod 0 q
946 $ hg log --style ./q
946 $ hg log --style ./q
947 abort: Permission denied: ./q
947 abort: Permission denied: ./q
948 [255]
948 [255]
949 #endif
949 #endif
950
950
951 Error if no style:
951 Error if no style:
952
952
953 $ hg log --style notexist
953 $ hg log --style notexist
954 abort: style 'notexist' not found
954 abort: style 'notexist' not found
955 (available styles: bisect, changelog, compact, default, phases, xml)
955 (available styles: bisect, changelog, compact, default, phases, xml)
956 [255]
956 [255]
957
957
958 $ hg log -T list
958 $ hg log -T list
959 available styles: bisect, changelog, compact, default, phases, xml
959 available styles: bisect, changelog, compact, default, phases, xml
960 abort: specify a template
960 abort: specify a template
961 [255]
961 [255]
962
962
963 Error if style missing key:
963 Error if style missing key:
964
964
965 $ echo 'q = q' > t
965 $ echo 'q = q' > t
966 $ hg log --style ./t
966 $ hg log --style ./t
967 abort: "changeset" not in template map
967 abort: "changeset" not in template map
968 [255]
968 [255]
969
969
970 Error if style missing value:
970 Error if style missing value:
971
971
972 $ echo 'changeset =' > t
972 $ echo 'changeset =' > t
973 $ hg log --style t
973 $ hg log --style t
974 abort: t:1: missing value
974 abort: t:1: missing value
975 [255]
975 [255]
976
976
977 Error if include fails:
977 Error if include fails:
978
978
979 $ echo 'changeset = q' >> t
979 $ echo 'changeset = q' >> t
980 #if unix-permissions no-root
980 #if unix-permissions no-root
981 $ hg log --style ./t
981 $ hg log --style ./t
982 abort: template file ./q: Permission denied
982 abort: template file ./q: Permission denied
983 [255]
983 [255]
984 $ rm q
984 $ rm q
985 #endif
985 #endif
986
986
987 Include works:
987 Include works:
988
988
989 $ echo '{rev}' > q
989 $ echo '{rev}' > q
990 $ hg log --style ./t
990 $ hg log --style ./t
991 8
991 8
992 7
992 7
993 6
993 6
994 5
994 5
995 4
995 4
996 3
996 3
997 2
997 2
998 1
998 1
999 0
999 0
1000
1000
1001 Check that {phase} works correctly on parents:
1001 Check that {phase} works correctly on parents:
1002
1002
1003 $ cat << EOF > parentphase
1003 $ cat << EOF > parentphase
1004 > changeset_debug = '{rev} ({phase}):{parents}\n'
1004 > changeset_debug = '{rev} ({phase}):{parents}\n'
1005 > parent = ' {rev} ({phase})'
1005 > parent = ' {rev} ({phase})'
1006 > EOF
1006 > EOF
1007 $ hg phase -r 5 --public
1007 $ hg phase -r 5 --public
1008 $ hg phase -r 7 --secret --force
1008 $ hg phase -r 7 --secret --force
1009 $ hg log --debug -G --style ./parentphase
1009 $ hg log --debug -G --style ./parentphase
1010 @ 8 (secret): 7 (secret) -1 (public)
1010 @ 8 (secret): 7 (secret) -1 (public)
1011 |
1011 |
1012 o 7 (secret): -1 (public) -1 (public)
1012 o 7 (secret): -1 (public) -1 (public)
1013
1013
1014 o 6 (draft): 5 (public) 4 (draft)
1014 o 6 (draft): 5 (public) 4 (draft)
1015 |\
1015 |\
1016 | o 5 (public): 3 (public) -1 (public)
1016 | o 5 (public): 3 (public) -1 (public)
1017 | |
1017 | |
1018 o | 4 (draft): 3 (public) -1 (public)
1018 o | 4 (draft): 3 (public) -1 (public)
1019 |/
1019 |/
1020 o 3 (public): 2 (public) -1 (public)
1020 o 3 (public): 2 (public) -1 (public)
1021 |
1021 |
1022 o 2 (public): 1 (public) -1 (public)
1022 o 2 (public): 1 (public) -1 (public)
1023 |
1023 |
1024 o 1 (public): 0 (public) -1 (public)
1024 o 1 (public): 0 (public) -1 (public)
1025 |
1025 |
1026 o 0 (public): -1 (public) -1 (public)
1026 o 0 (public): -1 (public) -1 (public)
1027
1027
1028
1028
1029 Missing non-standard names give no error (backward compatibility):
1029 Missing non-standard names give no error (backward compatibility):
1030
1030
1031 $ echo "changeset = '{c}'" > t
1031 $ echo "changeset = '{c}'" > t
1032 $ hg log --style ./t
1032 $ hg log --style ./t
1033
1033
1034 Defining non-standard name works:
1034 Defining non-standard name works:
1035
1035
1036 $ cat <<EOF > t
1036 $ cat <<EOF > t
1037 > changeset = '{c}'
1037 > changeset = '{c}'
1038 > c = q
1038 > c = q
1039 > EOF
1039 > EOF
1040 $ hg log --style ./t
1040 $ hg log --style ./t
1041 8
1041 8
1042 7
1042 7
1043 6
1043 6
1044 5
1044 5
1045 4
1045 4
1046 3
1046 3
1047 2
1047 2
1048 1
1048 1
1049 0
1049 0
1050
1050
1051 ui.style works:
1051 ui.style works:
1052
1052
1053 $ echo '[ui]' > .hg/hgrc
1053 $ echo '[ui]' > .hg/hgrc
1054 $ echo 'style = t' >> .hg/hgrc
1054 $ echo 'style = t' >> .hg/hgrc
1055 $ hg log
1055 $ hg log
1056 8
1056 8
1057 7
1057 7
1058 6
1058 6
1059 5
1059 5
1060 4
1060 4
1061 3
1061 3
1062 2
1062 2
1063 1
1063 1
1064 0
1064 0
1065
1065
1066
1066
1067 Issue338:
1067 Issue338:
1068
1068
1069 $ hg log --style=changelog > changelog
1069 $ hg log --style=changelog > changelog
1070
1070
1071 $ cat changelog
1071 $ cat changelog
1072 2020-01-01 test <test>
1072 2020-01-01 test <test>
1073
1073
1074 * fourth, second, third:
1074 * fourth, second, third:
1075 third
1075 third
1076 [95c24699272e] [tip]
1076 [95c24699272e] [tip]
1077
1077
1078 1970-01-12 User Name <user@hostname>
1078 1970-01-12 User Name <user@hostname>
1079
1079
1080 * second:
1080 * second:
1081 second
1081 second
1082 [29114dbae42b]
1082 [29114dbae42b]
1083
1083
1084 1970-01-18 person <person>
1084 1970-01-18 person <person>
1085
1085
1086 * merge
1086 * merge
1087 [d41e714fe50d]
1087 [d41e714fe50d]
1088
1088
1089 * d:
1089 * d:
1090 new head
1090 new head
1091 [13207e5a10d9]
1091 [13207e5a10d9]
1092
1092
1093 1970-01-17 person <person>
1093 1970-01-17 person <person>
1094
1094
1095 * new branch
1095 * new branch
1096 [bbe44766e73d] <foo>
1096 [bbe44766e73d] <foo>
1097
1097
1098 1970-01-16 person <person>
1098 1970-01-16 person <person>
1099
1099
1100 * c:
1100 * c:
1101 no user, no domain
1101 no user, no domain
1102 [10e46f2dcbf4]
1102 [10e46f2dcbf4]
1103
1103
1104 1970-01-14 other <other@place>
1104 1970-01-14 other <other@place>
1105
1105
1106 * c:
1106 * c:
1107 no person
1107 no person
1108 [97054abb4ab8]
1108 [97054abb4ab8]
1109
1109
1110 1970-01-13 A. N. Other <other@place>
1110 1970-01-13 A. N. Other <other@place>
1111
1111
1112 * b:
1112 * b:
1113 other 1 other 2
1113 other 1 other 2
1114
1114
1115 other 3
1115 other 3
1116 [b608e9d1a3f0]
1116 [b608e9d1a3f0]
1117
1117
1118 1970-01-12 User Name <user@hostname>
1118 1970-01-12 User Name <user@hostname>
1119
1119
1120 * a:
1120 * a:
1121 line 1 line 2
1121 line 1 line 2
1122 [1e4e1b8f71e0]
1122 [1e4e1b8f71e0]
1123
1123
1124
1124
1125 Issue2130: xml output for 'hg heads' is malformed
1125 Issue2130: xml output for 'hg heads' is malformed
1126
1126
1127 $ hg heads --style changelog
1127 $ hg heads --style changelog
1128 2020-01-01 test <test>
1128 2020-01-01 test <test>
1129
1129
1130 * fourth, second, third:
1130 * fourth, second, third:
1131 third
1131 third
1132 [95c24699272e] [tip]
1132 [95c24699272e] [tip]
1133
1133
1134 1970-01-18 person <person>
1134 1970-01-18 person <person>
1135
1135
1136 * merge
1136 * merge
1137 [d41e714fe50d]
1137 [d41e714fe50d]
1138
1138
1139 1970-01-17 person <person>
1139 1970-01-17 person <person>
1140
1140
1141 * new branch
1141 * new branch
1142 [bbe44766e73d] <foo>
1142 [bbe44766e73d] <foo>
1143
1143
1144
1144
1145 Keys work:
1145 Keys work:
1146
1146
1147 $ for key in author branch branches date desc file_adds file_dels file_mods \
1147 $ for key in author branch branches date desc file_adds file_dels file_mods \
1148 > file_copies file_copies_switch files \
1148 > file_copies file_copies_switch files \
1149 > manifest node parents rev tags diffstat extras \
1149 > manifest node parents rev tags diffstat extras \
1150 > p1rev p2rev p1node p2node; do
1150 > p1rev p2rev p1node p2node; do
1151 > for mode in '' --verbose --debug; do
1151 > for mode in '' --verbose --debug; do
1152 > hg log $mode --template "$key$mode: {$key}\n"
1152 > hg log $mode --template "$key$mode: {$key}\n"
1153 > done
1153 > done
1154 > done
1154 > done
1155 author: test
1155 author: test
1156 author: User Name <user@hostname>
1156 author: User Name <user@hostname>
1157 author: person
1157 author: person
1158 author: person
1158 author: person
1159 author: person
1159 author: person
1160 author: person
1160 author: person
1161 author: other@place
1161 author: other@place
1162 author: A. N. Other <other@place>
1162 author: A. N. Other <other@place>
1163 author: User Name <user@hostname>
1163 author: User Name <user@hostname>
1164 author--verbose: test
1164 author--verbose: test
1165 author--verbose: User Name <user@hostname>
1165 author--verbose: User Name <user@hostname>
1166 author--verbose: person
1166 author--verbose: person
1167 author--verbose: person
1167 author--verbose: person
1168 author--verbose: person
1168 author--verbose: person
1169 author--verbose: person
1169 author--verbose: person
1170 author--verbose: other@place
1170 author--verbose: other@place
1171 author--verbose: A. N. Other <other@place>
1171 author--verbose: A. N. Other <other@place>
1172 author--verbose: User Name <user@hostname>
1172 author--verbose: User Name <user@hostname>
1173 author--debug: test
1173 author--debug: test
1174 author--debug: User Name <user@hostname>
1174 author--debug: User Name <user@hostname>
1175 author--debug: person
1175 author--debug: person
1176 author--debug: person
1176 author--debug: person
1177 author--debug: person
1177 author--debug: person
1178 author--debug: person
1178 author--debug: person
1179 author--debug: other@place
1179 author--debug: other@place
1180 author--debug: A. N. Other <other@place>
1180 author--debug: A. N. Other <other@place>
1181 author--debug: User Name <user@hostname>
1181 author--debug: User Name <user@hostname>
1182 branch: default
1182 branch: default
1183 branch: default
1183 branch: default
1184 branch: default
1184 branch: default
1185 branch: default
1185 branch: default
1186 branch: foo
1186 branch: foo
1187 branch: default
1187 branch: default
1188 branch: default
1188 branch: default
1189 branch: default
1189 branch: default
1190 branch: default
1190 branch: default
1191 branch--verbose: default
1191 branch--verbose: default
1192 branch--verbose: default
1192 branch--verbose: default
1193 branch--verbose: default
1193 branch--verbose: default
1194 branch--verbose: default
1194 branch--verbose: default
1195 branch--verbose: foo
1195 branch--verbose: foo
1196 branch--verbose: default
1196 branch--verbose: default
1197 branch--verbose: default
1197 branch--verbose: default
1198 branch--verbose: default
1198 branch--verbose: default
1199 branch--verbose: default
1199 branch--verbose: default
1200 branch--debug: default
1200 branch--debug: default
1201 branch--debug: default
1201 branch--debug: default
1202 branch--debug: default
1202 branch--debug: default
1203 branch--debug: default
1203 branch--debug: default
1204 branch--debug: foo
1204 branch--debug: foo
1205 branch--debug: default
1205 branch--debug: default
1206 branch--debug: default
1206 branch--debug: default
1207 branch--debug: default
1207 branch--debug: default
1208 branch--debug: default
1208 branch--debug: default
1209 branches:
1209 branches:
1210 branches:
1210 branches:
1211 branches:
1211 branches:
1212 branches:
1212 branches:
1213 branches: foo
1213 branches: foo
1214 branches:
1214 branches:
1215 branches:
1215 branches:
1216 branches:
1216 branches:
1217 branches:
1217 branches:
1218 branches--verbose:
1218 branches--verbose:
1219 branches--verbose:
1219 branches--verbose:
1220 branches--verbose:
1220 branches--verbose:
1221 branches--verbose:
1221 branches--verbose:
1222 branches--verbose: foo
1222 branches--verbose: foo
1223 branches--verbose:
1223 branches--verbose:
1224 branches--verbose:
1224 branches--verbose:
1225 branches--verbose:
1225 branches--verbose:
1226 branches--verbose:
1226 branches--verbose:
1227 branches--debug:
1227 branches--debug:
1228 branches--debug:
1228 branches--debug:
1229 branches--debug:
1229 branches--debug:
1230 branches--debug:
1230 branches--debug:
1231 branches--debug: foo
1231 branches--debug: foo
1232 branches--debug:
1232 branches--debug:
1233 branches--debug:
1233 branches--debug:
1234 branches--debug:
1234 branches--debug:
1235 branches--debug:
1235 branches--debug:
1236 date: 1577872860.00
1236 date: 1577872860.00
1237 date: 1000000.00
1237 date: 1000000.00
1238 date: 1500001.00
1238 date: 1500001.00
1239 date: 1500000.00
1239 date: 1500000.00
1240 date: 1400000.00
1240 date: 1400000.00
1241 date: 1300000.00
1241 date: 1300000.00
1242 date: 1200000.00
1242 date: 1200000.00
1243 date: 1100000.00
1243 date: 1100000.00
1244 date: 1000000.00
1244 date: 1000000.00
1245 date--verbose: 1577872860.00
1245 date--verbose: 1577872860.00
1246 date--verbose: 1000000.00
1246 date--verbose: 1000000.00
1247 date--verbose: 1500001.00
1247 date--verbose: 1500001.00
1248 date--verbose: 1500000.00
1248 date--verbose: 1500000.00
1249 date--verbose: 1400000.00
1249 date--verbose: 1400000.00
1250 date--verbose: 1300000.00
1250 date--verbose: 1300000.00
1251 date--verbose: 1200000.00
1251 date--verbose: 1200000.00
1252 date--verbose: 1100000.00
1252 date--verbose: 1100000.00
1253 date--verbose: 1000000.00
1253 date--verbose: 1000000.00
1254 date--debug: 1577872860.00
1254 date--debug: 1577872860.00
1255 date--debug: 1000000.00
1255 date--debug: 1000000.00
1256 date--debug: 1500001.00
1256 date--debug: 1500001.00
1257 date--debug: 1500000.00
1257 date--debug: 1500000.00
1258 date--debug: 1400000.00
1258 date--debug: 1400000.00
1259 date--debug: 1300000.00
1259 date--debug: 1300000.00
1260 date--debug: 1200000.00
1260 date--debug: 1200000.00
1261 date--debug: 1100000.00
1261 date--debug: 1100000.00
1262 date--debug: 1000000.00
1262 date--debug: 1000000.00
1263 desc: third
1263 desc: third
1264 desc: second
1264 desc: second
1265 desc: merge
1265 desc: merge
1266 desc: new head
1266 desc: new head
1267 desc: new branch
1267 desc: new branch
1268 desc: no user, no domain
1268 desc: no user, no domain
1269 desc: no person
1269 desc: no person
1270 desc: other 1
1270 desc: other 1
1271 other 2
1271 other 2
1272
1272
1273 other 3
1273 other 3
1274 desc: line 1
1274 desc: line 1
1275 line 2
1275 line 2
1276 desc--verbose: third
1276 desc--verbose: third
1277 desc--verbose: second
1277 desc--verbose: second
1278 desc--verbose: merge
1278 desc--verbose: merge
1279 desc--verbose: new head
1279 desc--verbose: new head
1280 desc--verbose: new branch
1280 desc--verbose: new branch
1281 desc--verbose: no user, no domain
1281 desc--verbose: no user, no domain
1282 desc--verbose: no person
1282 desc--verbose: no person
1283 desc--verbose: other 1
1283 desc--verbose: other 1
1284 other 2
1284 other 2
1285
1285
1286 other 3
1286 other 3
1287 desc--verbose: line 1
1287 desc--verbose: line 1
1288 line 2
1288 line 2
1289 desc--debug: third
1289 desc--debug: third
1290 desc--debug: second
1290 desc--debug: second
1291 desc--debug: merge
1291 desc--debug: merge
1292 desc--debug: new head
1292 desc--debug: new head
1293 desc--debug: new branch
1293 desc--debug: new branch
1294 desc--debug: no user, no domain
1294 desc--debug: no user, no domain
1295 desc--debug: no person
1295 desc--debug: no person
1296 desc--debug: other 1
1296 desc--debug: other 1
1297 other 2
1297 other 2
1298
1298
1299 other 3
1299 other 3
1300 desc--debug: line 1
1300 desc--debug: line 1
1301 line 2
1301 line 2
1302 file_adds: fourth third
1302 file_adds: fourth third
1303 file_adds: second
1303 file_adds: second
1304 file_adds:
1304 file_adds:
1305 file_adds: d
1305 file_adds: d
1306 file_adds:
1306 file_adds:
1307 file_adds:
1307 file_adds:
1308 file_adds: c
1308 file_adds: c
1309 file_adds: b
1309 file_adds: b
1310 file_adds: a
1310 file_adds: a
1311 file_adds--verbose: fourth third
1311 file_adds--verbose: fourth third
1312 file_adds--verbose: second
1312 file_adds--verbose: second
1313 file_adds--verbose:
1313 file_adds--verbose:
1314 file_adds--verbose: d
1314 file_adds--verbose: d
1315 file_adds--verbose:
1315 file_adds--verbose:
1316 file_adds--verbose:
1316 file_adds--verbose:
1317 file_adds--verbose: c
1317 file_adds--verbose: c
1318 file_adds--verbose: b
1318 file_adds--verbose: b
1319 file_adds--verbose: a
1319 file_adds--verbose: a
1320 file_adds--debug: fourth third
1320 file_adds--debug: fourth third
1321 file_adds--debug: second
1321 file_adds--debug: second
1322 file_adds--debug:
1322 file_adds--debug:
1323 file_adds--debug: d
1323 file_adds--debug: d
1324 file_adds--debug:
1324 file_adds--debug:
1325 file_adds--debug:
1325 file_adds--debug:
1326 file_adds--debug: c
1326 file_adds--debug: c
1327 file_adds--debug: b
1327 file_adds--debug: b
1328 file_adds--debug: a
1328 file_adds--debug: a
1329 file_dels: second
1329 file_dels: second
1330 file_dels:
1330 file_dels:
1331 file_dels:
1331 file_dels:
1332 file_dels:
1332 file_dels:
1333 file_dels:
1333 file_dels:
1334 file_dels:
1334 file_dels:
1335 file_dels:
1335 file_dels:
1336 file_dels:
1336 file_dels:
1337 file_dels:
1337 file_dels:
1338 file_dels--verbose: second
1338 file_dels--verbose: second
1339 file_dels--verbose:
1339 file_dels--verbose:
1340 file_dels--verbose:
1340 file_dels--verbose:
1341 file_dels--verbose:
1341 file_dels--verbose:
1342 file_dels--verbose:
1342 file_dels--verbose:
1343 file_dels--verbose:
1343 file_dels--verbose:
1344 file_dels--verbose:
1344 file_dels--verbose:
1345 file_dels--verbose:
1345 file_dels--verbose:
1346 file_dels--verbose:
1346 file_dels--verbose:
1347 file_dels--debug: second
1347 file_dels--debug: second
1348 file_dels--debug:
1348 file_dels--debug:
1349 file_dels--debug:
1349 file_dels--debug:
1350 file_dels--debug:
1350 file_dels--debug:
1351 file_dels--debug:
1351 file_dels--debug:
1352 file_dels--debug:
1352 file_dels--debug:
1353 file_dels--debug:
1353 file_dels--debug:
1354 file_dels--debug:
1354 file_dels--debug:
1355 file_dels--debug:
1355 file_dels--debug:
1356 file_mods:
1356 file_mods:
1357 file_mods:
1357 file_mods:
1358 file_mods:
1358 file_mods:
1359 file_mods:
1359 file_mods:
1360 file_mods:
1360 file_mods:
1361 file_mods: c
1361 file_mods: c
1362 file_mods:
1362 file_mods:
1363 file_mods:
1363 file_mods:
1364 file_mods:
1364 file_mods:
1365 file_mods--verbose:
1365 file_mods--verbose:
1366 file_mods--verbose:
1366 file_mods--verbose:
1367 file_mods--verbose:
1367 file_mods--verbose:
1368 file_mods--verbose:
1368 file_mods--verbose:
1369 file_mods--verbose:
1369 file_mods--verbose:
1370 file_mods--verbose: c
1370 file_mods--verbose: c
1371 file_mods--verbose:
1371 file_mods--verbose:
1372 file_mods--verbose:
1372 file_mods--verbose:
1373 file_mods--verbose:
1373 file_mods--verbose:
1374 file_mods--debug:
1374 file_mods--debug:
1375 file_mods--debug:
1375 file_mods--debug:
1376 file_mods--debug:
1376 file_mods--debug:
1377 file_mods--debug:
1377 file_mods--debug:
1378 file_mods--debug:
1378 file_mods--debug:
1379 file_mods--debug: c
1379 file_mods--debug: c
1380 file_mods--debug:
1380 file_mods--debug:
1381 file_mods--debug:
1381 file_mods--debug:
1382 file_mods--debug:
1382 file_mods--debug:
1383 file_copies: fourth (second)
1383 file_copies: fourth (second)
1384 file_copies:
1384 file_copies:
1385 file_copies:
1385 file_copies:
1386 file_copies:
1386 file_copies:
1387 file_copies:
1387 file_copies:
1388 file_copies:
1388 file_copies:
1389 file_copies:
1389 file_copies:
1390 file_copies:
1390 file_copies:
1391 file_copies:
1391 file_copies:
1392 file_copies--verbose: fourth (second)
1392 file_copies--verbose: fourth (second)
1393 file_copies--verbose:
1393 file_copies--verbose:
1394 file_copies--verbose:
1394 file_copies--verbose:
1395 file_copies--verbose:
1395 file_copies--verbose:
1396 file_copies--verbose:
1396 file_copies--verbose:
1397 file_copies--verbose:
1397 file_copies--verbose:
1398 file_copies--verbose:
1398 file_copies--verbose:
1399 file_copies--verbose:
1399 file_copies--verbose:
1400 file_copies--verbose:
1400 file_copies--verbose:
1401 file_copies--debug: fourth (second)
1401 file_copies--debug: fourth (second)
1402 file_copies--debug:
1402 file_copies--debug:
1403 file_copies--debug:
1403 file_copies--debug:
1404 file_copies--debug:
1404 file_copies--debug:
1405 file_copies--debug:
1405 file_copies--debug:
1406 file_copies--debug:
1406 file_copies--debug:
1407 file_copies--debug:
1407 file_copies--debug:
1408 file_copies--debug:
1408 file_copies--debug:
1409 file_copies--debug:
1409 file_copies--debug:
1410 file_copies_switch:
1410 file_copies_switch:
1411 file_copies_switch:
1411 file_copies_switch:
1412 file_copies_switch:
1412 file_copies_switch:
1413 file_copies_switch:
1413 file_copies_switch:
1414 file_copies_switch:
1414 file_copies_switch:
1415 file_copies_switch:
1415 file_copies_switch:
1416 file_copies_switch:
1416 file_copies_switch:
1417 file_copies_switch:
1417 file_copies_switch:
1418 file_copies_switch:
1418 file_copies_switch:
1419 file_copies_switch--verbose:
1419 file_copies_switch--verbose:
1420 file_copies_switch--verbose:
1420 file_copies_switch--verbose:
1421 file_copies_switch--verbose:
1421 file_copies_switch--verbose:
1422 file_copies_switch--verbose:
1422 file_copies_switch--verbose:
1423 file_copies_switch--verbose:
1423 file_copies_switch--verbose:
1424 file_copies_switch--verbose:
1424 file_copies_switch--verbose:
1425 file_copies_switch--verbose:
1425 file_copies_switch--verbose:
1426 file_copies_switch--verbose:
1426 file_copies_switch--verbose:
1427 file_copies_switch--verbose:
1427 file_copies_switch--verbose:
1428 file_copies_switch--debug:
1428 file_copies_switch--debug:
1429 file_copies_switch--debug:
1429 file_copies_switch--debug:
1430 file_copies_switch--debug:
1430 file_copies_switch--debug:
1431 file_copies_switch--debug:
1431 file_copies_switch--debug:
1432 file_copies_switch--debug:
1432 file_copies_switch--debug:
1433 file_copies_switch--debug:
1433 file_copies_switch--debug:
1434 file_copies_switch--debug:
1434 file_copies_switch--debug:
1435 file_copies_switch--debug:
1435 file_copies_switch--debug:
1436 file_copies_switch--debug:
1436 file_copies_switch--debug:
1437 files: fourth second third
1437 files: fourth second third
1438 files: second
1438 files: second
1439 files:
1439 files:
1440 files: d
1440 files: d
1441 files:
1441 files:
1442 files: c
1442 files: c
1443 files: c
1443 files: c
1444 files: b
1444 files: b
1445 files: a
1445 files: a
1446 files--verbose: fourth second third
1446 files--verbose: fourth second third
1447 files--verbose: second
1447 files--verbose: second
1448 files--verbose:
1448 files--verbose:
1449 files--verbose: d
1449 files--verbose: d
1450 files--verbose:
1450 files--verbose:
1451 files--verbose: c
1451 files--verbose: c
1452 files--verbose: c
1452 files--verbose: c
1453 files--verbose: b
1453 files--verbose: b
1454 files--verbose: a
1454 files--verbose: a
1455 files--debug: fourth second third
1455 files--debug: fourth second third
1456 files--debug: second
1456 files--debug: second
1457 files--debug:
1457 files--debug:
1458 files--debug: d
1458 files--debug: d
1459 files--debug:
1459 files--debug:
1460 files--debug: c
1460 files--debug: c
1461 files--debug: c
1461 files--debug: c
1462 files--debug: b
1462 files--debug: b
1463 files--debug: a
1463 files--debug: a
1464 manifest: 6:94961b75a2da
1464 manifest: 6:94961b75a2da
1465 manifest: 5:f2dbc354b94e
1465 manifest: 5:f2dbc354b94e
1466 manifest: 4:4dc3def4f9b4
1466 manifest: 4:4dc3def4f9b4
1467 manifest: 4:4dc3def4f9b4
1467 manifest: 4:4dc3def4f9b4
1468 manifest: 3:cb5a1327723b
1468 manifest: 3:cb5a1327723b
1469 manifest: 3:cb5a1327723b
1469 manifest: 3:cb5a1327723b
1470 manifest: 2:6e0e82995c35
1470 manifest: 2:6e0e82995c35
1471 manifest: 1:4e8d705b1e53
1471 manifest: 1:4e8d705b1e53
1472 manifest: 0:a0c8bcbbb45c
1472 manifest: 0:a0c8bcbbb45c
1473 manifest--verbose: 6:94961b75a2da
1473 manifest--verbose: 6:94961b75a2da
1474 manifest--verbose: 5:f2dbc354b94e
1474 manifest--verbose: 5:f2dbc354b94e
1475 manifest--verbose: 4:4dc3def4f9b4
1475 manifest--verbose: 4:4dc3def4f9b4
1476 manifest--verbose: 4:4dc3def4f9b4
1476 manifest--verbose: 4:4dc3def4f9b4
1477 manifest--verbose: 3:cb5a1327723b
1477 manifest--verbose: 3:cb5a1327723b
1478 manifest--verbose: 3:cb5a1327723b
1478 manifest--verbose: 3:cb5a1327723b
1479 manifest--verbose: 2:6e0e82995c35
1479 manifest--verbose: 2:6e0e82995c35
1480 manifest--verbose: 1:4e8d705b1e53
1480 manifest--verbose: 1:4e8d705b1e53
1481 manifest--verbose: 0:a0c8bcbbb45c
1481 manifest--verbose: 0:a0c8bcbbb45c
1482 manifest--debug: 6:94961b75a2da554b4df6fb599e5bfc7d48de0c64
1482 manifest--debug: 6:94961b75a2da554b4df6fb599e5bfc7d48de0c64
1483 manifest--debug: 5:f2dbc354b94e5ec0b4f10680ee0cee816101d0bf
1483 manifest--debug: 5:f2dbc354b94e5ec0b4f10680ee0cee816101d0bf
1484 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1484 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1485 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1485 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1486 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1486 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1487 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1487 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1488 manifest--debug: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
1488 manifest--debug: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
1489 manifest--debug: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
1489 manifest--debug: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
1490 manifest--debug: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
1490 manifest--debug: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
1491 node: 95c24699272ef57d062b8bccc32c878bf841784a
1491 node: 95c24699272ef57d062b8bccc32c878bf841784a
1492 node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1492 node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1493 node: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1493 node: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1494 node: 13207e5a10d9fd28ec424934298e176197f2c67f
1494 node: 13207e5a10d9fd28ec424934298e176197f2c67f
1495 node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1495 node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1496 node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1496 node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1497 node: 97054abb4ab824450e9164180baf491ae0078465
1497 node: 97054abb4ab824450e9164180baf491ae0078465
1498 node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1498 node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1499 node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1499 node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1500 node--verbose: 95c24699272ef57d062b8bccc32c878bf841784a
1500 node--verbose: 95c24699272ef57d062b8bccc32c878bf841784a
1501 node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1501 node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1502 node--verbose: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1502 node--verbose: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1503 node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1503 node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1504 node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1504 node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1505 node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1505 node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1506 node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1506 node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1507 node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1507 node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1508 node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1508 node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1509 node--debug: 95c24699272ef57d062b8bccc32c878bf841784a
1509 node--debug: 95c24699272ef57d062b8bccc32c878bf841784a
1510 node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1510 node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1511 node--debug: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1511 node--debug: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1512 node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1512 node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1513 node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1513 node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1514 node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1514 node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1515 node--debug: 97054abb4ab824450e9164180baf491ae0078465
1515 node--debug: 97054abb4ab824450e9164180baf491ae0078465
1516 node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1516 node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1517 node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1517 node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1518 parents:
1518 parents:
1519 parents: -1:000000000000
1519 parents: -1:000000000000
1520 parents: 5:13207e5a10d9 4:bbe44766e73d
1520 parents: 5:13207e5a10d9 4:bbe44766e73d
1521 parents: 3:10e46f2dcbf4
1521 parents: 3:10e46f2dcbf4
1522 parents:
1522 parents:
1523 parents:
1523 parents:
1524 parents:
1524 parents:
1525 parents:
1525 parents:
1526 parents:
1526 parents:
1527 parents--verbose:
1527 parents--verbose:
1528 parents--verbose: -1:000000000000
1528 parents--verbose: -1:000000000000
1529 parents--verbose: 5:13207e5a10d9 4:bbe44766e73d
1529 parents--verbose: 5:13207e5a10d9 4:bbe44766e73d
1530 parents--verbose: 3:10e46f2dcbf4
1530 parents--verbose: 3:10e46f2dcbf4
1531 parents--verbose:
1531 parents--verbose:
1532 parents--verbose:
1532 parents--verbose:
1533 parents--verbose:
1533 parents--verbose:
1534 parents--verbose:
1534 parents--verbose:
1535 parents--verbose:
1535 parents--verbose:
1536 parents--debug: 7:29114dbae42b9f078cf2714dbe3a86bba8ec7453 -1:0000000000000000000000000000000000000000
1536 parents--debug: 7:29114dbae42b9f078cf2714dbe3a86bba8ec7453 -1:0000000000000000000000000000000000000000
1537 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1537 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1538 parents--debug: 5:13207e5a10d9fd28ec424934298e176197f2c67f 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
1538 parents--debug: 5:13207e5a10d9fd28ec424934298e176197f2c67f 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
1539 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1539 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1540 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1540 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1541 parents--debug: 2:97054abb4ab824450e9164180baf491ae0078465 -1:0000000000000000000000000000000000000000
1541 parents--debug: 2:97054abb4ab824450e9164180baf491ae0078465 -1:0000000000000000000000000000000000000000
1542 parents--debug: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965 -1:0000000000000000000000000000000000000000
1542 parents--debug: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965 -1:0000000000000000000000000000000000000000
1543 parents--debug: 0:1e4e1b8f71e05681d422154f5421e385fec3454f -1:0000000000000000000000000000000000000000
1543 parents--debug: 0:1e4e1b8f71e05681d422154f5421e385fec3454f -1:0000000000000000000000000000000000000000
1544 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1544 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1545 rev: 8
1545 rev: 8
1546 rev: 7
1546 rev: 7
1547 rev: 6
1547 rev: 6
1548 rev: 5
1548 rev: 5
1549 rev: 4
1549 rev: 4
1550 rev: 3
1550 rev: 3
1551 rev: 2
1551 rev: 2
1552 rev: 1
1552 rev: 1
1553 rev: 0
1553 rev: 0
1554 rev--verbose: 8
1554 rev--verbose: 8
1555 rev--verbose: 7
1555 rev--verbose: 7
1556 rev--verbose: 6
1556 rev--verbose: 6
1557 rev--verbose: 5
1557 rev--verbose: 5
1558 rev--verbose: 4
1558 rev--verbose: 4
1559 rev--verbose: 3
1559 rev--verbose: 3
1560 rev--verbose: 2
1560 rev--verbose: 2
1561 rev--verbose: 1
1561 rev--verbose: 1
1562 rev--verbose: 0
1562 rev--verbose: 0
1563 rev--debug: 8
1563 rev--debug: 8
1564 rev--debug: 7
1564 rev--debug: 7
1565 rev--debug: 6
1565 rev--debug: 6
1566 rev--debug: 5
1566 rev--debug: 5
1567 rev--debug: 4
1567 rev--debug: 4
1568 rev--debug: 3
1568 rev--debug: 3
1569 rev--debug: 2
1569 rev--debug: 2
1570 rev--debug: 1
1570 rev--debug: 1
1571 rev--debug: 0
1571 rev--debug: 0
1572 tags: tip
1572 tags: tip
1573 tags:
1573 tags:
1574 tags:
1574 tags:
1575 tags:
1575 tags:
1576 tags:
1576 tags:
1577 tags:
1577 tags:
1578 tags:
1578 tags:
1579 tags:
1579 tags:
1580 tags:
1580 tags:
1581 tags--verbose: tip
1581 tags--verbose: tip
1582 tags--verbose:
1582 tags--verbose:
1583 tags--verbose:
1583 tags--verbose:
1584 tags--verbose:
1584 tags--verbose:
1585 tags--verbose:
1585 tags--verbose:
1586 tags--verbose:
1586 tags--verbose:
1587 tags--verbose:
1587 tags--verbose:
1588 tags--verbose:
1588 tags--verbose:
1589 tags--verbose:
1589 tags--verbose:
1590 tags--debug: tip
1590 tags--debug: tip
1591 tags--debug:
1591 tags--debug:
1592 tags--debug:
1592 tags--debug:
1593 tags--debug:
1593 tags--debug:
1594 tags--debug:
1594 tags--debug:
1595 tags--debug:
1595 tags--debug:
1596 tags--debug:
1596 tags--debug:
1597 tags--debug:
1597 tags--debug:
1598 tags--debug:
1598 tags--debug:
1599 diffstat: 3: +2/-1
1599 diffstat: 3: +2/-1
1600 diffstat: 1: +1/-0
1600 diffstat: 1: +1/-0
1601 diffstat: 0: +0/-0
1601 diffstat: 0: +0/-0
1602 diffstat: 1: +1/-0
1602 diffstat: 1: +1/-0
1603 diffstat: 0: +0/-0
1603 diffstat: 0: +0/-0
1604 diffstat: 1: +1/-0
1604 diffstat: 1: +1/-0
1605 diffstat: 1: +4/-0
1605 diffstat: 1: +4/-0
1606 diffstat: 1: +2/-0
1606 diffstat: 1: +2/-0
1607 diffstat: 1: +1/-0
1607 diffstat: 1: +1/-0
1608 diffstat--verbose: 3: +2/-1
1608 diffstat--verbose: 3: +2/-1
1609 diffstat--verbose: 1: +1/-0
1609 diffstat--verbose: 1: +1/-0
1610 diffstat--verbose: 0: +0/-0
1610 diffstat--verbose: 0: +0/-0
1611 diffstat--verbose: 1: +1/-0
1611 diffstat--verbose: 1: +1/-0
1612 diffstat--verbose: 0: +0/-0
1612 diffstat--verbose: 0: +0/-0
1613 diffstat--verbose: 1: +1/-0
1613 diffstat--verbose: 1: +1/-0
1614 diffstat--verbose: 1: +4/-0
1614 diffstat--verbose: 1: +4/-0
1615 diffstat--verbose: 1: +2/-0
1615 diffstat--verbose: 1: +2/-0
1616 diffstat--verbose: 1: +1/-0
1616 diffstat--verbose: 1: +1/-0
1617 diffstat--debug: 3: +2/-1
1617 diffstat--debug: 3: +2/-1
1618 diffstat--debug: 1: +1/-0
1618 diffstat--debug: 1: +1/-0
1619 diffstat--debug: 0: +0/-0
1619 diffstat--debug: 0: +0/-0
1620 diffstat--debug: 1: +1/-0
1620 diffstat--debug: 1: +1/-0
1621 diffstat--debug: 0: +0/-0
1621 diffstat--debug: 0: +0/-0
1622 diffstat--debug: 1: +1/-0
1622 diffstat--debug: 1: +1/-0
1623 diffstat--debug: 1: +4/-0
1623 diffstat--debug: 1: +4/-0
1624 diffstat--debug: 1: +2/-0
1624 diffstat--debug: 1: +2/-0
1625 diffstat--debug: 1: +1/-0
1625 diffstat--debug: 1: +1/-0
1626 extras: branch=default
1626 extras: branch=default
1627 extras: branch=default
1627 extras: branch=default
1628 extras: branch=default
1628 extras: branch=default
1629 extras: branch=default
1629 extras: branch=default
1630 extras: branch=foo
1630 extras: branch=foo
1631 extras: branch=default
1631 extras: branch=default
1632 extras: branch=default
1632 extras: branch=default
1633 extras: branch=default
1633 extras: branch=default
1634 extras: branch=default
1634 extras: branch=default
1635 extras--verbose: branch=default
1635 extras--verbose: branch=default
1636 extras--verbose: branch=default
1636 extras--verbose: branch=default
1637 extras--verbose: branch=default
1637 extras--verbose: branch=default
1638 extras--verbose: branch=default
1638 extras--verbose: branch=default
1639 extras--verbose: branch=foo
1639 extras--verbose: branch=foo
1640 extras--verbose: branch=default
1640 extras--verbose: branch=default
1641 extras--verbose: branch=default
1641 extras--verbose: branch=default
1642 extras--verbose: branch=default
1642 extras--verbose: branch=default
1643 extras--verbose: branch=default
1643 extras--verbose: branch=default
1644 extras--debug: branch=default
1644 extras--debug: branch=default
1645 extras--debug: branch=default
1645 extras--debug: branch=default
1646 extras--debug: branch=default
1646 extras--debug: branch=default
1647 extras--debug: branch=default
1647 extras--debug: branch=default
1648 extras--debug: branch=foo
1648 extras--debug: branch=foo
1649 extras--debug: branch=default
1649 extras--debug: branch=default
1650 extras--debug: branch=default
1650 extras--debug: branch=default
1651 extras--debug: branch=default
1651 extras--debug: branch=default
1652 extras--debug: branch=default
1652 extras--debug: branch=default
1653 p1rev: 7
1653 p1rev: 7
1654 p1rev: -1
1654 p1rev: -1
1655 p1rev: 5
1655 p1rev: 5
1656 p1rev: 3
1656 p1rev: 3
1657 p1rev: 3
1657 p1rev: 3
1658 p1rev: 2
1658 p1rev: 2
1659 p1rev: 1
1659 p1rev: 1
1660 p1rev: 0
1660 p1rev: 0
1661 p1rev: -1
1661 p1rev: -1
1662 p1rev--verbose: 7
1662 p1rev--verbose: 7
1663 p1rev--verbose: -1
1663 p1rev--verbose: -1
1664 p1rev--verbose: 5
1664 p1rev--verbose: 5
1665 p1rev--verbose: 3
1665 p1rev--verbose: 3
1666 p1rev--verbose: 3
1666 p1rev--verbose: 3
1667 p1rev--verbose: 2
1667 p1rev--verbose: 2
1668 p1rev--verbose: 1
1668 p1rev--verbose: 1
1669 p1rev--verbose: 0
1669 p1rev--verbose: 0
1670 p1rev--verbose: -1
1670 p1rev--verbose: -1
1671 p1rev--debug: 7
1671 p1rev--debug: 7
1672 p1rev--debug: -1
1672 p1rev--debug: -1
1673 p1rev--debug: 5
1673 p1rev--debug: 5
1674 p1rev--debug: 3
1674 p1rev--debug: 3
1675 p1rev--debug: 3
1675 p1rev--debug: 3
1676 p1rev--debug: 2
1676 p1rev--debug: 2
1677 p1rev--debug: 1
1677 p1rev--debug: 1
1678 p1rev--debug: 0
1678 p1rev--debug: 0
1679 p1rev--debug: -1
1679 p1rev--debug: -1
1680 p2rev: -1
1680 p2rev: -1
1681 p2rev: -1
1681 p2rev: -1
1682 p2rev: 4
1682 p2rev: 4
1683 p2rev: -1
1683 p2rev: -1
1684 p2rev: -1
1684 p2rev: -1
1685 p2rev: -1
1685 p2rev: -1
1686 p2rev: -1
1686 p2rev: -1
1687 p2rev: -1
1687 p2rev: -1
1688 p2rev: -1
1688 p2rev: -1
1689 p2rev--verbose: -1
1689 p2rev--verbose: -1
1690 p2rev--verbose: -1
1690 p2rev--verbose: -1
1691 p2rev--verbose: 4
1691 p2rev--verbose: 4
1692 p2rev--verbose: -1
1692 p2rev--verbose: -1
1693 p2rev--verbose: -1
1693 p2rev--verbose: -1
1694 p2rev--verbose: -1
1694 p2rev--verbose: -1
1695 p2rev--verbose: -1
1695 p2rev--verbose: -1
1696 p2rev--verbose: -1
1696 p2rev--verbose: -1
1697 p2rev--verbose: -1
1697 p2rev--verbose: -1
1698 p2rev--debug: -1
1698 p2rev--debug: -1
1699 p2rev--debug: -1
1699 p2rev--debug: -1
1700 p2rev--debug: 4
1700 p2rev--debug: 4
1701 p2rev--debug: -1
1701 p2rev--debug: -1
1702 p2rev--debug: -1
1702 p2rev--debug: -1
1703 p2rev--debug: -1
1703 p2rev--debug: -1
1704 p2rev--debug: -1
1704 p2rev--debug: -1
1705 p2rev--debug: -1
1705 p2rev--debug: -1
1706 p2rev--debug: -1
1706 p2rev--debug: -1
1707 p1node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1707 p1node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1708 p1node: 0000000000000000000000000000000000000000
1708 p1node: 0000000000000000000000000000000000000000
1709 p1node: 13207e5a10d9fd28ec424934298e176197f2c67f
1709 p1node: 13207e5a10d9fd28ec424934298e176197f2c67f
1710 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1710 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1711 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1711 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1712 p1node: 97054abb4ab824450e9164180baf491ae0078465
1712 p1node: 97054abb4ab824450e9164180baf491ae0078465
1713 p1node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1713 p1node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1714 p1node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1714 p1node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1715 p1node: 0000000000000000000000000000000000000000
1715 p1node: 0000000000000000000000000000000000000000
1716 p1node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1716 p1node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1717 p1node--verbose: 0000000000000000000000000000000000000000
1717 p1node--verbose: 0000000000000000000000000000000000000000
1718 p1node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1718 p1node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1719 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1719 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1720 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1720 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1721 p1node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1721 p1node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1722 p1node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1722 p1node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1723 p1node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1723 p1node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1724 p1node--verbose: 0000000000000000000000000000000000000000
1724 p1node--verbose: 0000000000000000000000000000000000000000
1725 p1node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1725 p1node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1726 p1node--debug: 0000000000000000000000000000000000000000
1726 p1node--debug: 0000000000000000000000000000000000000000
1727 p1node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1727 p1node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1728 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1728 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1729 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1729 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1730 p1node--debug: 97054abb4ab824450e9164180baf491ae0078465
1730 p1node--debug: 97054abb4ab824450e9164180baf491ae0078465
1731 p1node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1731 p1node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1732 p1node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1732 p1node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1733 p1node--debug: 0000000000000000000000000000000000000000
1733 p1node--debug: 0000000000000000000000000000000000000000
1734 p2node: 0000000000000000000000000000000000000000
1734 p2node: 0000000000000000000000000000000000000000
1735 p2node: 0000000000000000000000000000000000000000
1735 p2node: 0000000000000000000000000000000000000000
1736 p2node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1736 p2node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1737 p2node: 0000000000000000000000000000000000000000
1737 p2node: 0000000000000000000000000000000000000000
1738 p2node: 0000000000000000000000000000000000000000
1738 p2node: 0000000000000000000000000000000000000000
1739 p2node: 0000000000000000000000000000000000000000
1739 p2node: 0000000000000000000000000000000000000000
1740 p2node: 0000000000000000000000000000000000000000
1740 p2node: 0000000000000000000000000000000000000000
1741 p2node: 0000000000000000000000000000000000000000
1741 p2node: 0000000000000000000000000000000000000000
1742 p2node: 0000000000000000000000000000000000000000
1742 p2node: 0000000000000000000000000000000000000000
1743 p2node--verbose: 0000000000000000000000000000000000000000
1743 p2node--verbose: 0000000000000000000000000000000000000000
1744 p2node--verbose: 0000000000000000000000000000000000000000
1744 p2node--verbose: 0000000000000000000000000000000000000000
1745 p2node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1745 p2node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1746 p2node--verbose: 0000000000000000000000000000000000000000
1746 p2node--verbose: 0000000000000000000000000000000000000000
1747 p2node--verbose: 0000000000000000000000000000000000000000
1747 p2node--verbose: 0000000000000000000000000000000000000000
1748 p2node--verbose: 0000000000000000000000000000000000000000
1748 p2node--verbose: 0000000000000000000000000000000000000000
1749 p2node--verbose: 0000000000000000000000000000000000000000
1749 p2node--verbose: 0000000000000000000000000000000000000000
1750 p2node--verbose: 0000000000000000000000000000000000000000
1750 p2node--verbose: 0000000000000000000000000000000000000000
1751 p2node--verbose: 0000000000000000000000000000000000000000
1751 p2node--verbose: 0000000000000000000000000000000000000000
1752 p2node--debug: 0000000000000000000000000000000000000000
1752 p2node--debug: 0000000000000000000000000000000000000000
1753 p2node--debug: 0000000000000000000000000000000000000000
1753 p2node--debug: 0000000000000000000000000000000000000000
1754 p2node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1754 p2node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1755 p2node--debug: 0000000000000000000000000000000000000000
1755 p2node--debug: 0000000000000000000000000000000000000000
1756 p2node--debug: 0000000000000000000000000000000000000000
1756 p2node--debug: 0000000000000000000000000000000000000000
1757 p2node--debug: 0000000000000000000000000000000000000000
1757 p2node--debug: 0000000000000000000000000000000000000000
1758 p2node--debug: 0000000000000000000000000000000000000000
1758 p2node--debug: 0000000000000000000000000000000000000000
1759 p2node--debug: 0000000000000000000000000000000000000000
1759 p2node--debug: 0000000000000000000000000000000000000000
1760 p2node--debug: 0000000000000000000000000000000000000000
1760 p2node--debug: 0000000000000000000000000000000000000000
1761
1761
1762 Filters work:
1762 Filters work:
1763
1763
1764 $ hg log --template '{author|domain}\n'
1764 $ hg log --template '{author|domain}\n'
1765
1765
1766 hostname
1766 hostname
1767
1767
1768
1768
1769
1769
1770
1770
1771 place
1771 place
1772 place
1772 place
1773 hostname
1773 hostname
1774
1774
1775 $ hg log --template '{author|person}\n'
1775 $ hg log --template '{author|person}\n'
1776 test
1776 test
1777 User Name
1777 User Name
1778 person
1778 person
1779 person
1779 person
1780 person
1780 person
1781 person
1781 person
1782 other
1782 other
1783 A. N. Other
1783 A. N. Other
1784 User Name
1784 User Name
1785
1785
1786 $ hg log --template '{author|user}\n'
1786 $ hg log --template '{author|user}\n'
1787 test
1787 test
1788 user
1788 user
1789 person
1789 person
1790 person
1790 person
1791 person
1791 person
1792 person
1792 person
1793 other
1793 other
1794 other
1794 other
1795 user
1795 user
1796
1796
1797 $ hg log --template '{date|date}\n'
1797 $ hg log --template '{date|date}\n'
1798 Wed Jan 01 10:01:00 2020 +0000
1798 Wed Jan 01 10:01:00 2020 +0000
1799 Mon Jan 12 13:46:40 1970 +0000
1799 Mon Jan 12 13:46:40 1970 +0000
1800 Sun Jan 18 08:40:01 1970 +0000
1800 Sun Jan 18 08:40:01 1970 +0000
1801 Sun Jan 18 08:40:00 1970 +0000
1801 Sun Jan 18 08:40:00 1970 +0000
1802 Sat Jan 17 04:53:20 1970 +0000
1802 Sat Jan 17 04:53:20 1970 +0000
1803 Fri Jan 16 01:06:40 1970 +0000
1803 Fri Jan 16 01:06:40 1970 +0000
1804 Wed Jan 14 21:20:00 1970 +0000
1804 Wed Jan 14 21:20:00 1970 +0000
1805 Tue Jan 13 17:33:20 1970 +0000
1805 Tue Jan 13 17:33:20 1970 +0000
1806 Mon Jan 12 13:46:40 1970 +0000
1806 Mon Jan 12 13:46:40 1970 +0000
1807
1807
1808 $ hg log --template '{date|isodate}\n'
1808 $ hg log --template '{date|isodate}\n'
1809 2020-01-01 10:01 +0000
1809 2020-01-01 10:01 +0000
1810 1970-01-12 13:46 +0000
1810 1970-01-12 13:46 +0000
1811 1970-01-18 08:40 +0000
1811 1970-01-18 08:40 +0000
1812 1970-01-18 08:40 +0000
1812 1970-01-18 08:40 +0000
1813 1970-01-17 04:53 +0000
1813 1970-01-17 04:53 +0000
1814 1970-01-16 01:06 +0000
1814 1970-01-16 01:06 +0000
1815 1970-01-14 21:20 +0000
1815 1970-01-14 21:20 +0000
1816 1970-01-13 17:33 +0000
1816 1970-01-13 17:33 +0000
1817 1970-01-12 13:46 +0000
1817 1970-01-12 13:46 +0000
1818
1818
1819 $ hg log --template '{date|isodatesec}\n'
1819 $ hg log --template '{date|isodatesec}\n'
1820 2020-01-01 10:01:00 +0000
1820 2020-01-01 10:01:00 +0000
1821 1970-01-12 13:46:40 +0000
1821 1970-01-12 13:46:40 +0000
1822 1970-01-18 08:40:01 +0000
1822 1970-01-18 08:40:01 +0000
1823 1970-01-18 08:40:00 +0000
1823 1970-01-18 08:40:00 +0000
1824 1970-01-17 04:53:20 +0000
1824 1970-01-17 04:53:20 +0000
1825 1970-01-16 01:06:40 +0000
1825 1970-01-16 01:06:40 +0000
1826 1970-01-14 21:20:00 +0000
1826 1970-01-14 21:20:00 +0000
1827 1970-01-13 17:33:20 +0000
1827 1970-01-13 17:33:20 +0000
1828 1970-01-12 13:46:40 +0000
1828 1970-01-12 13:46:40 +0000
1829
1829
1830 $ hg log --template '{date|rfc822date}\n'
1830 $ hg log --template '{date|rfc822date}\n'
1831 Wed, 01 Jan 2020 10:01:00 +0000
1831 Wed, 01 Jan 2020 10:01:00 +0000
1832 Mon, 12 Jan 1970 13:46:40 +0000
1832 Mon, 12 Jan 1970 13:46:40 +0000
1833 Sun, 18 Jan 1970 08:40:01 +0000
1833 Sun, 18 Jan 1970 08:40:01 +0000
1834 Sun, 18 Jan 1970 08:40:00 +0000
1834 Sun, 18 Jan 1970 08:40:00 +0000
1835 Sat, 17 Jan 1970 04:53:20 +0000
1835 Sat, 17 Jan 1970 04:53:20 +0000
1836 Fri, 16 Jan 1970 01:06:40 +0000
1836 Fri, 16 Jan 1970 01:06:40 +0000
1837 Wed, 14 Jan 1970 21:20:00 +0000
1837 Wed, 14 Jan 1970 21:20:00 +0000
1838 Tue, 13 Jan 1970 17:33:20 +0000
1838 Tue, 13 Jan 1970 17:33:20 +0000
1839 Mon, 12 Jan 1970 13:46:40 +0000
1839 Mon, 12 Jan 1970 13:46:40 +0000
1840
1840
1841 $ hg log --template '{desc|firstline}\n'
1841 $ hg log --template '{desc|firstline}\n'
1842 third
1842 third
1843 second
1843 second
1844 merge
1844 merge
1845 new head
1845 new head
1846 new branch
1846 new branch
1847 no user, no domain
1847 no user, no domain
1848 no person
1848 no person
1849 other 1
1849 other 1
1850 line 1
1850 line 1
1851
1851
1852 $ hg log --template '{node|short}\n'
1852 $ hg log --template '{node|short}\n'
1853 95c24699272e
1853 95c24699272e
1854 29114dbae42b
1854 29114dbae42b
1855 d41e714fe50d
1855 d41e714fe50d
1856 13207e5a10d9
1856 13207e5a10d9
1857 bbe44766e73d
1857 bbe44766e73d
1858 10e46f2dcbf4
1858 10e46f2dcbf4
1859 97054abb4ab8
1859 97054abb4ab8
1860 b608e9d1a3f0
1860 b608e9d1a3f0
1861 1e4e1b8f71e0
1861 1e4e1b8f71e0
1862
1862
1863 $ hg log --template '<changeset author="{author|xmlescape}"/>\n'
1863 $ hg log --template '<changeset author="{author|xmlescape}"/>\n'
1864 <changeset author="test"/>
1864 <changeset author="test"/>
1865 <changeset author="User Name &lt;user@hostname&gt;"/>
1865 <changeset author="User Name &lt;user@hostname&gt;"/>
1866 <changeset author="person"/>
1866 <changeset author="person"/>
1867 <changeset author="person"/>
1867 <changeset author="person"/>
1868 <changeset author="person"/>
1868 <changeset author="person"/>
1869 <changeset author="person"/>
1869 <changeset author="person"/>
1870 <changeset author="other@place"/>
1870 <changeset author="other@place"/>
1871 <changeset author="A. N. Other &lt;other@place&gt;"/>
1871 <changeset author="A. N. Other &lt;other@place&gt;"/>
1872 <changeset author="User Name &lt;user@hostname&gt;"/>
1872 <changeset author="User Name &lt;user@hostname&gt;"/>
1873
1873
1874 $ hg log --template '{rev}: {children}\n'
1874 $ hg log --template '{rev}: {children}\n'
1875 8:
1875 8:
1876 7: 8:95c24699272e
1876 7: 8:95c24699272e
1877 6:
1877 6:
1878 5: 6:d41e714fe50d
1878 5: 6:d41e714fe50d
1879 4: 6:d41e714fe50d
1879 4: 6:d41e714fe50d
1880 3: 4:bbe44766e73d 5:13207e5a10d9
1880 3: 4:bbe44766e73d 5:13207e5a10d9
1881 2: 3:10e46f2dcbf4
1881 2: 3:10e46f2dcbf4
1882 1: 2:97054abb4ab8
1882 1: 2:97054abb4ab8
1883 0: 1:b608e9d1a3f0
1883 0: 1:b608e9d1a3f0
1884
1884
1885 Formatnode filter works:
1885 Formatnode filter works:
1886
1886
1887 $ hg -q log -r 0 --template '{node|formatnode}\n'
1887 $ hg -q log -r 0 --template '{node|formatnode}\n'
1888 1e4e1b8f71e0
1888 1e4e1b8f71e0
1889
1889
1890 $ hg log -r 0 --template '{node|formatnode}\n'
1890 $ hg log -r 0 --template '{node|formatnode}\n'
1891 1e4e1b8f71e0
1891 1e4e1b8f71e0
1892
1892
1893 $ hg -v log -r 0 --template '{node|formatnode}\n'
1893 $ hg -v log -r 0 --template '{node|formatnode}\n'
1894 1e4e1b8f71e0
1894 1e4e1b8f71e0
1895
1895
1896 $ hg --debug log -r 0 --template '{node|formatnode}\n'
1896 $ hg --debug log -r 0 --template '{node|formatnode}\n'
1897 1e4e1b8f71e05681d422154f5421e385fec3454f
1897 1e4e1b8f71e05681d422154f5421e385fec3454f
1898
1898
1899 Age filter:
1899 Age filter:
1900
1900
1901 $ hg log --template '{date|age}\n' > /dev/null || exit 1
1901 $ hg log --template '{date|age}\n' > /dev/null || exit 1
1902
1902
1903 >>> from datetime import datetime, timedelta
1903 >>> from datetime import datetime, timedelta
1904 >>> fp = open('a', 'w')
1904 >>> fp = open('a', 'w')
1905 >>> n = datetime.now() + timedelta(366 * 7)
1905 >>> n = datetime.now() + timedelta(366 * 7)
1906 >>> fp.write('%d-%d-%d 00:00' % (n.year, n.month, n.day))
1906 >>> fp.write('%d-%d-%d 00:00' % (n.year, n.month, n.day))
1907 >>> fp.close()
1907 >>> fp.close()
1908 $ hg add a
1908 $ hg add a
1909 $ hg commit -m future -d "`cat a`"
1909 $ hg commit -m future -d "`cat a`"
1910
1910
1911 $ hg log -l1 --template '{date|age}\n'
1911 $ hg log -l1 --template '{date|age}\n'
1912 7 years from now
1912 7 years from now
1913
1913
1914 Count filter:
1914 Count filter:
1915
1915
1916 $ hg log -l1 --template '{node|count} {node|short|count}\n'
1916 $ hg log -l1 --template '{node|count} {node|short|count}\n'
1917 40 12
1917 40 12
1918
1918
1919 $ hg log -l1 --template '{revset("null^")|count} {revset(".")|count} {revset("0::3")|count}\n'
1919 $ hg log -l1 --template '{revset("null^")|count} {revset(".")|count} {revset("0::3")|count}\n'
1920 0 1 4
1920 0 1 4
1921
1921
1922 $ hg log -G --template '{rev}: children: {children|count}, \
1922 $ hg log -G --template '{rev}: children: {children|count}, \
1923 > tags: {tags|count}, file_adds: {file_adds|count}, \
1923 > tags: {tags|count}, file_adds: {file_adds|count}, \
1924 > ancestors: {revset("ancestors(%s)", rev)|count}'
1924 > ancestors: {revset("ancestors(%s)", rev)|count}'
1925 @ 9: children: 0, tags: 1, file_adds: 1, ancestors: 3
1925 @ 9: children: 0, tags: 1, file_adds: 1, ancestors: 3
1926 |
1926 |
1927 o 8: children: 1, tags: 0, file_adds: 2, ancestors: 2
1927 o 8: children: 1, tags: 0, file_adds: 2, ancestors: 2
1928 |
1928 |
1929 o 7: children: 1, tags: 0, file_adds: 1, ancestors: 1
1929 o 7: children: 1, tags: 0, file_adds: 1, ancestors: 1
1930
1930
1931 o 6: children: 0, tags: 0, file_adds: 0, ancestors: 7
1931 o 6: children: 0, tags: 0, file_adds: 0, ancestors: 7
1932 |\
1932 |\
1933 | o 5: children: 1, tags: 0, file_adds: 1, ancestors: 5
1933 | o 5: children: 1, tags: 0, file_adds: 1, ancestors: 5
1934 | |
1934 | |
1935 o | 4: children: 1, tags: 0, file_adds: 0, ancestors: 5
1935 o | 4: children: 1, tags: 0, file_adds: 0, ancestors: 5
1936 |/
1936 |/
1937 o 3: children: 2, tags: 0, file_adds: 0, ancestors: 4
1937 o 3: children: 2, tags: 0, file_adds: 0, ancestors: 4
1938 |
1938 |
1939 o 2: children: 1, tags: 0, file_adds: 1, ancestors: 3
1939 o 2: children: 1, tags: 0, file_adds: 1, ancestors: 3
1940 |
1940 |
1941 o 1: children: 1, tags: 0, file_adds: 1, ancestors: 2
1941 o 1: children: 1, tags: 0, file_adds: 1, ancestors: 2
1942 |
1942 |
1943 o 0: children: 1, tags: 0, file_adds: 1, ancestors: 1
1943 o 0: children: 1, tags: 0, file_adds: 1, ancestors: 1
1944
1944
1945
1945
1946 Upper/lower filters:
1946 Upper/lower filters:
1947
1947
1948 $ hg log -r0 --template '{branch|upper}\n'
1948 $ hg log -r0 --template '{branch|upper}\n'
1949 DEFAULT
1949 DEFAULT
1950 $ hg log -r0 --template '{author|lower}\n'
1950 $ hg log -r0 --template '{author|lower}\n'
1951 user name <user@hostname>
1951 user name <user@hostname>
1952 $ hg log -r0 --template '{date|upper}\n'
1952 $ hg log -r0 --template '{date|upper}\n'
1953 abort: template filter 'upper' is not compatible with keyword 'date'
1953 abort: template filter 'upper' is not compatible with keyword 'date'
1954 [255]
1954 [255]
1955
1955
1956 Error on syntax:
1956 Error on syntax:
1957
1957
1958 $ echo 'x = "f' >> t
1958 $ echo 'x = "f' >> t
1959 $ hg log
1959 $ hg log
1960 abort: t:3: unmatched quotes
1960 abort: t:3: unmatched quotes
1961 [255]
1961 [255]
1962
1962
1963 Behind the scenes, this will throw TypeError
1963 Behind the scenes, this will throw TypeError
1964
1964
1965 $ hg log -l 3 --template '{date|obfuscate}\n'
1965 $ hg log -l 3 --template '{date|obfuscate}\n'
1966 abort: template filter 'obfuscate' is not compatible with keyword 'date'
1966 abort: template filter 'obfuscate' is not compatible with keyword 'date'
1967 [255]
1967 [255]
1968
1968
1969 Behind the scenes, this will throw a ValueError
1969 Behind the scenes, this will throw a ValueError
1970
1970
1971 $ hg log -l 3 --template 'line: {desc|shortdate}\n'
1971 $ hg log -l 3 --template 'line: {desc|shortdate}\n'
1972 abort: template filter 'shortdate' is not compatible with keyword 'desc'
1972 abort: template filter 'shortdate' is not compatible with keyword 'desc'
1973 [255]
1973 [255]
1974
1974
1975 Behind the scenes, this will throw AttributeError
1975 Behind the scenes, this will throw AttributeError
1976
1976
1977 $ hg log -l 3 --template 'line: {date|escape}\n'
1977 $ hg log -l 3 --template 'line: {date|escape}\n'
1978 abort: template filter 'escape' is not compatible with keyword 'date'
1978 abort: template filter 'escape' is not compatible with keyword 'date'
1979 [255]
1979 [255]
1980
1980
1981 Behind the scenes, this will throw ValueError
1981 Behind the scenes, this will throw ValueError
1982
1982
1983 $ hg tip --template '{author|email|date}\n'
1983 $ hg tip --template '{author|email|date}\n'
1984 abort: template filter 'datefilter' is not compatible with keyword 'author'
1984 abort: template filter 'datefilter' is not compatible with keyword 'author'
1985 [255]
1985 [255]
1986
1986
1987 Thrown an error if a template function doesn't exist
1987 Thrown an error if a template function doesn't exist
1988
1988
1989 $ hg tip --template '{foo()}\n'
1989 $ hg tip --template '{foo()}\n'
1990 hg: parse error: unknown function 'foo'
1990 hg: parse error: unknown function 'foo'
1991 [255]
1991 [255]
1992
1992
1993 Pass generator object created by template function to filter
1993 Pass generator object created by template function to filter
1994
1994
1995 $ hg log -l 1 --template '{if(author, author)|user}\n'
1995 $ hg log -l 1 --template '{if(author, author)|user}\n'
1996 test
1996 test
1997
1997
1998 Test diff function:
1998 Test diff function:
1999
1999
2000 $ hg diff -c 8
2000 $ hg diff -c 8
2001 diff -r 29114dbae42b -r 95c24699272e fourth
2001 diff -r 29114dbae42b -r 95c24699272e fourth
2002 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2002 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2003 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2003 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2004 @@ -0,0 +1,1 @@
2004 @@ -0,0 +1,1 @@
2005 +second
2005 +second
2006 diff -r 29114dbae42b -r 95c24699272e second
2006 diff -r 29114dbae42b -r 95c24699272e second
2007 --- a/second Mon Jan 12 13:46:40 1970 +0000
2007 --- a/second Mon Jan 12 13:46:40 1970 +0000
2008 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2008 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2009 @@ -1,1 +0,0 @@
2009 @@ -1,1 +0,0 @@
2010 -second
2010 -second
2011 diff -r 29114dbae42b -r 95c24699272e third
2011 diff -r 29114dbae42b -r 95c24699272e third
2012 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2012 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2013 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2013 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2014 @@ -0,0 +1,1 @@
2014 @@ -0,0 +1,1 @@
2015 +third
2015 +third
2016
2016
2017 $ hg log -r 8 -T "{diff()}"
2017 $ hg log -r 8 -T "{diff()}"
2018 diff -r 29114dbae42b -r 95c24699272e fourth
2018 diff -r 29114dbae42b -r 95c24699272e fourth
2019 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2019 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2020 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2020 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2021 @@ -0,0 +1,1 @@
2021 @@ -0,0 +1,1 @@
2022 +second
2022 +second
2023 diff -r 29114dbae42b -r 95c24699272e second
2023 diff -r 29114dbae42b -r 95c24699272e second
2024 --- a/second Mon Jan 12 13:46:40 1970 +0000
2024 --- a/second Mon Jan 12 13:46:40 1970 +0000
2025 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2025 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2026 @@ -1,1 +0,0 @@
2026 @@ -1,1 +0,0 @@
2027 -second
2027 -second
2028 diff -r 29114dbae42b -r 95c24699272e third
2028 diff -r 29114dbae42b -r 95c24699272e third
2029 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2029 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2030 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2030 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2031 @@ -0,0 +1,1 @@
2031 @@ -0,0 +1,1 @@
2032 +third
2032 +third
2033
2033
2034 $ hg log -r 8 -T "{diff('glob:f*')}"
2034 $ hg log -r 8 -T "{diff('glob:f*')}"
2035 diff -r 29114dbae42b -r 95c24699272e fourth
2035 diff -r 29114dbae42b -r 95c24699272e fourth
2036 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2036 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2037 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2037 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2038 @@ -0,0 +1,1 @@
2038 @@ -0,0 +1,1 @@
2039 +second
2039 +second
2040
2040
2041 $ hg log -r 8 -T "{diff('', 'glob:f*')}"
2041 $ hg log -r 8 -T "{diff('', 'glob:f*')}"
2042 diff -r 29114dbae42b -r 95c24699272e second
2042 diff -r 29114dbae42b -r 95c24699272e second
2043 --- a/second Mon Jan 12 13:46:40 1970 +0000
2043 --- a/second Mon Jan 12 13:46:40 1970 +0000
2044 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2044 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2045 @@ -1,1 +0,0 @@
2045 @@ -1,1 +0,0 @@
2046 -second
2046 -second
2047 diff -r 29114dbae42b -r 95c24699272e third
2047 diff -r 29114dbae42b -r 95c24699272e third
2048 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2048 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2049 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2049 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2050 @@ -0,0 +1,1 @@
2050 @@ -0,0 +1,1 @@
2051 +third
2051 +third
2052
2052
2053 $ cd ..
2053 $ cd ..
2054
2054
2055
2055
2056 latesttag:
2056 latesttag:
2057
2057
2058 $ hg init latesttag
2058 $ hg init latesttag
2059 $ cd latesttag
2059 $ cd latesttag
2060
2060
2061 $ echo a > file
2061 $ echo a > file
2062 $ hg ci -Am a -d '0 0'
2062 $ hg ci -Am a -d '0 0'
2063 adding file
2063 adding file
2064
2064
2065 $ echo b >> file
2065 $ echo b >> file
2066 $ hg ci -m b -d '1 0'
2066 $ hg ci -m b -d '1 0'
2067
2067
2068 $ echo c >> head1
2068 $ echo c >> head1
2069 $ hg ci -Am h1c -d '2 0'
2069 $ hg ci -Am h1c -d '2 0'
2070 adding head1
2070 adding head1
2071
2071
2072 $ hg update -q 1
2072 $ hg update -q 1
2073 $ echo d >> head2
2073 $ echo d >> head2
2074 $ hg ci -Am h2d -d '3 0'
2074 $ hg ci -Am h2d -d '3 0'
2075 adding head2
2075 adding head2
2076 created new head
2076 created new head
2077
2077
2078 $ echo e >> head2
2078 $ echo e >> head2
2079 $ hg ci -m h2e -d '4 0'
2079 $ hg ci -m h2e -d '4 0'
2080
2080
2081 $ hg merge -q
2081 $ hg merge -q
2082 $ hg ci -m merge -d '5 -3600'
2082 $ hg ci -m merge -d '5 -3600'
2083
2083
2084 No tag set:
2084 No tag set:
2085
2085
2086 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2086 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2087 5: null+5
2087 5: null+5
2088 4: null+4
2088 4: null+4
2089 3: null+3
2089 3: null+3
2090 2: null+3
2090 2: null+3
2091 1: null+2
2091 1: null+2
2092 0: null+1
2092 0: null+1
2093
2093
2094 One common tag: longest path wins:
2094 One common tag: longest path wins:
2095
2095
2096 $ hg tag -r 1 -m t1 -d '6 0' t1
2096 $ hg tag -r 1 -m t1 -d '6 0' t1
2097 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2097 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2098 6: t1+4
2098 6: t1+4
2099 5: t1+3
2099 5: t1+3
2100 4: t1+2
2100 4: t1+2
2101 3: t1+1
2101 3: t1+1
2102 2: t1+1
2102 2: t1+1
2103 1: t1+0
2103 1: t1+0
2104 0: null+1
2104 0: null+1
2105
2105
2106 One ancestor tag: more recent wins:
2106 One ancestor tag: more recent wins:
2107
2107
2108 $ hg tag -r 2 -m t2 -d '7 0' t2
2108 $ hg tag -r 2 -m t2 -d '7 0' t2
2109 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2109 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2110 7: t2+3
2110 7: t2+3
2111 6: t2+2
2111 6: t2+2
2112 5: t2+1
2112 5: t2+1
2113 4: t1+2
2113 4: t1+2
2114 3: t1+1
2114 3: t1+1
2115 2: t2+0
2115 2: t2+0
2116 1: t1+0
2116 1: t1+0
2117 0: null+1
2117 0: null+1
2118
2118
2119 Two branch tags: more recent wins:
2119 Two branch tags: more recent wins:
2120
2120
2121 $ hg tag -r 3 -m t3 -d '8 0' t3
2121 $ hg tag -r 3 -m t3 -d '8 0' t3
2122 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2122 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2123 8: t3+5
2123 8: t3+5
2124 7: t3+4
2124 7: t3+4
2125 6: t3+3
2125 6: t3+3
2126 5: t3+2
2126 5: t3+2
2127 4: t3+1
2127 4: t3+1
2128 3: t3+0
2128 3: t3+0
2129 2: t2+0
2129 2: t2+0
2130 1: t1+0
2130 1: t1+0
2131 0: null+1
2131 0: null+1
2132
2132
2133 Merged tag overrides:
2133 Merged tag overrides:
2134
2134
2135 $ hg tag -r 5 -m t5 -d '9 0' t5
2135 $ hg tag -r 5 -m t5 -d '9 0' t5
2136 $ hg tag -r 3 -m at3 -d '10 0' at3
2136 $ hg tag -r 3 -m at3 -d '10 0' at3
2137 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2137 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
2138 10: t5+5
2138 10: t5+5
2139 9: t5+4
2139 9: t5+4
2140 8: t5+3
2140 8: t5+3
2141 7: t5+2
2141 7: t5+2
2142 6: t5+1
2142 6: t5+1
2143 5: t5+0
2143 5: t5+0
2144 4: at3:t3+1
2144 4: at3:t3+1
2145 3: at3:t3+0
2145 3: at3:t3+0
2146 2: t2+0
2146 2: t2+0
2147 1: t1+0
2147 1: t1+0
2148 0: null+1
2148 0: null+1
2149
2149
2150 $ cd ..
2150 $ cd ..
2151
2151
2152
2152
2153 Style path expansion: issue1948 - ui.style option doesn't work on OSX
2153 Style path expansion: issue1948 - ui.style option doesn't work on OSX
2154 if it is a relative path
2154 if it is a relative path
2155
2155
2156 $ mkdir -p home/styles
2156 $ mkdir -p home/styles
2157
2157
2158 $ cat > home/styles/teststyle <<EOF
2158 $ cat > home/styles/teststyle <<EOF
2159 > changeset = 'test {rev}:{node|short}\n'
2159 > changeset = 'test {rev}:{node|short}\n'
2160 > EOF
2160 > EOF
2161
2161
2162 $ HOME=`pwd`/home; export HOME
2162 $ HOME=`pwd`/home; export HOME
2163
2163
2164 $ cat > latesttag/.hg/hgrc <<EOF
2164 $ cat > latesttag/.hg/hgrc <<EOF
2165 > [ui]
2165 > [ui]
2166 > style = ~/styles/teststyle
2166 > style = ~/styles/teststyle
2167 > EOF
2167 > EOF
2168
2168
2169 $ hg -R latesttag tip
2169 $ hg -R latesttag tip
2170 test 10:9b4a630e5f5f
2170 test 10:9b4a630e5f5f
2171
2171
2172 Test recursive showlist template (issue1989):
2172 Test recursive showlist template (issue1989):
2173
2173
2174 $ cat > style1989 <<EOF
2174 $ cat > style1989 <<EOF
2175 > changeset = '{file_mods}{manifest}{extras}'
2175 > changeset = '{file_mods}{manifest}{extras}'
2176 > file_mod = 'M|{author|person}\n'
2176 > file_mod = 'M|{author|person}\n'
2177 > manifest = '{rev},{author}\n'
2177 > manifest = '{rev},{author}\n'
2178 > extra = '{key}: {author}\n'
2178 > extra = '{key}: {author}\n'
2179 > EOF
2179 > EOF
2180
2180
2181 $ hg -R latesttag log -r tip --style=style1989
2181 $ hg -R latesttag log -r tip --style=style1989
2182 M|test
2182 M|test
2183 10,test
2183 10,test
2184 branch: test
2184 branch: test
2185
2185
2186 Test new-style inline templating:
2186 Test new-style inline templating:
2187
2187
2188 $ hg log -R latesttag -r tip --template 'modified files: {file_mods % " {file}\n"}\n'
2188 $ hg log -R latesttag -r tip --template 'modified files: {file_mods % " {file}\n"}\n'
2189 modified files: .hgtags
2189 modified files: .hgtags
2190
2190
2191 Test the sub function of templating for expansion:
2191 Test the sub function of templating for expansion:
2192
2192
2193 $ hg log -R latesttag -r 10 --template '{sub("[0-9]", "x", "{rev}")}\n'
2193 $ hg log -R latesttag -r 10 --template '{sub("[0-9]", "x", "{rev}")}\n'
2194 xx
2194 xx
2195
2195
2196 Test the strip function with chars specified:
2196 Test the strip function with chars specified:
2197
2197
2198 $ hg log -R latesttag --template '{desc}\n'
2198 $ hg log -R latesttag --template '{desc}\n'
2199 at3
2199 at3
2200 t5
2200 t5
2201 t3
2201 t3
2202 t2
2202 t2
2203 t1
2203 t1
2204 merge
2204 merge
2205 h2e
2205 h2e
2206 h2d
2206 h2d
2207 h1c
2207 h1c
2208 b
2208 b
2209 a
2209 a
2210
2210
2211 $ hg log -R latesttag --template '{strip(desc, "te")}\n'
2211 $ hg log -R latesttag --template '{strip(desc, "te")}\n'
2212 at3
2212 at3
2213 5
2213 5
2214 3
2214 3
2215 2
2215 2
2216 1
2216 1
2217 merg
2217 merg
2218 h2
2218 h2
2219 h2d
2219 h2d
2220 h1c
2220 h1c
2221 b
2221 b
2222 a
2222 a
2223
2223
2224 Test date format:
2224 Test date format:
2225
2225
2226 $ hg log -R latesttag --template 'date: {date(date, "%y %m %d %S %z")}\n'
2226 $ hg log -R latesttag --template 'date: {date(date, "%y %m %d %S %z")}\n'
2227 date: 70 01 01 10 +0000
2227 date: 70 01 01 10 +0000
2228 date: 70 01 01 09 +0000
2228 date: 70 01 01 09 +0000
2229 date: 70 01 01 08 +0000
2229 date: 70 01 01 08 +0000
2230 date: 70 01 01 07 +0000
2230 date: 70 01 01 07 +0000
2231 date: 70 01 01 06 +0000
2231 date: 70 01 01 06 +0000
2232 date: 70 01 01 05 +0100
2232 date: 70 01 01 05 +0100
2233 date: 70 01 01 04 +0000
2233 date: 70 01 01 04 +0000
2234 date: 70 01 01 03 +0000
2234 date: 70 01 01 03 +0000
2235 date: 70 01 01 02 +0000
2235 date: 70 01 01 02 +0000
2236 date: 70 01 01 01 +0000
2236 date: 70 01 01 01 +0000
2237 date: 70 01 01 00 +0000
2237 date: 70 01 01 00 +0000
2238
2238
2239 Test invalid date:
2239 Test invalid date:
2240
2240
2241 $ hg log -R latesttag -T '{date(rev)}\n'
2241 $ hg log -R latesttag -T '{date(rev)}\n'
2242 hg: parse error: date expects a date information
2242 hg: parse error: date expects a date information
2243 [255]
2243 [255]
2244
2244
2245 Test string escaping:
2245 Test string escaping:
2246
2246
2247 $ hg log -R latesttag -r 0 --template '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2247 $ hg log -R latesttag -r 0 --template '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2248 >
2248 >
2249 <>\n<[>
2249 <>\n<[>
2250 <>\n<]>
2250 <>\n<]>
2251 <>\n<
2251 <>\n<
2252
2252
2253 $ hg log -R latesttag -r 0 \
2253 $ hg log -R latesttag -r 0 \
2254 > --config ui.logtemplate='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2254 > --config ui.logtemplate='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2255 >
2255 >
2256 <>\n<[>
2256 <>\n<[>
2257 <>\n<]>
2257 <>\n<]>
2258 <>\n<
2258 <>\n<
2259
2259
2260 $ hg log -R latesttag -r 0 -T esc \
2260 $ hg log -R latesttag -r 0 -T esc \
2261 > --config templates.esc='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2261 > --config templates.esc='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2262 >
2262 >
2263 <>\n<[>
2263 <>\n<[>
2264 <>\n<]>
2264 <>\n<]>
2265 <>\n<
2265 <>\n<
2266
2266
2267 $ cat <<'EOF' > esctmpl
2267 $ cat <<'EOF' > esctmpl
2268 > changeset = '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2268 > changeset = '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2269 > EOF
2269 > EOF
2270 $ hg log -R latesttag -r 0 --style ./esctmpl
2270 $ hg log -R latesttag -r 0 --style ./esctmpl
2271 >
2271 >
2272 <>\n<[>
2272 <>\n<[>
2273 <>\n<]>
2273 <>\n<]>
2274 <>\n<
2274 <>\n<
2275
2275
2276 Test leading backslashes:
2276 Test leading backslashes:
2277
2277
2278 $ cd latesttag
2278 $ cd latesttag
2279 $ hg log -r 2 -T '\{rev} {files % "\{file}"} {files % r"\{file}"}\n'
2279 $ hg log -r 2 -T '\{rev} {files % "\{file}"} {files % r"\{file}"}\n'
2280 {rev} {file} \head1
2280 {rev} {file} \head1
2281 $ hg log -r 2 -T '\\{rev} {files % "\\{file}"} {files % r"\\{file}"}\n'
2281 $ hg log -r 2 -T '\\{rev} {files % "\\{file}"} {files % r"\\{file}"}\n'
2282 \2 \head1 \\head1
2282 \2 \head1 \\head1
2283 $ hg log -r 2 -T '\\\{rev} {files % "\\\{file}"} {files % r"\\\{file}"}\n'
2283 $ hg log -r 2 -T '\\\{rev} {files % "\\\{file}"} {files % r"\\\{file}"}\n'
2284 \{rev} \{file} \\\head1
2284 \{rev} \{file} \\\head1
2285 $ cd ..
2285 $ cd ..
2286
2286
2287 Test leading backslashes in "if" expression (issue4714):
2288
2289 $ cd latesttag
2290 $ hg log -r 2 -T '{if("1", "\{rev}")} {if("1", r"\{rev}")}\n'
2291 {rev} \2
2292 $ hg log -r 2 -T '{if("1", "\\{rev}")} {if("1", r"\\{rev}")}\n'
2293 \2 \\2
2294 $ hg log -r 2 -T '{if("1", "\\\{rev}")} {if("1", r"\\\{rev}")}\n'
2295 \{rev} \\\2
2296 $ cd ..
2297
2287 "string-escape"-ed "\x5c\x786e" becomes r"\x6e" (once) or r"n" (twice)
2298 "string-escape"-ed "\x5c\x786e" becomes r"\x6e" (once) or r"n" (twice)
2288
2299
2289 $ hg log -R a -r 0 --template '{if("1", "\x5c\x786e", "NG")}\n'
2300 $ hg log -R a -r 0 --template '{if("1", "\x5c\x786e", "NG")}\n'
2290 \x6e
2301 \x6e
2291 $ hg log -R a -r 0 --template '{if("1", r"\x5c\x786e", "NG")}\n'
2302 $ hg log -R a -r 0 --template '{if("1", r"\x5c\x786e", "NG")}\n'
2292 \x5c\x786e
2303 \x5c\x786e
2293 $ hg log -R a -r 0 --template '{if("", "NG", "\x5c\x786e")}\n'
2304 $ hg log -R a -r 0 --template '{if("", "NG", "\x5c\x786e")}\n'
2294 \x6e
2305 \x6e
2295 $ hg log -R a -r 0 --template '{if("", "NG", r"\x5c\x786e")}\n'
2306 $ hg log -R a -r 0 --template '{if("", "NG", r"\x5c\x786e")}\n'
2296 \x5c\x786e
2307 \x5c\x786e
2297
2308
2298 $ hg log -R a -r 2 --template '{ifeq("no perso\x6e", desc, "\x5c\x786e", "NG")}\n'
2309 $ hg log -R a -r 2 --template '{ifeq("no perso\x6e", desc, "\x5c\x786e", "NG")}\n'
2299 \x6e
2310 \x6e
2300 $ hg log -R a -r 2 --template '{ifeq(r"no perso\x6e", desc, "NG", r"\x5c\x786e")}\n'
2311 $ hg log -R a -r 2 --template '{ifeq(r"no perso\x6e", desc, "NG", r"\x5c\x786e")}\n'
2301 \x5c\x786e
2312 \x5c\x786e
2302 $ hg log -R a -r 2 --template '{ifeq(desc, "no perso\x6e", "\x5c\x786e", "NG")}\n'
2313 $ hg log -R a -r 2 --template '{ifeq(desc, "no perso\x6e", "\x5c\x786e", "NG")}\n'
2303 \x6e
2314 \x6e
2304 $ hg log -R a -r 2 --template '{ifeq(desc, r"no perso\x6e", "NG", r"\x5c\x786e")}\n'
2315 $ hg log -R a -r 2 --template '{ifeq(desc, r"no perso\x6e", "NG", r"\x5c\x786e")}\n'
2305 \x5c\x786e
2316 \x5c\x786e
2306
2317
2307 $ hg log -R a -r 8 --template '{join(files, "\n")}\n'
2318 $ hg log -R a -r 8 --template '{join(files, "\n")}\n'
2308 fourth
2319 fourth
2309 second
2320 second
2310 third
2321 third
2311 $ hg log -R a -r 8 --template '{join(files, r"\n")}\n'
2322 $ hg log -R a -r 8 --template '{join(files, r"\n")}\n'
2312 fourth\nsecond\nthird
2323 fourth\nsecond\nthird
2313
2324
2314 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", "htm\x6c")}'
2325 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", "htm\x6c")}'
2315 <p>
2326 <p>
2316 1st
2327 1st
2317 </p>
2328 </p>
2318 <p>
2329 <p>
2319 2nd
2330 2nd
2320 </p>
2331 </p>
2321 $ hg log -R a -r 2 --template '{rstdoc(r"1st\n\n2nd", "html")}'
2332 $ hg log -R a -r 2 --template '{rstdoc(r"1st\n\n2nd", "html")}'
2322 <p>
2333 <p>
2323 1st\n\n2nd
2334 1st\n\n2nd
2324 </p>
2335 </p>
2325 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", r"htm\x6c")}'
2336 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", r"htm\x6c")}'
2326 1st
2337 1st
2327
2338
2328 2nd
2339 2nd
2329
2340
2330 $ hg log -R a -r 2 --template '{strip(desc, "\x6e")}\n'
2341 $ hg log -R a -r 2 --template '{strip(desc, "\x6e")}\n'
2331 o perso
2342 o perso
2332 $ hg log -R a -r 2 --template '{strip(desc, r"\x6e")}\n'
2343 $ hg log -R a -r 2 --template '{strip(desc, r"\x6e")}\n'
2333 no person
2344 no person
2334 $ hg log -R a -r 2 --template '{strip("no perso\x6e", "\x6e")}\n'
2345 $ hg log -R a -r 2 --template '{strip("no perso\x6e", "\x6e")}\n'
2335 o perso
2346 o perso
2336 $ hg log -R a -r 2 --template '{strip(r"no perso\x6e", r"\x6e")}\n'
2347 $ hg log -R a -r 2 --template '{strip(r"no perso\x6e", r"\x6e")}\n'
2337 no perso
2348 no perso
2338
2349
2339 $ hg log -R a -r 2 --template '{sub("\\x6e", "\x2d", desc)}\n'
2350 $ hg log -R a -r 2 --template '{sub("\\x6e", "\x2d", desc)}\n'
2340 -o perso-
2351 -o perso-
2341 $ hg log -R a -r 2 --template '{sub(r"\\x6e", "-", desc)}\n'
2352 $ hg log -R a -r 2 --template '{sub(r"\\x6e", "-", desc)}\n'
2342 no person
2353 no person
2343 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", desc)}\n'
2354 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", desc)}\n'
2344 \x2do perso\x2d
2355 \x2do perso\x2d
2345 $ hg log -R a -r 2 --template '{sub("n", "\x2d", "no perso\x6e")}\n'
2356 $ hg log -R a -r 2 --template '{sub("n", "\x2d", "no perso\x6e")}\n'
2346 -o perso-
2357 -o perso-
2347 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", r"no perso\x6e")}\n'
2358 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", r"no perso\x6e")}\n'
2348 \x2do perso\x6e
2359 \x2do perso\x6e
2349
2360
2350 $ hg log -R a -r 8 --template '{files % "{file}\n"}'
2361 $ hg log -R a -r 8 --template '{files % "{file}\n"}'
2351 fourth
2362 fourth
2352 second
2363 second
2353 third
2364 third
2354 $ hg log -R a -r 8 --template '{files % r"{file}\n"}\n'
2365 $ hg log -R a -r 8 --template '{files % r"{file}\n"}\n'
2355 fourth\nsecond\nthird\n
2366 fourth\nsecond\nthird\n
2356
2367
2357 Test string escaping in nested expression:
2368 Test string escaping in nested expression:
2358
2369
2359 $ hg log -R a -r 8 --template '{ifeq(r"\x6e", if("1", "\x5c\x786e"), join(files, "\x5c\x786e"))}\n'
2370 $ hg log -R a -r 8 --template '{ifeq(r"\x6e", if("1", "\x5c\x786e"), join(files, "\x5c\x786e"))}\n'
2360 fourth\x6esecond\x6ethird
2371 fourth\x6esecond\x6ethird
2361 $ hg log -R a -r 8 --template '{ifeq(if("1", r"\x6e"), "\x5c\x786e", join(files, "\x5c\x786e"))}\n'
2372 $ hg log -R a -r 8 --template '{ifeq(if("1", r"\x6e"), "\x5c\x786e", join(files, "\x5c\x786e"))}\n'
2362 fourth\x6esecond\x6ethird
2373 fourth\x6esecond\x6ethird
2363
2374
2364 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", "\x5c\x786e"))}\n'
2375 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", "\x5c\x786e"))}\n'
2365 fourth\x6esecond\x6ethird
2376 fourth\x6esecond\x6ethird
2366 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", r"\x5c\x786e"))}\n'
2377 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", r"\x5c\x786e"))}\n'
2367 fourth\x5c\x786esecond\x5c\x786ethird
2378 fourth\x5c\x786esecond\x5c\x786ethird
2368
2379
2369 $ hg log -R a -r 3:4 --template '{rev}:{sub(if("1", "\x6e"), ifeq(branch, "foo", r"\x5c\x786e", "\x5c\x786e"), desc)}\n'
2380 $ hg log -R a -r 3:4 --template '{rev}:{sub(if("1", "\x6e"), ifeq(branch, "foo", r"\x5c\x786e", "\x5c\x786e"), desc)}\n'
2370 3:\x6eo user, \x6eo domai\x6e
2381 3:\x6eo user, \x6eo domai\x6e
2371 4:\x5c\x786eew bra\x5c\x786ech
2382 4:\x5c\x786eew bra\x5c\x786ech
2372
2383
2373 Test recursive evaluation:
2384 Test recursive evaluation:
2374
2385
2375 $ hg init r
2386 $ hg init r
2376 $ cd r
2387 $ cd r
2377 $ echo a > a
2388 $ echo a > a
2378 $ hg ci -Am '{rev}'
2389 $ hg ci -Am '{rev}'
2379 adding a
2390 adding a
2380 $ hg log -r 0 --template '{if(rev, desc)}\n'
2391 $ hg log -r 0 --template '{if(rev, desc)}\n'
2381 {rev}
2392 {rev}
2382 $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n'
2393 $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n'
2383 test 0
2394 test 0
2384
2395
2385 $ hg branch -q 'text.{rev}'
2396 $ hg branch -q 'text.{rev}'
2386 $ echo aa >> aa
2397 $ echo aa >> aa
2387 $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
2398 $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
2388
2399
2389 $ hg log -l1 --template '{fill(desc, "20", author, branch)}'
2400 $ hg log -l1 --template '{fill(desc, "20", author, branch)}'
2390 {node|short}desc to
2401 {node|short}desc to
2391 text.{rev}be wrapped
2402 text.{rev}be wrapped
2392 text.{rev}desc to be
2403 text.{rev}desc to be
2393 text.{rev}wrapped (no-eol)
2404 text.{rev}wrapped (no-eol)
2394 $ hg log -l1 --template '{fill(desc, "20", "{node|short}:", "text.{rev}:")}'
2405 $ hg log -l1 --template '{fill(desc, "20", "{node|short}:", "text.{rev}:")}'
2395 bcc7ff960b8e:desc to
2406 bcc7ff960b8e:desc to
2396 text.1:be wrapped
2407 text.1:be wrapped
2397 text.1:desc to be
2408 text.1:desc to be
2398 text.1:wrapped (no-eol)
2409 text.1:wrapped (no-eol)
2399
2410
2400 $ hg log -l 1 --template '{sub(r"[0-9]", "-", author)}'
2411 $ hg log -l 1 --template '{sub(r"[0-9]", "-", author)}'
2401 {node|short} (no-eol)
2412 {node|short} (no-eol)
2402 $ hg log -l 1 --template '{sub(r"[0-9]", "-", "{node|short}")}'
2413 $ hg log -l 1 --template '{sub(r"[0-9]", "-", "{node|short}")}'
2403 bcc-ff---b-e (no-eol)
2414 bcc-ff---b-e (no-eol)
2404
2415
2405 $ cat >> .hg/hgrc <<EOF
2416 $ cat >> .hg/hgrc <<EOF
2406 > [extensions]
2417 > [extensions]
2407 > color=
2418 > color=
2408 > [color]
2419 > [color]
2409 > mode=ansi
2420 > mode=ansi
2410 > text.{rev} = red
2421 > text.{rev} = red
2411 > text.1 = green
2422 > text.1 = green
2412 > EOF
2423 > EOF
2413 $ hg log --color=always -l 1 --template '{label(branch, "text\n")}'
2424 $ hg log --color=always -l 1 --template '{label(branch, "text\n")}'
2414 \x1b[0;31mtext\x1b[0m (esc)
2425 \x1b[0;31mtext\x1b[0m (esc)
2415 $ hg log --color=always -l 1 --template '{label("text.{rev}", "text\n")}'
2426 $ hg log --color=always -l 1 --template '{label("text.{rev}", "text\n")}'
2416 \x1b[0;32mtext\x1b[0m (esc)
2427 \x1b[0;32mtext\x1b[0m (esc)
2417
2428
2418 Test branches inside if statement:
2429 Test branches inside if statement:
2419
2430
2420 $ hg log -r 0 --template '{if(branches, "yes", "no")}\n'
2431 $ hg log -r 0 --template '{if(branches, "yes", "no")}\n'
2421 no
2432 no
2422
2433
2423 Test get function:
2434 Test get function:
2424
2435
2425 $ hg log -r 0 --template '{get(extras, "branch")}\n'
2436 $ hg log -r 0 --template '{get(extras, "branch")}\n'
2426 default
2437 default
2427 $ hg log -r 0 --template '{get(files, "should_fail")}\n'
2438 $ hg log -r 0 --template '{get(files, "should_fail")}\n'
2428 hg: parse error: get() expects a dict as first argument
2439 hg: parse error: get() expects a dict as first argument
2429 [255]
2440 [255]
2430
2441
2431 Test shortest(node) function:
2442 Test shortest(node) function:
2432
2443
2433 $ echo b > b
2444 $ echo b > b
2434 $ hg ci -qAm b
2445 $ hg ci -qAm b
2435 $ hg log --template '{shortest(node)}\n'
2446 $ hg log --template '{shortest(node)}\n'
2436 e777
2447 e777
2437 bcc7
2448 bcc7
2438 f776
2449 f776
2439 $ hg log --template '{shortest(node, 10)}\n'
2450 $ hg log --template '{shortest(node, 10)}\n'
2440 e777603221
2451 e777603221
2441 bcc7ff960b
2452 bcc7ff960b
2442 f7769ec2ab
2453 f7769ec2ab
2443
2454
2444 Test pad function
2455 Test pad function
2445
2456
2446 $ hg log --template '{pad(rev, 20)} {author|user}\n'
2457 $ hg log --template '{pad(rev, 20)} {author|user}\n'
2447 2 test
2458 2 test
2448 1 {node|short}
2459 1 {node|short}
2449 0 test
2460 0 test
2450
2461
2451 $ hg log --template '{pad(rev, 20, " ", True)} {author|user}\n'
2462 $ hg log --template '{pad(rev, 20, " ", True)} {author|user}\n'
2452 2 test
2463 2 test
2453 1 {node|short}
2464 1 {node|short}
2454 0 test
2465 0 test
2455
2466
2456 $ hg log --template '{pad(rev, 20, "-", False)} {author|user}\n'
2467 $ hg log --template '{pad(rev, 20, "-", False)} {author|user}\n'
2457 2------------------- test
2468 2------------------- test
2458 1------------------- {node|short}
2469 1------------------- {node|short}
2459 0------------------- test
2470 0------------------- test
2460
2471
2461 Test ifcontains function
2472 Test ifcontains function
2462
2473
2463 $ hg log --template '{rev} {ifcontains(rev, "2 two 0", "is in the string", "is not")}\n'
2474 $ hg log --template '{rev} {ifcontains(rev, "2 two 0", "is in the string", "is not")}\n'
2464 2 is in the string
2475 2 is in the string
2465 1 is not
2476 1 is not
2466 0 is in the string
2477 0 is in the string
2467
2478
2468 $ hg log --template '{rev} {ifcontains("a", file_adds, "added a", "did not add a")}\n'
2479 $ hg log --template '{rev} {ifcontains("a", file_adds, "added a", "did not add a")}\n'
2469 2 did not add a
2480 2 did not add a
2470 1 did not add a
2481 1 did not add a
2471 0 added a
2482 0 added a
2472
2483
2473 Test revset function
2484 Test revset function
2474
2485
2475 $ hg log --template '{rev} {ifcontains(rev, revset("."), "current rev", "not current rev")}\n'
2486 $ hg log --template '{rev} {ifcontains(rev, revset("."), "current rev", "not current rev")}\n'
2476 2 current rev
2487 2 current rev
2477 1 not current rev
2488 1 not current rev
2478 0 not current rev
2489 0 not current rev
2479
2490
2480 $ hg log --template '{rev} {ifcontains(rev, revset(". + .^"), "match rev", "not match rev")}\n'
2491 $ hg log --template '{rev} {ifcontains(rev, revset(". + .^"), "match rev", "not match rev")}\n'
2481 2 match rev
2492 2 match rev
2482 1 match rev
2493 1 match rev
2483 0 not match rev
2494 0 not match rev
2484
2495
2485 $ hg log --template '{rev} Parents: {revset("parents(%s)", rev)}\n'
2496 $ hg log --template '{rev} Parents: {revset("parents(%s)", rev)}\n'
2486 2 Parents: 1
2497 2 Parents: 1
2487 1 Parents: 0
2498 1 Parents: 0
2488 0 Parents:
2499 0 Parents:
2489
2500
2490 $ cat >> .hg/hgrc <<EOF
2501 $ cat >> .hg/hgrc <<EOF
2491 > [revsetalias]
2502 > [revsetalias]
2492 > myparents(\$1) = parents(\$1)
2503 > myparents(\$1) = parents(\$1)
2493 > EOF
2504 > EOF
2494 $ hg log --template '{rev} Parents: {revset("myparents(%s)", rev)}\n'
2505 $ hg log --template '{rev} Parents: {revset("myparents(%s)", rev)}\n'
2495 2 Parents: 1
2506 2 Parents: 1
2496 1 Parents: 0
2507 1 Parents: 0
2497 0 Parents:
2508 0 Parents:
2498
2509
2499 $ hg log --template 'Rev: {rev}\n{revset("::%s", rev) % "Ancestor: {revision}\n"}\n'
2510 $ hg log --template 'Rev: {rev}\n{revset("::%s", rev) % "Ancestor: {revision}\n"}\n'
2500 Rev: 2
2511 Rev: 2
2501 Ancestor: 0
2512 Ancestor: 0
2502 Ancestor: 1
2513 Ancestor: 1
2503 Ancestor: 2
2514 Ancestor: 2
2504
2515
2505 Rev: 1
2516 Rev: 1
2506 Ancestor: 0
2517 Ancestor: 0
2507 Ancestor: 1
2518 Ancestor: 1
2508
2519
2509 Rev: 0
2520 Rev: 0
2510 Ancestor: 0
2521 Ancestor: 0
2511
2522
2512 Test current bookmark templating
2523 Test current bookmark templating
2513
2524
2514 $ hg book foo
2525 $ hg book foo
2515 $ hg book bar
2526 $ hg book bar
2516 $ hg log --template "{rev} {bookmarks % '{bookmark}{ifeq(bookmark, current, \"*\")} '}\n"
2527 $ hg log --template "{rev} {bookmarks % '{bookmark}{ifeq(bookmark, current, \"*\")} '}\n"
2517 2 bar* foo
2528 2 bar* foo
2518 1
2529 1
2519 0
2530 0
2520 $ hg log --template "{rev} {currentbookmark}\n"
2531 $ hg log --template "{rev} {currentbookmark}\n"
2521 2 bar
2532 2 bar
2522 1
2533 1
2523 0
2534 0
2524 $ hg bookmarks --inactive bar
2535 $ hg bookmarks --inactive bar
2525 $ hg log --template "{rev} {currentbookmark}\n"
2536 $ hg log --template "{rev} {currentbookmark}\n"
2526 2
2537 2
2527 1
2538 1
2528 0
2539 0
2529 $ hg book -r1 baz
2540 $ hg book -r1 baz
2530 $ hg log --template "{rev} {join(bookmarks, ' ')}\n"
2541 $ hg log --template "{rev} {join(bookmarks, ' ')}\n"
2531 2 bar foo
2542 2 bar foo
2532 1 baz
2543 1 baz
2533 0
2544 0
2534 $ hg log --template "{rev} {ifcontains('foo', bookmarks, 't', 'f')}\n"
2545 $ hg log --template "{rev} {ifcontains('foo', bookmarks, 't', 'f')}\n"
2535 2 t
2546 2 t
2536 1 f
2547 1 f
2537 0 f
2548 0 f
2538
2549
2539 Test stringify on sub expressions
2550 Test stringify on sub expressions
2540
2551
2541 $ cd ..
2552 $ cd ..
2542 $ hg log -R a -r 8 --template '{join(files, if("1", if("1", ", ")))}\n'
2553 $ hg log -R a -r 8 --template '{join(files, if("1", if("1", ", ")))}\n'
2543 fourth, second, third
2554 fourth, second, third
2544 $ hg log -R a -r 8 --template '{strip(if("1", if("1", "-abc-")), if("1", if("1", "-")))}\n'
2555 $ hg log -R a -r 8 --template '{strip(if("1", if("1", "-abc-")), if("1", if("1", "-")))}\n'
2545 abc
2556 abc
2546
2557
2547 Test splitlines
2558 Test splitlines
2548
2559
2549 $ hg log -Gv -R a --template "{splitlines(desc) % 'foo {line}\n'}"
2560 $ hg log -Gv -R a --template "{splitlines(desc) % 'foo {line}\n'}"
2550 @ foo future
2561 @ foo future
2551 |
2562 |
2552 o foo third
2563 o foo third
2553 |
2564 |
2554 o foo second
2565 o foo second
2555
2566
2556 o foo merge
2567 o foo merge
2557 |\
2568 |\
2558 | o foo new head
2569 | o foo new head
2559 | |
2570 | |
2560 o | foo new branch
2571 o | foo new branch
2561 |/
2572 |/
2562 o foo no user, no domain
2573 o foo no user, no domain
2563 |
2574 |
2564 o foo no person
2575 o foo no person
2565 |
2576 |
2566 o foo other 1
2577 o foo other 1
2567 | foo other 2
2578 | foo other 2
2568 | foo
2579 | foo
2569 | foo other 3
2580 | foo other 3
2570 o foo line 1
2581 o foo line 1
2571 foo line 2
2582 foo line 2
2572
2583
2573 Test startswith
2584 Test startswith
2574 $ hg log -Gv -R a --template "{startswith(desc)}"
2585 $ hg log -Gv -R a --template "{startswith(desc)}"
2575 hg: parse error: startswith expects two arguments
2586 hg: parse error: startswith expects two arguments
2576 [255]
2587 [255]
2577
2588
2578 $ hg log -Gv -R a --template "{startswith('line', desc)}"
2589 $ hg log -Gv -R a --template "{startswith('line', desc)}"
2579 @
2590 @
2580 |
2591 |
2581 o
2592 o
2582 |
2593 |
2583 o
2594 o
2584
2595
2585 o
2596 o
2586 |\
2597 |\
2587 | o
2598 | o
2588 | |
2599 | |
2589 o |
2600 o |
2590 |/
2601 |/
2591 o
2602 o
2592 |
2603 |
2593 o
2604 o
2594 |
2605 |
2595 o
2606 o
2596 |
2607 |
2597 o line 1
2608 o line 1
2598 line 2
2609 line 2
2599
2610
2600 Test bad template with better error message
2611 Test bad template with better error message
2601
2612
2602 $ hg log -Gv -R a --template '{desc|user()}'
2613 $ hg log -Gv -R a --template '{desc|user()}'
2603 hg: parse error: expected a symbol, got 'func'
2614 hg: parse error: expected a symbol, got 'func'
2604 [255]
2615 [255]
2605
2616
2606 Test word function (including index out of bounds graceful failure)
2617 Test word function (including index out of bounds graceful failure)
2607
2618
2608 $ hg log -Gv -R a --template "{word('1', desc)}"
2619 $ hg log -Gv -R a --template "{word('1', desc)}"
2609 @
2620 @
2610 |
2621 |
2611 o
2622 o
2612 |
2623 |
2613 o
2624 o
2614
2625
2615 o
2626 o
2616 |\
2627 |\
2617 | o head
2628 | o head
2618 | |
2629 | |
2619 o | branch
2630 o | branch
2620 |/
2631 |/
2621 o user,
2632 o user,
2622 |
2633 |
2623 o person
2634 o person
2624 |
2635 |
2625 o 1
2636 o 1
2626 |
2637 |
2627 o 1
2638 o 1
2628
2639
2629
2640
2630 Test word third parameter used as splitter
2641 Test word third parameter used as splitter
2631
2642
2632 $ hg log -Gv -R a --template "{word('0', desc, 'o')}"
2643 $ hg log -Gv -R a --template "{word('0', desc, 'o')}"
2633 @ future
2644 @ future
2634 |
2645 |
2635 o third
2646 o third
2636 |
2647 |
2637 o sec
2648 o sec
2638
2649
2639 o merge
2650 o merge
2640 |\
2651 |\
2641 | o new head
2652 | o new head
2642 | |
2653 | |
2643 o | new branch
2654 o | new branch
2644 |/
2655 |/
2645 o n
2656 o n
2646 |
2657 |
2647 o n
2658 o n
2648 |
2659 |
2649 o
2660 o
2650 |
2661 |
2651 o line 1
2662 o line 1
2652 line 2
2663 line 2
2653
2664
2654 Test word error messages for not enough and too many arguments
2665 Test word error messages for not enough and too many arguments
2655
2666
2656 $ hg log -Gv -R a --template "{word('0')}"
2667 $ hg log -Gv -R a --template "{word('0')}"
2657 hg: parse error: word expects two or three arguments, got 1
2668 hg: parse error: word expects two or three arguments, got 1
2658 [255]
2669 [255]
2659
2670
2660 $ hg log -Gv -R a --template "{word('0', desc, 'o', 'h', 'b', 'o', 'y')}"
2671 $ hg log -Gv -R a --template "{word('0', desc, 'o', 'h', 'b', 'o', 'y')}"
2661 hg: parse error: word expects two or three arguments, got 7
2672 hg: parse error: word expects two or three arguments, got 7
2662 [255]
2673 [255]
2663
2674
2664 Test word for invalid numbers
2675 Test word for invalid numbers
2665
2676
2666 $ hg log -Gv -R a --template "{word(2, desc)}"
2677 $ hg log -Gv -R a --template "{word(2, desc)}"
2667 hg: parse error: Use strings like '3' for numbers passed to word function
2678 hg: parse error: Use strings like '3' for numbers passed to word function
2668 [255]
2679 [255]
General Comments 0
You need to be logged in to leave comments. Login now