##// END OF EJS Templates
templater: fail more gracefully for blank strings to word
Ryan McElroy -
r24886:10a13da8 stable
parent child Browse files
Show More
@@ -1,798 +1,803 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 if n > 0 and tmpl[n - 1] == '\\':
90 if n > 0 and tmpl[n - 1] == '\\':
91 # escaped
91 # escaped
92 parsed.append((strtoken, (tmpl[pos:n - 1] + "{")))
92 parsed.append((strtoken, (tmpl[pos:n - 1] + "{")))
93 pos = n + 1
93 pos = n + 1
94 continue
94 continue
95 if n > pos:
95 if n > pos:
96 parsed.append((strtoken, tmpl[pos:n]))
96 parsed.append((strtoken, tmpl[pos:n]))
97
97
98 pd = [tmpl, n + 1, stop]
98 pd = [tmpl, n + 1, stop]
99 parseres, pos = p.parse(pd)
99 parseres, pos = p.parse(pd)
100 parsed.append(parseres)
100 parsed.append(parseres)
101
101
102 return [compileexp(e, context) for e in parsed]
102 return [compileexp(e, context) for e in parsed]
103
103
104 def compileexp(exp, context):
104 def compileexp(exp, context):
105 t = exp[0]
105 t = exp[0]
106 if t in methods:
106 if t in methods:
107 return methods[t](exp, context)
107 return methods[t](exp, context)
108 raise error.ParseError(_("unknown method '%s'") % t)
108 raise error.ParseError(_("unknown method '%s'") % t)
109
109
110 # template evaluation
110 # template evaluation
111
111
112 def getsymbol(exp):
112 def getsymbol(exp):
113 if exp[0] == 'symbol':
113 if exp[0] == 'symbol':
114 return exp[1]
114 return exp[1]
115 raise error.ParseError(_("expected a symbol, got '%s'") % exp[0])
115 raise error.ParseError(_("expected a symbol, got '%s'") % exp[0])
116
116
117 def getlist(x):
117 def getlist(x):
118 if not x:
118 if not x:
119 return []
119 return []
120 if x[0] == 'list':
120 if x[0] == 'list':
121 return getlist(x[1]) + [x[2]]
121 return getlist(x[1]) + [x[2]]
122 return [x]
122 return [x]
123
123
124 def getfilter(exp, context):
124 def getfilter(exp, context):
125 f = getsymbol(exp)
125 f = getsymbol(exp)
126 if f not in context._filters:
126 if f not in context._filters:
127 raise error.ParseError(_("unknown function '%s'") % f)
127 raise error.ParseError(_("unknown function '%s'") % f)
128 return context._filters[f]
128 return context._filters[f]
129
129
130 def gettemplate(exp, context):
130 def gettemplate(exp, context):
131 if exp[0] == 'string' or exp[0] == 'rawstring':
131 if exp[0] == 'string' or exp[0] == 'rawstring':
132 return compiletemplate(exp[1], context, strtoken=exp[0])
132 return compiletemplate(exp[1], context, strtoken=exp[0])
133 if exp[0] == 'symbol':
133 if exp[0] == 'symbol':
134 return context._load(exp[1])
134 return context._load(exp[1])
135 raise error.ParseError(_("expected template specifier"))
135 raise error.ParseError(_("expected template specifier"))
136
136
137 def runstring(context, mapping, data):
137 def runstring(context, mapping, data):
138 return data.decode("string-escape")
138 return data.decode("string-escape")
139
139
140 def runrawstring(context, mapping, data):
140 def runrawstring(context, mapping, data):
141 return data
141 return data
142
142
143 def runsymbol(context, mapping, key):
143 def runsymbol(context, mapping, key):
144 v = mapping.get(key)
144 v = mapping.get(key)
145 if v is None:
145 if v is None:
146 v = context._defaults.get(key)
146 v = context._defaults.get(key)
147 if v is None:
147 if v is None:
148 try:
148 try:
149 v = context.process(key, mapping)
149 v = context.process(key, mapping)
150 except TemplateNotFound:
150 except TemplateNotFound:
151 v = ''
151 v = ''
152 if callable(v):
152 if callable(v):
153 return v(**mapping)
153 return v(**mapping)
154 if isinstance(v, types.GeneratorType):
154 if isinstance(v, types.GeneratorType):
155 v = list(v)
155 v = list(v)
156 return v
156 return v
157
157
158 def buildfilter(exp, context):
158 def buildfilter(exp, context):
159 func, data = compileexp(exp[1], context)
159 func, data = compileexp(exp[1], context)
160 filt = getfilter(exp[2], context)
160 filt = getfilter(exp[2], context)
161 return (runfilter, (func, data, filt))
161 return (runfilter, (func, data, filt))
162
162
163 def runfilter(context, mapping, data):
163 def runfilter(context, mapping, data):
164 func, data, filt = data
164 func, data, filt = data
165 # func() may return string, generator of strings or arbitrary object such
165 # func() may return string, generator of strings or arbitrary object such
166 # as date tuple, but filter does not want generator.
166 # as date tuple, but filter does not want generator.
167 thing = func(context, mapping, data)
167 thing = func(context, mapping, data)
168 if isinstance(thing, types.GeneratorType):
168 if isinstance(thing, types.GeneratorType):
169 thing = stringify(thing)
169 thing = stringify(thing)
170 try:
170 try:
171 return filt(thing)
171 return filt(thing)
172 except (ValueError, AttributeError, TypeError):
172 except (ValueError, AttributeError, TypeError):
173 if isinstance(data, tuple):
173 if isinstance(data, tuple):
174 dt = data[1]
174 dt = data[1]
175 else:
175 else:
176 dt = data
176 dt = data
177 raise util.Abort(_("template filter '%s' is not compatible with "
177 raise util.Abort(_("template filter '%s' is not compatible with "
178 "keyword '%s'") % (filt.func_name, dt))
178 "keyword '%s'") % (filt.func_name, dt))
179
179
180 def buildmap(exp, context):
180 def buildmap(exp, context):
181 func, data = compileexp(exp[1], context)
181 func, data = compileexp(exp[1], context)
182 ctmpl = gettemplate(exp[2], context)
182 ctmpl = gettemplate(exp[2], context)
183 return (runmap, (func, data, ctmpl))
183 return (runmap, (func, data, ctmpl))
184
184
185 def runtemplate(context, mapping, template):
185 def runtemplate(context, mapping, template):
186 for func, data in template:
186 for func, data in template:
187 yield func(context, mapping, data)
187 yield func(context, mapping, data)
188
188
189 def runmap(context, mapping, data):
189 def runmap(context, mapping, data):
190 func, data, ctmpl = data
190 func, data, ctmpl = data
191 d = func(context, mapping, data)
191 d = func(context, mapping, data)
192 if callable(d):
192 if callable(d):
193 d = d()
193 d = d()
194
194
195 lm = mapping.copy()
195 lm = mapping.copy()
196
196
197 for i in d:
197 for i in d:
198 if isinstance(i, dict):
198 if isinstance(i, dict):
199 lm.update(i)
199 lm.update(i)
200 lm['originalnode'] = mapping.get('node')
200 lm['originalnode'] = mapping.get('node')
201 yield runtemplate(context, lm, ctmpl)
201 yield runtemplate(context, lm, ctmpl)
202 else:
202 else:
203 # v is not an iterable of dicts, this happen when 'key'
203 # v is not an iterable of dicts, this happen when 'key'
204 # has been fully expanded already and format is useless.
204 # has been fully expanded already and format is useless.
205 # If so, return the expanded value.
205 # If so, return the expanded value.
206 yield i
206 yield i
207
207
208 def buildfunc(exp, context):
208 def buildfunc(exp, context):
209 n = getsymbol(exp[1])
209 n = getsymbol(exp[1])
210 args = [compileexp(x, context) for x in getlist(exp[2])]
210 args = [compileexp(x, context) for x in getlist(exp[2])]
211 if n in funcs:
211 if n in funcs:
212 f = funcs[n]
212 f = funcs[n]
213 return (f, args)
213 return (f, args)
214 if n in context._filters:
214 if n in context._filters:
215 if len(args) != 1:
215 if len(args) != 1:
216 raise error.ParseError(_("filter %s expects one argument") % n)
216 raise error.ParseError(_("filter %s expects one argument") % n)
217 f = context._filters[n]
217 f = context._filters[n]
218 return (runfilter, (args[0][0], args[0][1], f))
218 return (runfilter, (args[0][0], args[0][1], f))
219 raise error.ParseError(_("unknown function '%s'") % n)
219 raise error.ParseError(_("unknown function '%s'") % n)
220
220
221 def date(context, mapping, args):
221 def date(context, mapping, args):
222 """:date(date[, fmt]): Format a date. See :hg:`help dates` for formatting
222 """:date(date[, fmt]): Format a date. See :hg:`help dates` for formatting
223 strings."""
223 strings."""
224 if not (1 <= len(args) <= 2):
224 if not (1 <= len(args) <= 2):
225 # i18n: "date" is a keyword
225 # i18n: "date" is a keyword
226 raise error.ParseError(_("date expects one or two arguments"))
226 raise error.ParseError(_("date expects one or two arguments"))
227
227
228 date = args[0][0](context, mapping, args[0][1])
228 date = args[0][0](context, mapping, args[0][1])
229 if len(args) == 2:
229 if len(args) == 2:
230 fmt = stringify(args[1][0](context, mapping, args[1][1]))
230 fmt = stringify(args[1][0](context, mapping, args[1][1]))
231 return util.datestr(date, fmt)
231 return util.datestr(date, fmt)
232 return util.datestr(date)
232 return util.datestr(date)
233
233
234 def diff(context, mapping, args):
234 def diff(context, mapping, args):
235 """:diff([includepattern [, excludepattern]]): Show a diff, optionally
235 """:diff([includepattern [, excludepattern]]): Show a diff, optionally
236 specifying files to include or exclude."""
236 specifying files to include or exclude."""
237 if len(args) > 2:
237 if len(args) > 2:
238 # i18n: "diff" is a keyword
238 # i18n: "diff" is a keyword
239 raise error.ParseError(_("diff expects one, two or no arguments"))
239 raise error.ParseError(_("diff expects one, two or no arguments"))
240
240
241 def getpatterns(i):
241 def getpatterns(i):
242 if i < len(args):
242 if i < len(args):
243 s = args[i][1].strip()
243 s = args[i][1].strip()
244 if s:
244 if s:
245 return [s]
245 return [s]
246 return []
246 return []
247
247
248 ctx = mapping['ctx']
248 ctx = mapping['ctx']
249 chunks = ctx.diff(match=ctx.match([], getpatterns(0), getpatterns(1)))
249 chunks = ctx.diff(match=ctx.match([], getpatterns(0), getpatterns(1)))
250
250
251 return ''.join(chunks)
251 return ''.join(chunks)
252
252
253 def fill(context, mapping, args):
253 def fill(context, mapping, args):
254 """:fill(text[, width[, initialident[, hangindent]]]): Fill many
254 """:fill(text[, width[, initialident[, hangindent]]]): Fill many
255 paragraphs with optional indentation. See the "fill" filter."""
255 paragraphs with optional indentation. See the "fill" filter."""
256 if not (1 <= len(args) <= 4):
256 if not (1 <= len(args) <= 4):
257 # i18n: "fill" is a keyword
257 # i18n: "fill" is a keyword
258 raise error.ParseError(_("fill expects one to four arguments"))
258 raise error.ParseError(_("fill expects one to four arguments"))
259
259
260 text = stringify(args[0][0](context, mapping, args[0][1]))
260 text = stringify(args[0][0](context, mapping, args[0][1]))
261 width = 76
261 width = 76
262 initindent = ''
262 initindent = ''
263 hangindent = ''
263 hangindent = ''
264 if 2 <= len(args) <= 4:
264 if 2 <= len(args) <= 4:
265 try:
265 try:
266 width = int(stringify(args[1][0](context, mapping, args[1][1])))
266 width = int(stringify(args[1][0](context, mapping, args[1][1])))
267 except ValueError:
267 except ValueError:
268 # i18n: "fill" is a keyword
268 # i18n: "fill" is a keyword
269 raise error.ParseError(_("fill expects an integer width"))
269 raise error.ParseError(_("fill expects an integer width"))
270 try:
270 try:
271 initindent = stringify(_evalifliteral(args[2], context, mapping))
271 initindent = stringify(_evalifliteral(args[2], context, mapping))
272 hangindent = stringify(_evalifliteral(args[3], context, mapping))
272 hangindent = stringify(_evalifliteral(args[3], context, mapping))
273 except IndexError:
273 except IndexError:
274 pass
274 pass
275
275
276 return templatefilters.fill(text, width, initindent, hangindent)
276 return templatefilters.fill(text, width, initindent, hangindent)
277
277
278 def pad(context, mapping, args):
278 def pad(context, mapping, args):
279 """:pad(text, width[, fillchar=' '[, right=False]]): Pad text with a
279 """:pad(text, width[, fillchar=' '[, right=False]]): Pad text with a
280 fill character."""
280 fill character."""
281 if not (2 <= len(args) <= 4):
281 if not (2 <= len(args) <= 4):
282 # i18n: "pad" is a keyword
282 # i18n: "pad" is a keyword
283 raise error.ParseError(_("pad() expects two to four arguments"))
283 raise error.ParseError(_("pad() expects two to four arguments"))
284
284
285 width = int(args[1][1])
285 width = int(args[1][1])
286
286
287 text = stringify(args[0][0](context, mapping, args[0][1]))
287 text = stringify(args[0][0](context, mapping, args[0][1]))
288 if args[0][0] == runstring:
288 if args[0][0] == runstring:
289 text = stringify(runtemplate(context, mapping,
289 text = stringify(runtemplate(context, mapping,
290 compiletemplate(text, context)))
290 compiletemplate(text, context)))
291
291
292 right = False
292 right = False
293 fillchar = ' '
293 fillchar = ' '
294 if len(args) > 2:
294 if len(args) > 2:
295 fillchar = stringify(args[2][0](context, mapping, args[2][1]))
295 fillchar = stringify(args[2][0](context, mapping, args[2][1]))
296 if len(args) > 3:
296 if len(args) > 3:
297 right = util.parsebool(args[3][1])
297 right = util.parsebool(args[3][1])
298
298
299 if right:
299 if right:
300 return text.rjust(width, fillchar)
300 return text.rjust(width, fillchar)
301 else:
301 else:
302 return text.ljust(width, fillchar)
302 return text.ljust(width, fillchar)
303
303
304 def get(context, mapping, args):
304 def get(context, mapping, args):
305 """:get(dict, key): Get an attribute/key from an object. Some keywords
305 """:get(dict, key): Get an attribute/key from an object. Some keywords
306 are complex types. This function allows you to obtain the value of an
306 are complex types. This function allows you to obtain the value of an
307 attribute on these type."""
307 attribute on these type."""
308 if len(args) != 2:
308 if len(args) != 2:
309 # i18n: "get" is a keyword
309 # i18n: "get" is a keyword
310 raise error.ParseError(_("get() expects two arguments"))
310 raise error.ParseError(_("get() expects two arguments"))
311
311
312 dictarg = args[0][0](context, mapping, args[0][1])
312 dictarg = args[0][0](context, mapping, args[0][1])
313 if not util.safehasattr(dictarg, 'get'):
313 if not util.safehasattr(dictarg, 'get'):
314 # i18n: "get" is a keyword
314 # i18n: "get" is a keyword
315 raise error.ParseError(_("get() expects a dict as first argument"))
315 raise error.ParseError(_("get() expects a dict as first argument"))
316
316
317 key = args[1][0](context, mapping, args[1][1])
317 key = args[1][0](context, mapping, args[1][1])
318 yield dictarg.get(key)
318 yield dictarg.get(key)
319
319
320 def _evalifliteral(arg, context, mapping):
320 def _evalifliteral(arg, context, mapping):
321 t = stringify(arg[0](context, mapping, arg[1]))
321 t = stringify(arg[0](context, mapping, arg[1]))
322 if arg[0] == runstring or arg[0] == runrawstring:
322 if arg[0] == runstring or arg[0] == runrawstring:
323 yield runtemplate(context, mapping,
323 yield runtemplate(context, mapping,
324 compiletemplate(t, context, strtoken='rawstring'))
324 compiletemplate(t, context, strtoken='rawstring'))
325 else:
325 else:
326 yield t
326 yield t
327
327
328 def if_(context, mapping, args):
328 def if_(context, mapping, args):
329 """:if(expr, then[, else]): Conditionally execute based on the result of
329 """:if(expr, then[, else]): Conditionally execute based on the result of
330 an expression."""
330 an expression."""
331 if not (2 <= len(args) <= 3):
331 if not (2 <= len(args) <= 3):
332 # i18n: "if" is a keyword
332 # i18n: "if" is a keyword
333 raise error.ParseError(_("if expects two or three arguments"))
333 raise error.ParseError(_("if expects two or three arguments"))
334
334
335 test = stringify(args[0][0](context, mapping, args[0][1]))
335 test = stringify(args[0][0](context, mapping, args[0][1]))
336 if test:
336 if test:
337 yield _evalifliteral(args[1], context, mapping)
337 yield _evalifliteral(args[1], context, mapping)
338 elif len(args) == 3:
338 elif len(args) == 3:
339 yield _evalifliteral(args[2], context, mapping)
339 yield _evalifliteral(args[2], context, mapping)
340
340
341 def ifcontains(context, mapping, args):
341 def ifcontains(context, mapping, args):
342 """:ifcontains(search, thing, then[, else]): Conditionally execute based
342 """:ifcontains(search, thing, then[, else]): Conditionally execute based
343 on whether the item "search" is in "thing"."""
343 on whether the item "search" is in "thing"."""
344 if not (3 <= len(args) <= 4):
344 if not (3 <= len(args) <= 4):
345 # i18n: "ifcontains" is a keyword
345 # i18n: "ifcontains" is a keyword
346 raise error.ParseError(_("ifcontains expects three or four arguments"))
346 raise error.ParseError(_("ifcontains expects three or four arguments"))
347
347
348 item = stringify(args[0][0](context, mapping, args[0][1]))
348 item = stringify(args[0][0](context, mapping, args[0][1]))
349 items = args[1][0](context, mapping, args[1][1])
349 items = args[1][0](context, mapping, args[1][1])
350
350
351 if item in items:
351 if item in items:
352 yield _evalifliteral(args[2], context, mapping)
352 yield _evalifliteral(args[2], context, mapping)
353 elif len(args) == 4:
353 elif len(args) == 4:
354 yield _evalifliteral(args[3], context, mapping)
354 yield _evalifliteral(args[3], context, mapping)
355
355
356 def ifeq(context, mapping, args):
356 def ifeq(context, mapping, args):
357 """:ifeq(expr1, expr2, then[, else]): Conditionally execute based on
357 """:ifeq(expr1, expr2, then[, else]): Conditionally execute based on
358 whether 2 items are equivalent."""
358 whether 2 items are equivalent."""
359 if not (3 <= len(args) <= 4):
359 if not (3 <= len(args) <= 4):
360 # i18n: "ifeq" is a keyword
360 # i18n: "ifeq" is a keyword
361 raise error.ParseError(_("ifeq expects three or four arguments"))
361 raise error.ParseError(_("ifeq expects three or four arguments"))
362
362
363 test = stringify(args[0][0](context, mapping, args[0][1]))
363 test = stringify(args[0][0](context, mapping, args[0][1]))
364 match = stringify(args[1][0](context, mapping, args[1][1]))
364 match = stringify(args[1][0](context, mapping, args[1][1]))
365 if test == match:
365 if test == match:
366 yield _evalifliteral(args[2], context, mapping)
366 yield _evalifliteral(args[2], context, mapping)
367 elif len(args) == 4:
367 elif len(args) == 4:
368 yield _evalifliteral(args[3], context, mapping)
368 yield _evalifliteral(args[3], context, mapping)
369
369
370 def join(context, mapping, args):
370 def join(context, mapping, args):
371 """:join(list, sep): Join items in a list with a delimiter."""
371 """:join(list, sep): Join items in a list with a delimiter."""
372 if not (1 <= len(args) <= 2):
372 if not (1 <= len(args) <= 2):
373 # i18n: "join" is a keyword
373 # i18n: "join" is a keyword
374 raise error.ParseError(_("join expects one or two arguments"))
374 raise error.ParseError(_("join expects one or two arguments"))
375
375
376 joinset = args[0][0](context, mapping, args[0][1])
376 joinset = args[0][0](context, mapping, args[0][1])
377 if callable(joinset):
377 if callable(joinset):
378 jf = joinset.joinfmt
378 jf = joinset.joinfmt
379 joinset = [jf(x) for x in joinset()]
379 joinset = [jf(x) for x in joinset()]
380
380
381 joiner = " "
381 joiner = " "
382 if len(args) > 1:
382 if len(args) > 1:
383 joiner = stringify(args[1][0](context, mapping, args[1][1]))
383 joiner = stringify(args[1][0](context, mapping, args[1][1]))
384
384
385 first = True
385 first = True
386 for x in joinset:
386 for x in joinset:
387 if first:
387 if first:
388 first = False
388 first = False
389 else:
389 else:
390 yield joiner
390 yield joiner
391 yield x
391 yield x
392
392
393 def label(context, mapping, args):
393 def label(context, mapping, args):
394 """:label(label, expr): Apply a label to generated content. Content with
394 """:label(label, expr): Apply a label to generated content. Content with
395 a label applied can result in additional post-processing, such as
395 a label applied can result in additional post-processing, such as
396 automatic colorization."""
396 automatic colorization."""
397 if len(args) != 2:
397 if len(args) != 2:
398 # i18n: "label" is a keyword
398 # i18n: "label" is a keyword
399 raise error.ParseError(_("label expects two arguments"))
399 raise error.ParseError(_("label expects two arguments"))
400
400
401 # ignore args[0] (the label string) since this is supposed to be a a no-op
401 # ignore args[0] (the label string) since this is supposed to be a a no-op
402 yield _evalifliteral(args[1], context, mapping)
402 yield _evalifliteral(args[1], context, mapping)
403
403
404 def revset(context, mapping, args):
404 def revset(context, mapping, args):
405 """:revset(query[, formatargs...]): Execute a revision set query. See
405 """:revset(query[, formatargs...]): Execute a revision set query. See
406 :hg:`help revset`."""
406 :hg:`help revset`."""
407 if not len(args) > 0:
407 if not len(args) > 0:
408 # i18n: "revset" is a keyword
408 # i18n: "revset" is a keyword
409 raise error.ParseError(_("revset expects one or more arguments"))
409 raise error.ParseError(_("revset expects one or more arguments"))
410
410
411 raw = args[0][1]
411 raw = args[0][1]
412 ctx = mapping['ctx']
412 ctx = mapping['ctx']
413 repo = ctx.repo()
413 repo = ctx.repo()
414
414
415 def query(expr):
415 def query(expr):
416 m = revsetmod.match(repo.ui, expr)
416 m = revsetmod.match(repo.ui, expr)
417 return m(repo)
417 return m(repo)
418
418
419 if len(args) > 1:
419 if len(args) > 1:
420 formatargs = list([a[0](context, mapping, a[1]) for a in args[1:]])
420 formatargs = list([a[0](context, mapping, a[1]) for a in args[1:]])
421 revs = query(revsetmod.formatspec(raw, *formatargs))
421 revs = query(revsetmod.formatspec(raw, *formatargs))
422 revs = list([str(r) for r in revs])
422 revs = list([str(r) for r in revs])
423 else:
423 else:
424 revsetcache = mapping['cache'].setdefault("revsetcache", {})
424 revsetcache = mapping['cache'].setdefault("revsetcache", {})
425 if raw in revsetcache:
425 if raw in revsetcache:
426 revs = revsetcache[raw]
426 revs = revsetcache[raw]
427 else:
427 else:
428 revs = query(raw)
428 revs = query(raw)
429 revs = list([str(r) for r in revs])
429 revs = list([str(r) for r in revs])
430 revsetcache[raw] = revs
430 revsetcache[raw] = revs
431
431
432 return templatekw.showlist("revision", revs, **mapping)
432 return templatekw.showlist("revision", revs, **mapping)
433
433
434 def rstdoc(context, mapping, args):
434 def rstdoc(context, mapping, args):
435 """:rstdoc(text, style): Format ReStructuredText."""
435 """:rstdoc(text, style): Format ReStructuredText."""
436 if len(args) != 2:
436 if len(args) != 2:
437 # i18n: "rstdoc" is a keyword
437 # i18n: "rstdoc" is a keyword
438 raise error.ParseError(_("rstdoc expects two arguments"))
438 raise error.ParseError(_("rstdoc expects two arguments"))
439
439
440 text = stringify(args[0][0](context, mapping, args[0][1]))
440 text = stringify(args[0][0](context, mapping, args[0][1]))
441 style = stringify(args[1][0](context, mapping, args[1][1]))
441 style = stringify(args[1][0](context, mapping, args[1][1]))
442
442
443 return minirst.format(text, style=style, keep=['verbose'])
443 return minirst.format(text, style=style, keep=['verbose'])
444
444
445 def shortest(context, mapping, args):
445 def shortest(context, mapping, args):
446 """:shortest(node, minlength=4): Obtain the shortest representation of
446 """:shortest(node, minlength=4): Obtain the shortest representation of
447 a node."""
447 a node."""
448 if not (1 <= len(args) <= 2):
448 if not (1 <= len(args) <= 2):
449 # i18n: "shortest" is a keyword
449 # i18n: "shortest" is a keyword
450 raise error.ParseError(_("shortest() expects one or two arguments"))
450 raise error.ParseError(_("shortest() expects one or two arguments"))
451
451
452 node = stringify(args[0][0](context, mapping, args[0][1]))
452 node = stringify(args[0][0](context, mapping, args[0][1]))
453
453
454 minlength = 4
454 minlength = 4
455 if len(args) > 1:
455 if len(args) > 1:
456 minlength = int(args[1][1])
456 minlength = int(args[1][1])
457
457
458 cl = mapping['ctx']._repo.changelog
458 cl = mapping['ctx']._repo.changelog
459 def isvalid(test):
459 def isvalid(test):
460 try:
460 try:
461 try:
461 try:
462 cl.index.partialmatch(test)
462 cl.index.partialmatch(test)
463 except AttributeError:
463 except AttributeError:
464 # Pure mercurial doesn't support partialmatch on the index.
464 # Pure mercurial doesn't support partialmatch on the index.
465 # Fallback to the slow way.
465 # Fallback to the slow way.
466 if cl._partialmatch(test) is None:
466 if cl._partialmatch(test) is None:
467 return False
467 return False
468
468
469 try:
469 try:
470 i = int(test)
470 i = int(test)
471 # if we are a pure int, then starting with zero will not be
471 # if we are a pure int, then starting with zero will not be
472 # confused as a rev; or, obviously, if the int is larger than
472 # confused as a rev; or, obviously, if the int is larger than
473 # the value of the tip rev
473 # the value of the tip rev
474 if test[0] == '0' or i > len(cl):
474 if test[0] == '0' or i > len(cl):
475 return True
475 return True
476 return False
476 return False
477 except ValueError:
477 except ValueError:
478 return True
478 return True
479 except error.RevlogError:
479 except error.RevlogError:
480 return False
480 return False
481
481
482 shortest = node
482 shortest = node
483 startlength = max(6, minlength)
483 startlength = max(6, minlength)
484 length = startlength
484 length = startlength
485 while True:
485 while True:
486 test = node[:length]
486 test = node[:length]
487 if isvalid(test):
487 if isvalid(test):
488 shortest = test
488 shortest = test
489 if length == minlength or length > startlength:
489 if length == minlength or length > startlength:
490 return shortest
490 return shortest
491 length -= 1
491 length -= 1
492 else:
492 else:
493 length += 1
493 length += 1
494 if len(shortest) <= length:
494 if len(shortest) <= length:
495 return shortest
495 return shortest
496
496
497 def strip(context, mapping, args):
497 def strip(context, mapping, args):
498 """:strip(text[, chars]): Strip characters from a string."""
498 """:strip(text[, chars]): Strip characters from a string."""
499 if not (1 <= len(args) <= 2):
499 if not (1 <= len(args) <= 2):
500 # i18n: "strip" is a keyword
500 # i18n: "strip" is a keyword
501 raise error.ParseError(_("strip expects one or two arguments"))
501 raise error.ParseError(_("strip expects one or two arguments"))
502
502
503 text = stringify(args[0][0](context, mapping, args[0][1]))
503 text = stringify(args[0][0](context, mapping, args[0][1]))
504 if len(args) == 2:
504 if len(args) == 2:
505 chars = stringify(args[1][0](context, mapping, args[1][1]))
505 chars = stringify(args[1][0](context, mapping, args[1][1]))
506 return text.strip(chars)
506 return text.strip(chars)
507 return text.strip()
507 return text.strip()
508
508
509 def sub(context, mapping, args):
509 def sub(context, mapping, args):
510 """:sub(pattern, replacement, expression): Perform text substitution
510 """:sub(pattern, replacement, expression): Perform text substitution
511 using regular expressions."""
511 using regular expressions."""
512 if len(args) != 3:
512 if len(args) != 3:
513 # i18n: "sub" is a keyword
513 # i18n: "sub" is a keyword
514 raise error.ParseError(_("sub expects three arguments"))
514 raise error.ParseError(_("sub expects three arguments"))
515
515
516 pat = stringify(args[0][0](context, mapping, args[0][1]))
516 pat = stringify(args[0][0](context, mapping, args[0][1]))
517 rpl = stringify(args[1][0](context, mapping, args[1][1]))
517 rpl = stringify(args[1][0](context, mapping, args[1][1]))
518 src = stringify(_evalifliteral(args[2], context, mapping))
518 src = stringify(_evalifliteral(args[2], context, mapping))
519 yield re.sub(pat, rpl, src)
519 yield re.sub(pat, rpl, src)
520
520
521 def startswith(context, mapping, args):
521 def startswith(context, mapping, args):
522 """:startswith(pattern, text): Returns the value from the "text" argument
522 """:startswith(pattern, text): Returns the value from the "text" argument
523 if it begins with the content from the "pattern" argument."""
523 if it begins with the content from the "pattern" argument."""
524 if len(args) != 2:
524 if len(args) != 2:
525 # i18n: "startswith" is a keyword
525 # i18n: "startswith" is a keyword
526 raise error.ParseError(_("startswith expects two arguments"))
526 raise error.ParseError(_("startswith expects two arguments"))
527
527
528 patn = stringify(args[0][0](context, mapping, args[0][1]))
528 patn = stringify(args[0][0](context, mapping, args[0][1]))
529 text = stringify(args[1][0](context, mapping, args[1][1]))
529 text = stringify(args[1][0](context, mapping, args[1][1]))
530 if text.startswith(patn):
530 if text.startswith(patn):
531 return text
531 return text
532 return ''
532 return ''
533
533
534
534
535 def word(context, mapping, args):
535 def word(context, mapping, args):
536 """:word(number, text[, separator]): Return the nth word from a string."""
536 """:word(number, text[, separator]): Return the nth word from a string."""
537 if not (2 <= len(args) <= 3):
537 if not (2 <= len(args) <= 3):
538 # i18n: "word" is a keyword
538 # i18n: "word" is a keyword
539 raise error.ParseError(_("word expects two or three arguments, got %d")
539 raise error.ParseError(_("word expects two or three arguments, got %d")
540 % len(args))
540 % len(args))
541
541
542 num = int(stringify(args[0][0](context, mapping, args[0][1])))
542 try:
543 num = int(stringify(args[0][0](context, mapping, args[0][1])))
544 except ValueError:
545 # i18n: "word" is a keyword
546 raise error.ParseError(
547 _("Use strings like '3' for numbers passed to word function"))
543 text = stringify(args[1][0](context, mapping, args[1][1]))
548 text = stringify(args[1][0](context, mapping, args[1][1]))
544 if len(args) == 3:
549 if len(args) == 3:
545 splitter = stringify(args[2][0](context, mapping, args[2][1]))
550 splitter = stringify(args[2][0](context, mapping, args[2][1]))
546 else:
551 else:
547 splitter = None
552 splitter = None
548
553
549 tokens = text.split(splitter)
554 tokens = text.split(splitter)
550 if num >= len(tokens):
555 if num >= len(tokens):
551 return ''
556 return ''
552 else:
557 else:
553 return tokens[num]
558 return tokens[num]
554
559
555 methods = {
560 methods = {
556 "string": lambda e, c: (runstring, e[1]),
561 "string": lambda e, c: (runstring, e[1]),
557 "rawstring": lambda e, c: (runrawstring, e[1]),
562 "rawstring": lambda e, c: (runrawstring, e[1]),
558 "symbol": lambda e, c: (runsymbol, e[1]),
563 "symbol": lambda e, c: (runsymbol, e[1]),
559 "group": lambda e, c: compileexp(e[1], c),
564 "group": lambda e, c: compileexp(e[1], c),
560 # ".": buildmember,
565 # ".": buildmember,
561 "|": buildfilter,
566 "|": buildfilter,
562 "%": buildmap,
567 "%": buildmap,
563 "func": buildfunc,
568 "func": buildfunc,
564 }
569 }
565
570
566 funcs = {
571 funcs = {
567 "date": date,
572 "date": date,
568 "diff": diff,
573 "diff": diff,
569 "fill": fill,
574 "fill": fill,
570 "get": get,
575 "get": get,
571 "if": if_,
576 "if": if_,
572 "ifcontains": ifcontains,
577 "ifcontains": ifcontains,
573 "ifeq": ifeq,
578 "ifeq": ifeq,
574 "join": join,
579 "join": join,
575 "label": label,
580 "label": label,
576 "pad": pad,
581 "pad": pad,
577 "revset": revset,
582 "revset": revset,
578 "rstdoc": rstdoc,
583 "rstdoc": rstdoc,
579 "shortest": shortest,
584 "shortest": shortest,
580 "startswith": startswith,
585 "startswith": startswith,
581 "strip": strip,
586 "strip": strip,
582 "sub": sub,
587 "sub": sub,
583 "word": word,
588 "word": word,
584 }
589 }
585
590
586 # template engine
591 # template engine
587
592
588 stringify = templatefilters.stringify
593 stringify = templatefilters.stringify
589
594
590 def _flatten(thing):
595 def _flatten(thing):
591 '''yield a single stream from a possibly nested set of iterators'''
596 '''yield a single stream from a possibly nested set of iterators'''
592 if isinstance(thing, str):
597 if isinstance(thing, str):
593 yield thing
598 yield thing
594 elif not util.safehasattr(thing, '__iter__'):
599 elif not util.safehasattr(thing, '__iter__'):
595 if thing is not None:
600 if thing is not None:
596 yield str(thing)
601 yield str(thing)
597 else:
602 else:
598 for i in thing:
603 for i in thing:
599 if isinstance(i, str):
604 if isinstance(i, str):
600 yield i
605 yield i
601 elif not util.safehasattr(i, '__iter__'):
606 elif not util.safehasattr(i, '__iter__'):
602 if i is not None:
607 if i is not None:
603 yield str(i)
608 yield str(i)
604 elif i is not None:
609 elif i is not None:
605 for j in _flatten(i):
610 for j in _flatten(i):
606 yield j
611 yield j
607
612
608 def parsestring(s, quoted=True):
613 def parsestring(s, quoted=True):
609 '''parse a string using simple c-like syntax.
614 '''parse a string using simple c-like syntax.
610 string must be in quotes if quoted is True.'''
615 string must be in quotes if quoted is True.'''
611 if quoted:
616 if quoted:
612 if len(s) < 2 or s[0] != s[-1]:
617 if len(s) < 2 or s[0] != s[-1]:
613 raise SyntaxError(_('unmatched quotes'))
618 raise SyntaxError(_('unmatched quotes'))
614 return s[1:-1].decode('string_escape')
619 return s[1:-1].decode('string_escape')
615
620
616 return s.decode('string_escape')
621 return s.decode('string_escape')
617
622
618 class engine(object):
623 class engine(object):
619 '''template expansion engine.
624 '''template expansion engine.
620
625
621 template expansion works like this. a map file contains key=value
626 template expansion works like this. a map file contains key=value
622 pairs. if value is quoted, it is treated as string. otherwise, it
627 pairs. if value is quoted, it is treated as string. otherwise, it
623 is treated as name of template file.
628 is treated as name of template file.
624
629
625 templater is asked to expand a key in map. it looks up key, and
630 templater is asked to expand a key in map. it looks up key, and
626 looks for strings like this: {foo}. it expands {foo} by looking up
631 looks for strings like this: {foo}. it expands {foo} by looking up
627 foo in map, and substituting it. expansion is recursive: it stops
632 foo in map, and substituting it. expansion is recursive: it stops
628 when there is no more {foo} to replace.
633 when there is no more {foo} to replace.
629
634
630 expansion also allows formatting and filtering.
635 expansion also allows formatting and filtering.
631
636
632 format uses key to expand each item in list. syntax is
637 format uses key to expand each item in list. syntax is
633 {key%format}.
638 {key%format}.
634
639
635 filter uses function to transform value. syntax is
640 filter uses function to transform value. syntax is
636 {key|filter1|filter2|...}.'''
641 {key|filter1|filter2|...}.'''
637
642
638 def __init__(self, loader, filters={}, defaults={}):
643 def __init__(self, loader, filters={}, defaults={}):
639 self._loader = loader
644 self._loader = loader
640 self._filters = filters
645 self._filters = filters
641 self._defaults = defaults
646 self._defaults = defaults
642 self._cache = {}
647 self._cache = {}
643
648
644 def _load(self, t):
649 def _load(self, t):
645 '''load, parse, and cache a template'''
650 '''load, parse, and cache a template'''
646 if t not in self._cache:
651 if t not in self._cache:
647 self._cache[t] = compiletemplate(self._loader(t), self)
652 self._cache[t] = compiletemplate(self._loader(t), self)
648 return self._cache[t]
653 return self._cache[t]
649
654
650 def process(self, t, mapping):
655 def process(self, t, mapping):
651 '''Perform expansion. t is name of map element to expand.
656 '''Perform expansion. t is name of map element to expand.
652 mapping contains added elements for use during expansion. Is a
657 mapping contains added elements for use during expansion. Is a
653 generator.'''
658 generator.'''
654 return _flatten(runtemplate(self, mapping, self._load(t)))
659 return _flatten(runtemplate(self, mapping, self._load(t)))
655
660
656 engines = {'default': engine}
661 engines = {'default': engine}
657
662
658 def stylelist():
663 def stylelist():
659 paths = templatepaths()
664 paths = templatepaths()
660 if not paths:
665 if not paths:
661 return _('no templates found, try `hg debuginstall` for more info')
666 return _('no templates found, try `hg debuginstall` for more info')
662 dirlist = os.listdir(paths[0])
667 dirlist = os.listdir(paths[0])
663 stylelist = []
668 stylelist = []
664 for file in dirlist:
669 for file in dirlist:
665 split = file.split(".")
670 split = file.split(".")
666 if split[0] == "map-cmdline":
671 if split[0] == "map-cmdline":
667 stylelist.append(split[1])
672 stylelist.append(split[1])
668 return ", ".join(sorted(stylelist))
673 return ", ".join(sorted(stylelist))
669
674
670 class TemplateNotFound(util.Abort):
675 class TemplateNotFound(util.Abort):
671 pass
676 pass
672
677
673 class templater(object):
678 class templater(object):
674
679
675 def __init__(self, mapfile, filters={}, defaults={}, cache={},
680 def __init__(self, mapfile, filters={}, defaults={}, cache={},
676 minchunk=1024, maxchunk=65536):
681 minchunk=1024, maxchunk=65536):
677 '''set up template engine.
682 '''set up template engine.
678 mapfile is name of file to read map definitions from.
683 mapfile is name of file to read map definitions from.
679 filters is dict of functions. each transforms a value into another.
684 filters is dict of functions. each transforms a value into another.
680 defaults is dict of default map definitions.'''
685 defaults is dict of default map definitions.'''
681 self.mapfile = mapfile or 'template'
686 self.mapfile = mapfile or 'template'
682 self.cache = cache.copy()
687 self.cache = cache.copy()
683 self.map = {}
688 self.map = {}
684 if mapfile:
689 if mapfile:
685 self.base = os.path.dirname(mapfile)
690 self.base = os.path.dirname(mapfile)
686 else:
691 else:
687 self.base = ''
692 self.base = ''
688 self.filters = templatefilters.filters.copy()
693 self.filters = templatefilters.filters.copy()
689 self.filters.update(filters)
694 self.filters.update(filters)
690 self.defaults = defaults
695 self.defaults = defaults
691 self.minchunk, self.maxchunk = minchunk, maxchunk
696 self.minchunk, self.maxchunk = minchunk, maxchunk
692 self.ecache = {}
697 self.ecache = {}
693
698
694 if not mapfile:
699 if not mapfile:
695 return
700 return
696 if not os.path.exists(mapfile):
701 if not os.path.exists(mapfile):
697 raise util.Abort(_("style '%s' not found") % mapfile,
702 raise util.Abort(_("style '%s' not found") % mapfile,
698 hint=_("available styles: %s") % stylelist())
703 hint=_("available styles: %s") % stylelist())
699
704
700 conf = config.config()
705 conf = config.config()
701 conf.read(mapfile)
706 conf.read(mapfile)
702
707
703 for key, val in conf[''].items():
708 for key, val in conf[''].items():
704 if not val:
709 if not val:
705 raise SyntaxError(_('%s: missing value') % conf.source('', key))
710 raise SyntaxError(_('%s: missing value') % conf.source('', key))
706 if val[0] in "'\"":
711 if val[0] in "'\"":
707 try:
712 try:
708 self.cache[key] = parsestring(val)
713 self.cache[key] = parsestring(val)
709 except SyntaxError, inst:
714 except SyntaxError, inst:
710 raise SyntaxError('%s: %s' %
715 raise SyntaxError('%s: %s' %
711 (conf.source('', key), inst.args[0]))
716 (conf.source('', key), inst.args[0]))
712 else:
717 else:
713 val = 'default', val
718 val = 'default', val
714 if ':' in val[1]:
719 if ':' in val[1]:
715 val = val[1].split(':', 1)
720 val = val[1].split(':', 1)
716 self.map[key] = val[0], os.path.join(self.base, val[1])
721 self.map[key] = val[0], os.path.join(self.base, val[1])
717
722
718 def __contains__(self, key):
723 def __contains__(self, key):
719 return key in self.cache or key in self.map
724 return key in self.cache or key in self.map
720
725
721 def load(self, t):
726 def load(self, t):
722 '''Get the template for the given template name. Use a local cache.'''
727 '''Get the template for the given template name. Use a local cache.'''
723 if t not in self.cache:
728 if t not in self.cache:
724 try:
729 try:
725 self.cache[t] = util.readfile(self.map[t][1])
730 self.cache[t] = util.readfile(self.map[t][1])
726 except KeyError, inst:
731 except KeyError, inst:
727 raise TemplateNotFound(_('"%s" not in template map') %
732 raise TemplateNotFound(_('"%s" not in template map') %
728 inst.args[0])
733 inst.args[0])
729 except IOError, inst:
734 except IOError, inst:
730 raise IOError(inst.args[0], _('template file %s: %s') %
735 raise IOError(inst.args[0], _('template file %s: %s') %
731 (self.map[t][1], inst.args[1]))
736 (self.map[t][1], inst.args[1]))
732 return self.cache[t]
737 return self.cache[t]
733
738
734 def __call__(self, t, **mapping):
739 def __call__(self, t, **mapping):
735 ttype = t in self.map and self.map[t][0] or 'default'
740 ttype = t in self.map and self.map[t][0] or 'default'
736 if ttype not in self.ecache:
741 if ttype not in self.ecache:
737 self.ecache[ttype] = engines[ttype](self.load,
742 self.ecache[ttype] = engines[ttype](self.load,
738 self.filters, self.defaults)
743 self.filters, self.defaults)
739 proc = self.ecache[ttype]
744 proc = self.ecache[ttype]
740
745
741 stream = proc.process(t, mapping)
746 stream = proc.process(t, mapping)
742 if self.minchunk:
747 if self.minchunk:
743 stream = util.increasingchunks(stream, min=self.minchunk,
748 stream = util.increasingchunks(stream, min=self.minchunk,
744 max=self.maxchunk)
749 max=self.maxchunk)
745 return stream
750 return stream
746
751
747 def templatepaths():
752 def templatepaths():
748 '''return locations used for template files.'''
753 '''return locations used for template files.'''
749 pathsrel = ['templates']
754 pathsrel = ['templates']
750 paths = [os.path.normpath(os.path.join(util.datapath, f))
755 paths = [os.path.normpath(os.path.join(util.datapath, f))
751 for f in pathsrel]
756 for f in pathsrel]
752 return [p for p in paths if os.path.isdir(p)]
757 return [p for p in paths if os.path.isdir(p)]
753
758
754 def templatepath(name):
759 def templatepath(name):
755 '''return location of template file. returns None if not found.'''
760 '''return location of template file. returns None if not found.'''
756 for p in templatepaths():
761 for p in templatepaths():
757 f = os.path.join(p, name)
762 f = os.path.join(p, name)
758 if os.path.exists(f):
763 if os.path.exists(f):
759 return f
764 return f
760 return None
765 return None
761
766
762 def stylemap(styles, paths=None):
767 def stylemap(styles, paths=None):
763 """Return path to mapfile for a given style.
768 """Return path to mapfile for a given style.
764
769
765 Searches mapfile in the following locations:
770 Searches mapfile in the following locations:
766 1. templatepath/style/map
771 1. templatepath/style/map
767 2. templatepath/map-style
772 2. templatepath/map-style
768 3. templatepath/map
773 3. templatepath/map
769 """
774 """
770
775
771 if paths is None:
776 if paths is None:
772 paths = templatepaths()
777 paths = templatepaths()
773 elif isinstance(paths, str):
778 elif isinstance(paths, str):
774 paths = [paths]
779 paths = [paths]
775
780
776 if isinstance(styles, str):
781 if isinstance(styles, str):
777 styles = [styles]
782 styles = [styles]
778
783
779 for style in styles:
784 for style in styles:
780 # only plain name is allowed to honor template paths
785 # only plain name is allowed to honor template paths
781 if (not style
786 if (not style
782 or style in (os.curdir, os.pardir)
787 or style in (os.curdir, os.pardir)
783 or os.sep in style
788 or os.sep in style
784 or os.altsep and os.altsep in style):
789 or os.altsep and os.altsep in style):
785 continue
790 continue
786 locations = [os.path.join(style, 'map'), 'map-' + style]
791 locations = [os.path.join(style, 'map'), 'map-' + style]
787 locations.append('map')
792 locations.append('map')
788
793
789 for path in paths:
794 for path in paths:
790 for location in locations:
795 for location in locations:
791 mapfile = os.path.join(path, location)
796 mapfile = os.path.join(path, location)
792 if os.path.isfile(mapfile):
797 if os.path.isfile(mapfile):
793 return style, mapfile
798 return style, mapfile
794
799
795 raise RuntimeError("No hgweb templates found in %r" % paths)
800 raise RuntimeError("No hgweb templates found in %r" % paths)
796
801
797 # tell hggettext to extract docstrings from these functions:
802 # tell hggettext to extract docstrings from these functions:
798 i18nfunctions = funcs.values()
803 i18nfunctions = funcs.values()
@@ -1,2622 +1,2628 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 string escaping:
2239 Test string escaping:
2240
2240
2241 $ hg log -R latesttag -r 0 --template '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2241 $ hg log -R latesttag -r 0 --template '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
2242 >
2242 >
2243 <>\n<[>
2243 <>\n<[>
2244 <>\n<]>
2244 <>\n<]>
2245 <>\n<
2245 <>\n<
2246
2246
2247 "string-escape"-ed "\x5c\x786e" becomes r"\x6e" (once) or r"n" (twice)
2247 "string-escape"-ed "\x5c\x786e" becomes r"\x6e" (once) or r"n" (twice)
2248
2248
2249 $ hg log -R a -r 0 --template '{if("1", "\x5c\x786e", "NG")}\n'
2249 $ hg log -R a -r 0 --template '{if("1", "\x5c\x786e", "NG")}\n'
2250 \x6e
2250 \x6e
2251 $ hg log -R a -r 0 --template '{if("1", r"\x5c\x786e", "NG")}\n'
2251 $ hg log -R a -r 0 --template '{if("1", r"\x5c\x786e", "NG")}\n'
2252 \x5c\x786e
2252 \x5c\x786e
2253 $ hg log -R a -r 0 --template '{if("", "NG", "\x5c\x786e")}\n'
2253 $ hg log -R a -r 0 --template '{if("", "NG", "\x5c\x786e")}\n'
2254 \x6e
2254 \x6e
2255 $ hg log -R a -r 0 --template '{if("", "NG", r"\x5c\x786e")}\n'
2255 $ hg log -R a -r 0 --template '{if("", "NG", r"\x5c\x786e")}\n'
2256 \x5c\x786e
2256 \x5c\x786e
2257
2257
2258 $ hg log -R a -r 2 --template '{ifeq("no perso\x6e", desc, "\x5c\x786e", "NG")}\n'
2258 $ hg log -R a -r 2 --template '{ifeq("no perso\x6e", desc, "\x5c\x786e", "NG")}\n'
2259 \x6e
2259 \x6e
2260 $ hg log -R a -r 2 --template '{ifeq(r"no perso\x6e", desc, "NG", r"\x5c\x786e")}\n'
2260 $ hg log -R a -r 2 --template '{ifeq(r"no perso\x6e", desc, "NG", r"\x5c\x786e")}\n'
2261 \x5c\x786e
2261 \x5c\x786e
2262 $ hg log -R a -r 2 --template '{ifeq(desc, "no perso\x6e", "\x5c\x786e", "NG")}\n'
2262 $ hg log -R a -r 2 --template '{ifeq(desc, "no perso\x6e", "\x5c\x786e", "NG")}\n'
2263 \x6e
2263 \x6e
2264 $ hg log -R a -r 2 --template '{ifeq(desc, r"no perso\x6e", "NG", r"\x5c\x786e")}\n'
2264 $ hg log -R a -r 2 --template '{ifeq(desc, r"no perso\x6e", "NG", r"\x5c\x786e")}\n'
2265 \x5c\x786e
2265 \x5c\x786e
2266
2266
2267 $ hg log -R a -r 8 --template '{join(files, "\n")}\n'
2267 $ hg log -R a -r 8 --template '{join(files, "\n")}\n'
2268 fourth
2268 fourth
2269 second
2269 second
2270 third
2270 third
2271 $ hg log -R a -r 8 --template '{join(files, r"\n")}\n'
2271 $ hg log -R a -r 8 --template '{join(files, r"\n")}\n'
2272 fourth\nsecond\nthird
2272 fourth\nsecond\nthird
2273
2273
2274 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", "htm\x6c")}'
2274 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", "htm\x6c")}'
2275 <p>
2275 <p>
2276 1st
2276 1st
2277 </p>
2277 </p>
2278 <p>
2278 <p>
2279 2nd
2279 2nd
2280 </p>
2280 </p>
2281 $ hg log -R a -r 2 --template '{rstdoc(r"1st\n\n2nd", "html")}'
2281 $ hg log -R a -r 2 --template '{rstdoc(r"1st\n\n2nd", "html")}'
2282 <p>
2282 <p>
2283 1st\n\n2nd
2283 1st\n\n2nd
2284 </p>
2284 </p>
2285 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", r"htm\x6c")}'
2285 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", r"htm\x6c")}'
2286 1st
2286 1st
2287
2287
2288 2nd
2288 2nd
2289
2289
2290 $ hg log -R a -r 2 --template '{strip(desc, "\x6e")}\n'
2290 $ hg log -R a -r 2 --template '{strip(desc, "\x6e")}\n'
2291 o perso
2291 o perso
2292 $ hg log -R a -r 2 --template '{strip(desc, r"\x6e")}\n'
2292 $ hg log -R a -r 2 --template '{strip(desc, r"\x6e")}\n'
2293 no person
2293 no person
2294 $ hg log -R a -r 2 --template '{strip("no perso\x6e", "\x6e")}\n'
2294 $ hg log -R a -r 2 --template '{strip("no perso\x6e", "\x6e")}\n'
2295 o perso
2295 o perso
2296 $ hg log -R a -r 2 --template '{strip(r"no perso\x6e", r"\x6e")}\n'
2296 $ hg log -R a -r 2 --template '{strip(r"no perso\x6e", r"\x6e")}\n'
2297 no perso
2297 no perso
2298
2298
2299 $ hg log -R a -r 2 --template '{sub("\\x6e", "\x2d", desc)}\n'
2299 $ hg log -R a -r 2 --template '{sub("\\x6e", "\x2d", desc)}\n'
2300 -o perso-
2300 -o perso-
2301 $ hg log -R a -r 2 --template '{sub(r"\\x6e", "-", desc)}\n'
2301 $ hg log -R a -r 2 --template '{sub(r"\\x6e", "-", desc)}\n'
2302 no person
2302 no person
2303 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", desc)}\n'
2303 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", desc)}\n'
2304 \x2do perso\x2d
2304 \x2do perso\x2d
2305 $ hg log -R a -r 2 --template '{sub("n", "\x2d", "no perso\x6e")}\n'
2305 $ hg log -R a -r 2 --template '{sub("n", "\x2d", "no perso\x6e")}\n'
2306 -o perso-
2306 -o perso-
2307 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", r"no perso\x6e")}\n'
2307 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", r"no perso\x6e")}\n'
2308 \x2do perso\x6e
2308 \x2do perso\x6e
2309
2309
2310 $ hg log -R a -r 8 --template '{files % "{file}\n"}'
2310 $ hg log -R a -r 8 --template '{files % "{file}\n"}'
2311 fourth
2311 fourth
2312 second
2312 second
2313 third
2313 third
2314 $ hg log -R a -r 8 --template '{files % r"{file}\n"}\n'
2314 $ hg log -R a -r 8 --template '{files % r"{file}\n"}\n'
2315 fourth\nsecond\nthird\n
2315 fourth\nsecond\nthird\n
2316
2316
2317 Test string escaping in nested expression:
2317 Test string escaping in nested expression:
2318
2318
2319 $ hg log -R a -r 8 --template '{ifeq(r"\x6e", if("1", "\x5c\x786e"), join(files, "\x5c\x786e"))}\n'
2319 $ hg log -R a -r 8 --template '{ifeq(r"\x6e", if("1", "\x5c\x786e"), join(files, "\x5c\x786e"))}\n'
2320 fourth\x6esecond\x6ethird
2320 fourth\x6esecond\x6ethird
2321 $ hg log -R a -r 8 --template '{ifeq(if("1", r"\x6e"), "\x5c\x786e", join(files, "\x5c\x786e"))}\n'
2321 $ hg log -R a -r 8 --template '{ifeq(if("1", r"\x6e"), "\x5c\x786e", join(files, "\x5c\x786e"))}\n'
2322 fourth\x6esecond\x6ethird
2322 fourth\x6esecond\x6ethird
2323
2323
2324 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", "\x5c\x786e"))}\n'
2324 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", "\x5c\x786e"))}\n'
2325 fourth\x6esecond\x6ethird
2325 fourth\x6esecond\x6ethird
2326 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", r"\x5c\x786e"))}\n'
2326 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", r"\x5c\x786e"))}\n'
2327 fourth\x5c\x786esecond\x5c\x786ethird
2327 fourth\x5c\x786esecond\x5c\x786ethird
2328
2328
2329 $ hg log -R a -r 3:4 --template '{rev}:{sub(if("1", "\x6e"), ifeq(branch, "foo", r"\x5c\x786e", "\x5c\x786e"), desc)}\n'
2329 $ hg log -R a -r 3:4 --template '{rev}:{sub(if("1", "\x6e"), ifeq(branch, "foo", r"\x5c\x786e", "\x5c\x786e"), desc)}\n'
2330 3:\x6eo user, \x6eo domai\x6e
2330 3:\x6eo user, \x6eo domai\x6e
2331 4:\x5c\x786eew bra\x5c\x786ech
2331 4:\x5c\x786eew bra\x5c\x786ech
2332
2332
2333 Test recursive evaluation:
2333 Test recursive evaluation:
2334
2334
2335 $ hg init r
2335 $ hg init r
2336 $ cd r
2336 $ cd r
2337 $ echo a > a
2337 $ echo a > a
2338 $ hg ci -Am '{rev}'
2338 $ hg ci -Am '{rev}'
2339 adding a
2339 adding a
2340 $ hg log -r 0 --template '{if(rev, desc)}\n'
2340 $ hg log -r 0 --template '{if(rev, desc)}\n'
2341 {rev}
2341 {rev}
2342 $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n'
2342 $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n'
2343 test 0
2343 test 0
2344
2344
2345 $ hg branch -q 'text.{rev}'
2345 $ hg branch -q 'text.{rev}'
2346 $ echo aa >> aa
2346 $ echo aa >> aa
2347 $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
2347 $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
2348
2348
2349 $ hg log -l1 --template '{fill(desc, "20", author, branch)}'
2349 $ hg log -l1 --template '{fill(desc, "20", author, branch)}'
2350 {node|short}desc to
2350 {node|short}desc to
2351 text.{rev}be wrapped
2351 text.{rev}be wrapped
2352 text.{rev}desc to be
2352 text.{rev}desc to be
2353 text.{rev}wrapped (no-eol)
2353 text.{rev}wrapped (no-eol)
2354 $ hg log -l1 --template '{fill(desc, "20", "{node|short}:", "text.{rev}:")}'
2354 $ hg log -l1 --template '{fill(desc, "20", "{node|short}:", "text.{rev}:")}'
2355 bcc7ff960b8e:desc to
2355 bcc7ff960b8e:desc to
2356 text.1:be wrapped
2356 text.1:be wrapped
2357 text.1:desc to be
2357 text.1:desc to be
2358 text.1:wrapped (no-eol)
2358 text.1:wrapped (no-eol)
2359
2359
2360 $ hg log -l 1 --template '{sub(r"[0-9]", "-", author)}'
2360 $ hg log -l 1 --template '{sub(r"[0-9]", "-", author)}'
2361 {node|short} (no-eol)
2361 {node|short} (no-eol)
2362 $ hg log -l 1 --template '{sub(r"[0-9]", "-", "{node|short}")}'
2362 $ hg log -l 1 --template '{sub(r"[0-9]", "-", "{node|short}")}'
2363 bcc-ff---b-e (no-eol)
2363 bcc-ff---b-e (no-eol)
2364
2364
2365 $ cat >> .hg/hgrc <<EOF
2365 $ cat >> .hg/hgrc <<EOF
2366 > [extensions]
2366 > [extensions]
2367 > color=
2367 > color=
2368 > [color]
2368 > [color]
2369 > mode=ansi
2369 > mode=ansi
2370 > text.{rev} = red
2370 > text.{rev} = red
2371 > text.1 = green
2371 > text.1 = green
2372 > EOF
2372 > EOF
2373 $ hg log --color=always -l 1 --template '{label(branch, "text\n")}'
2373 $ hg log --color=always -l 1 --template '{label(branch, "text\n")}'
2374 \x1b[0;31mtext\x1b[0m (esc)
2374 \x1b[0;31mtext\x1b[0m (esc)
2375 $ hg log --color=always -l 1 --template '{label("text.{rev}", "text\n")}'
2375 $ hg log --color=always -l 1 --template '{label("text.{rev}", "text\n")}'
2376 \x1b[0;32mtext\x1b[0m (esc)
2376 \x1b[0;32mtext\x1b[0m (esc)
2377
2377
2378 Test branches inside if statement:
2378 Test branches inside if statement:
2379
2379
2380 $ hg log -r 0 --template '{if(branches, "yes", "no")}\n'
2380 $ hg log -r 0 --template '{if(branches, "yes", "no")}\n'
2381 no
2381 no
2382
2382
2383 Test get function:
2383 Test get function:
2384
2384
2385 $ hg log -r 0 --template '{get(extras, "branch")}\n'
2385 $ hg log -r 0 --template '{get(extras, "branch")}\n'
2386 default
2386 default
2387 $ hg log -r 0 --template '{get(files, "should_fail")}\n'
2387 $ hg log -r 0 --template '{get(files, "should_fail")}\n'
2388 hg: parse error: get() expects a dict as first argument
2388 hg: parse error: get() expects a dict as first argument
2389 [255]
2389 [255]
2390
2390
2391 Test shortest(node) function:
2391 Test shortest(node) function:
2392
2392
2393 $ echo b > b
2393 $ echo b > b
2394 $ hg ci -qAm b
2394 $ hg ci -qAm b
2395 $ hg log --template '{shortest(node)}\n'
2395 $ hg log --template '{shortest(node)}\n'
2396 e777
2396 e777
2397 bcc7
2397 bcc7
2398 f776
2398 f776
2399 $ hg log --template '{shortest(node, 10)}\n'
2399 $ hg log --template '{shortest(node, 10)}\n'
2400 e777603221
2400 e777603221
2401 bcc7ff960b
2401 bcc7ff960b
2402 f7769ec2ab
2402 f7769ec2ab
2403
2403
2404 Test pad function
2404 Test pad function
2405
2405
2406 $ hg log --template '{pad(rev, 20)} {author|user}\n'
2406 $ hg log --template '{pad(rev, 20)} {author|user}\n'
2407 2 test
2407 2 test
2408 1 {node|short}
2408 1 {node|short}
2409 0 test
2409 0 test
2410
2410
2411 $ hg log --template '{pad(rev, 20, " ", True)} {author|user}\n'
2411 $ hg log --template '{pad(rev, 20, " ", True)} {author|user}\n'
2412 2 test
2412 2 test
2413 1 {node|short}
2413 1 {node|short}
2414 0 test
2414 0 test
2415
2415
2416 $ hg log --template '{pad(rev, 20, "-", False)} {author|user}\n'
2416 $ hg log --template '{pad(rev, 20, "-", False)} {author|user}\n'
2417 2------------------- test
2417 2------------------- test
2418 1------------------- {node|short}
2418 1------------------- {node|short}
2419 0------------------- test
2419 0------------------- test
2420
2420
2421 Test ifcontains function
2421 Test ifcontains function
2422
2422
2423 $ hg log --template '{rev} {ifcontains(rev, "2 two 0", "is in the string", "is not")}\n'
2423 $ hg log --template '{rev} {ifcontains(rev, "2 two 0", "is in the string", "is not")}\n'
2424 2 is in the string
2424 2 is in the string
2425 1 is not
2425 1 is not
2426 0 is in the string
2426 0 is in the string
2427
2427
2428 $ hg log --template '{rev} {ifcontains("a", file_adds, "added a", "did not add a")}\n'
2428 $ hg log --template '{rev} {ifcontains("a", file_adds, "added a", "did not add a")}\n'
2429 2 did not add a
2429 2 did not add a
2430 1 did not add a
2430 1 did not add a
2431 0 added a
2431 0 added a
2432
2432
2433 Test revset function
2433 Test revset function
2434
2434
2435 $ hg log --template '{rev} {ifcontains(rev, revset("."), "current rev", "not current rev")}\n'
2435 $ hg log --template '{rev} {ifcontains(rev, revset("."), "current rev", "not current rev")}\n'
2436 2 current rev
2436 2 current rev
2437 1 not current rev
2437 1 not current rev
2438 0 not current rev
2438 0 not current rev
2439
2439
2440 $ hg log --template '{rev} {ifcontains(rev, revset(". + .^"), "match rev", "not match rev")}\n'
2440 $ hg log --template '{rev} {ifcontains(rev, revset(". + .^"), "match rev", "not match rev")}\n'
2441 2 match rev
2441 2 match rev
2442 1 match rev
2442 1 match rev
2443 0 not match rev
2443 0 not match rev
2444
2444
2445 $ hg log --template '{rev} Parents: {revset("parents(%s)", rev)}\n'
2445 $ hg log --template '{rev} Parents: {revset("parents(%s)", rev)}\n'
2446 2 Parents: 1
2446 2 Parents: 1
2447 1 Parents: 0
2447 1 Parents: 0
2448 0 Parents:
2448 0 Parents:
2449
2449
2450 $ cat >> .hg/hgrc <<EOF
2450 $ cat >> .hg/hgrc <<EOF
2451 > [revsetalias]
2451 > [revsetalias]
2452 > myparents(\$1) = parents(\$1)
2452 > myparents(\$1) = parents(\$1)
2453 > EOF
2453 > EOF
2454 $ hg log --template '{rev} Parents: {revset("myparents(%s)", rev)}\n'
2454 $ hg log --template '{rev} Parents: {revset("myparents(%s)", rev)}\n'
2455 2 Parents: 1
2455 2 Parents: 1
2456 1 Parents: 0
2456 1 Parents: 0
2457 0 Parents:
2457 0 Parents:
2458
2458
2459 $ hg log --template 'Rev: {rev}\n{revset("::%s", rev) % "Ancestor: {revision}\n"}\n'
2459 $ hg log --template 'Rev: {rev}\n{revset("::%s", rev) % "Ancestor: {revision}\n"}\n'
2460 Rev: 2
2460 Rev: 2
2461 Ancestor: 0
2461 Ancestor: 0
2462 Ancestor: 1
2462 Ancestor: 1
2463 Ancestor: 2
2463 Ancestor: 2
2464
2464
2465 Rev: 1
2465 Rev: 1
2466 Ancestor: 0
2466 Ancestor: 0
2467 Ancestor: 1
2467 Ancestor: 1
2468
2468
2469 Rev: 0
2469 Rev: 0
2470 Ancestor: 0
2470 Ancestor: 0
2471
2471
2472 Test current bookmark templating
2472 Test current bookmark templating
2473
2473
2474 $ hg book foo
2474 $ hg book foo
2475 $ hg book bar
2475 $ hg book bar
2476 $ hg log --template "{rev} {bookmarks % '{bookmark}{ifeq(bookmark, current, \"*\")} '}\n"
2476 $ hg log --template "{rev} {bookmarks % '{bookmark}{ifeq(bookmark, current, \"*\")} '}\n"
2477 2 bar* foo
2477 2 bar* foo
2478 1
2478 1
2479 0
2479 0
2480 $ hg log --template "{rev} {currentbookmark}\n"
2480 $ hg log --template "{rev} {currentbookmark}\n"
2481 2 bar
2481 2 bar
2482 1
2482 1
2483 0
2483 0
2484 $ hg bookmarks --inactive bar
2484 $ hg bookmarks --inactive bar
2485 $ hg log --template "{rev} {currentbookmark}\n"
2485 $ hg log --template "{rev} {currentbookmark}\n"
2486 2
2486 2
2487 1
2487 1
2488 0
2488 0
2489 $ hg book -r1 baz
2489 $ hg book -r1 baz
2490 $ hg log --template "{rev} {join(bookmarks, ' ')}\n"
2490 $ hg log --template "{rev} {join(bookmarks, ' ')}\n"
2491 2 bar foo
2491 2 bar foo
2492 1 baz
2492 1 baz
2493 0
2493 0
2494 $ hg log --template "{rev} {ifcontains('foo', bookmarks, 't', 'f')}\n"
2494 $ hg log --template "{rev} {ifcontains('foo', bookmarks, 't', 'f')}\n"
2495 2 t
2495 2 t
2496 1 f
2496 1 f
2497 0 f
2497 0 f
2498
2498
2499 Test stringify on sub expressions
2499 Test stringify on sub expressions
2500
2500
2501 $ cd ..
2501 $ cd ..
2502 $ hg log -R a -r 8 --template '{join(files, if("1", if("1", ", ")))}\n'
2502 $ hg log -R a -r 8 --template '{join(files, if("1", if("1", ", ")))}\n'
2503 fourth, second, third
2503 fourth, second, third
2504 $ hg log -R a -r 8 --template '{strip(if("1", if("1", "-abc-")), if("1", if("1", "-")))}\n'
2504 $ hg log -R a -r 8 --template '{strip(if("1", if("1", "-abc-")), if("1", if("1", "-")))}\n'
2505 abc
2505 abc
2506
2506
2507 Test splitlines
2507 Test splitlines
2508
2508
2509 $ hg log -Gv -R a --template "{splitlines(desc) % 'foo {line}\n'}"
2509 $ hg log -Gv -R a --template "{splitlines(desc) % 'foo {line}\n'}"
2510 @ foo future
2510 @ foo future
2511 |
2511 |
2512 o foo third
2512 o foo third
2513 |
2513 |
2514 o foo second
2514 o foo second
2515
2515
2516 o foo merge
2516 o foo merge
2517 |\
2517 |\
2518 | o foo new head
2518 | o foo new head
2519 | |
2519 | |
2520 o | foo new branch
2520 o | foo new branch
2521 |/
2521 |/
2522 o foo no user, no domain
2522 o foo no user, no domain
2523 |
2523 |
2524 o foo no person
2524 o foo no person
2525 |
2525 |
2526 o foo other 1
2526 o foo other 1
2527 | foo other 2
2527 | foo other 2
2528 | foo
2528 | foo
2529 | foo other 3
2529 | foo other 3
2530 o foo line 1
2530 o foo line 1
2531 foo line 2
2531 foo line 2
2532
2532
2533 Test startswith
2533 Test startswith
2534 $ hg log -Gv -R a --template "{startswith(desc)}"
2534 $ hg log -Gv -R a --template "{startswith(desc)}"
2535 hg: parse error: startswith expects two arguments
2535 hg: parse error: startswith expects two arguments
2536 [255]
2536 [255]
2537
2537
2538 $ hg log -Gv -R a --template "{startswith('line', desc)}"
2538 $ hg log -Gv -R a --template "{startswith('line', desc)}"
2539 @
2539 @
2540 |
2540 |
2541 o
2541 o
2542 |
2542 |
2543 o
2543 o
2544
2544
2545 o
2545 o
2546 |\
2546 |\
2547 | o
2547 | o
2548 | |
2548 | |
2549 o |
2549 o |
2550 |/
2550 |/
2551 o
2551 o
2552 |
2552 |
2553 o
2553 o
2554 |
2554 |
2555 o
2555 o
2556 |
2556 |
2557 o line 1
2557 o line 1
2558 line 2
2558 line 2
2559
2559
2560 Test bad template with better error message
2560 Test bad template with better error message
2561
2561
2562 $ hg log -Gv -R a --template '{desc|user()}'
2562 $ hg log -Gv -R a --template '{desc|user()}'
2563 hg: parse error: expected a symbol, got 'func'
2563 hg: parse error: expected a symbol, got 'func'
2564 [255]
2564 [255]
2565
2565
2566 Test word function (including index out of bounds graceful failure)
2566 Test word function (including index out of bounds graceful failure)
2567
2567
2568 $ hg log -Gv -R a --template "{word('1', desc)}"
2568 $ hg log -Gv -R a --template "{word('1', desc)}"
2569 @
2569 @
2570 |
2570 |
2571 o
2571 o
2572 |
2572 |
2573 o
2573 o
2574
2574
2575 o
2575 o
2576 |\
2576 |\
2577 | o head
2577 | o head
2578 | |
2578 | |
2579 o | branch
2579 o | branch
2580 |/
2580 |/
2581 o user,
2581 o user,
2582 |
2582 |
2583 o person
2583 o person
2584 |
2584 |
2585 o 1
2585 o 1
2586 |
2586 |
2587 o 1
2587 o 1
2588
2588
2589
2589
2590 Test word third parameter used as splitter
2590 Test word third parameter used as splitter
2591
2591
2592 $ hg log -Gv -R a --template "{word('0', desc, 'o')}"
2592 $ hg log -Gv -R a --template "{word('0', desc, 'o')}"
2593 @ future
2593 @ future
2594 |
2594 |
2595 o third
2595 o third
2596 |
2596 |
2597 o sec
2597 o sec
2598
2598
2599 o merge
2599 o merge
2600 |\
2600 |\
2601 | o new head
2601 | o new head
2602 | |
2602 | |
2603 o | new branch
2603 o | new branch
2604 |/
2604 |/
2605 o n
2605 o n
2606 |
2606 |
2607 o n
2607 o n
2608 |
2608 |
2609 o
2609 o
2610 |
2610 |
2611 o line 1
2611 o line 1
2612 line 2
2612 line 2
2613
2613
2614 Test word error messages for not enough and too many arguments
2614 Test word error messages for not enough and too many arguments
2615
2615
2616 $ hg log -Gv -R a --template "{word('0')}"
2616 $ hg log -Gv -R a --template "{word('0')}"
2617 hg: parse error: word expects two or three arguments, got 1
2617 hg: parse error: word expects two or three arguments, got 1
2618 [255]
2618 [255]
2619
2619
2620 $ hg log -Gv -R a --template "{word('0', desc, 'o', 'h', 'b', 'o', 'y')}"
2620 $ hg log -Gv -R a --template "{word('0', desc, 'o', 'h', 'b', 'o', 'y')}"
2621 hg: parse error: word expects two or three arguments, got 7
2621 hg: parse error: word expects two or three arguments, got 7
2622 [255]
2622 [255]
2623
2624 Test word for invalid numbers
2625
2626 $ hg log -Gv -R a --template "{word(2, desc)}"
2627 hg: parse error: Use strings like '3' for numbers passed to word function
2628 [255]
General Comments 0
You need to be logged in to leave comments. Login now