##// END OF EJS Templates
templater: support using templates with non-standard names from map file...
Alexander Plavin -
r19770:0361163e default
parent child Browse files
Show More
@@ -1,576 +1,585
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 sys, os, re
9 import sys, os, re
10 import util, config, templatefilters, parser, error
10 import util, config, templatefilters, parser, error
11 import types
11 import types
12 import minirst
12 import minirst
13
13
14 # template parsing
14 # template parsing
15
15
16 elements = {
16 elements = {
17 "(": (20, ("group", 1, ")"), ("func", 1, ")")),
17 "(": (20, ("group", 1, ")"), ("func", 1, ")")),
18 ",": (2, None, ("list", 2)),
18 ",": (2, None, ("list", 2)),
19 "|": (5, None, ("|", 5)),
19 "|": (5, None, ("|", 5)),
20 "%": (6, None, ("%", 6)),
20 "%": (6, None, ("%", 6)),
21 ")": (0, None, None),
21 ")": (0, None, None),
22 "symbol": (0, ("symbol",), None),
22 "symbol": (0, ("symbol",), None),
23 "string": (0, ("string",), None),
23 "string": (0, ("string",), None),
24 "end": (0, None, None),
24 "end": (0, None, None),
25 }
25 }
26
26
27 def tokenizer(data):
27 def tokenizer(data):
28 program, start, end = data
28 program, start, end = data
29 pos = start
29 pos = start
30 while pos < end:
30 while pos < end:
31 c = program[pos]
31 c = program[pos]
32 if c.isspace(): # skip inter-token whitespace
32 if c.isspace(): # skip inter-token whitespace
33 pass
33 pass
34 elif c in "(,)%|": # handle simple operators
34 elif c in "(,)%|": # handle simple operators
35 yield (c, None, pos)
35 yield (c, None, pos)
36 elif (c in '"\'' or c == 'r' and
36 elif (c in '"\'' or c == 'r' and
37 program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
37 program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
38 if c == 'r':
38 if c == 'r':
39 pos += 1
39 pos += 1
40 c = program[pos]
40 c = program[pos]
41 decode = False
41 decode = False
42 else:
42 else:
43 decode = True
43 decode = True
44 pos += 1
44 pos += 1
45 s = pos
45 s = pos
46 while pos < end: # find closing quote
46 while pos < end: # find closing quote
47 d = program[pos]
47 d = program[pos]
48 if decode and d == '\\': # skip over escaped characters
48 if decode and d == '\\': # skip over escaped characters
49 pos += 2
49 pos += 2
50 continue
50 continue
51 if d == c:
51 if d == c:
52 if not decode:
52 if not decode:
53 yield ('string', program[s:pos].replace('\\', r'\\'), s)
53 yield ('string', program[s:pos].replace('\\', r'\\'), s)
54 break
54 break
55 yield ('string', program[s:pos].decode('string-escape'), s)
55 yield ('string', program[s:pos].decode('string-escape'), s)
56 break
56 break
57 pos += 1
57 pos += 1
58 else:
58 else:
59 raise error.ParseError(_("unterminated string"), s)
59 raise error.ParseError(_("unterminated string"), s)
60 elif c.isalnum() or c in '_':
60 elif c.isalnum() or c in '_':
61 s = pos
61 s = pos
62 pos += 1
62 pos += 1
63 while pos < end: # find end of symbol
63 while pos < end: # find end of symbol
64 d = program[pos]
64 d = program[pos]
65 if not (d.isalnum() or d == "_"):
65 if not (d.isalnum() or d == "_"):
66 break
66 break
67 pos += 1
67 pos += 1
68 sym = program[s:pos]
68 sym = program[s:pos]
69 yield ('symbol', sym, s)
69 yield ('symbol', sym, s)
70 pos -= 1
70 pos -= 1
71 elif c == '}':
71 elif c == '}':
72 pos += 1
72 pos += 1
73 break
73 break
74 else:
74 else:
75 raise error.ParseError(_("syntax error"), pos)
75 raise error.ParseError(_("syntax error"), pos)
76 pos += 1
76 pos += 1
77 yield ('end', None, pos)
77 yield ('end', None, pos)
78
78
79 def compiletemplate(tmpl, context):
79 def compiletemplate(tmpl, context):
80 parsed = []
80 parsed = []
81 pos, stop = 0, len(tmpl)
81 pos, stop = 0, len(tmpl)
82 p = parser.parser(tokenizer, elements)
82 p = parser.parser(tokenizer, elements)
83
83
84 while pos < stop:
84 while pos < stop:
85 n = tmpl.find('{', pos)
85 n = tmpl.find('{', pos)
86 if n < 0:
86 if n < 0:
87 parsed.append(("string", tmpl[pos:]))
87 parsed.append(("string", tmpl[pos:]))
88 break
88 break
89 if n > 0 and tmpl[n - 1] == '\\':
89 if n > 0 and tmpl[n - 1] == '\\':
90 # escaped
90 # escaped
91 parsed.append(("string", tmpl[pos:n - 1] + "{"))
91 parsed.append(("string", tmpl[pos:n - 1] + "{"))
92 pos = n + 1
92 pos = n + 1
93 continue
93 continue
94 if n > pos:
94 if n > pos:
95 parsed.append(("string", tmpl[pos:n]))
95 parsed.append(("string", tmpl[pos:n]))
96
96
97 pd = [tmpl, n + 1, stop]
97 pd = [tmpl, n + 1, stop]
98 parseres, pos = p.parse(pd)
98 parseres, pos = p.parse(pd)
99 parsed.append(parseres)
99 parsed.append(parseres)
100
100
101 return [compileexp(e, context) for e in parsed]
101 return [compileexp(e, context) for e in parsed]
102
102
103 def compileexp(exp, context):
103 def compileexp(exp, context):
104 t = exp[0]
104 t = exp[0]
105 if t in methods:
105 if t in methods:
106 return methods[t](exp, context)
106 return methods[t](exp, context)
107 raise error.ParseError(_("unknown method '%s'") % t)
107 raise error.ParseError(_("unknown method '%s'") % t)
108
108
109 # template evaluation
109 # template evaluation
110
110
111 def getsymbol(exp):
111 def getsymbol(exp):
112 if exp[0] == 'symbol':
112 if exp[0] == 'symbol':
113 return exp[1]
113 return exp[1]
114 raise error.ParseError(_("expected a symbol"))
114 raise error.ParseError(_("expected a symbol"))
115
115
116 def getlist(x):
116 def getlist(x):
117 if not x:
117 if not x:
118 return []
118 return []
119 if x[0] == 'list':
119 if x[0] == 'list':
120 return getlist(x[1]) + [x[2]]
120 return getlist(x[1]) + [x[2]]
121 return [x]
121 return [x]
122
122
123 def getfilter(exp, context):
123 def getfilter(exp, context):
124 f = getsymbol(exp)
124 f = getsymbol(exp)
125 if f not in context._filters:
125 if f not in context._filters:
126 raise error.ParseError(_("unknown function '%s'") % f)
126 raise error.ParseError(_("unknown function '%s'") % f)
127 return context._filters[f]
127 return context._filters[f]
128
128
129 def gettemplate(exp, context):
129 def gettemplate(exp, context):
130 if exp[0] == 'string':
130 if exp[0] == 'string':
131 return compiletemplate(exp[1], context)
131 return compiletemplate(exp[1], context)
132 if exp[0] == 'symbol':
132 if exp[0] == 'symbol':
133 return context._load(exp[1])
133 return context._load(exp[1])
134 raise error.ParseError(_("expected template specifier"))
134 raise error.ParseError(_("expected template specifier"))
135
135
136 def runstring(context, mapping, data):
136 def runstring(context, mapping, data):
137 return data
137 return data
138
138
139 def runsymbol(context, mapping, key):
139 def runsymbol(context, mapping, key):
140 v = mapping.get(key)
140 v = mapping.get(key)
141 if v is None:
141 if v is None:
142 v = context._defaults.get(key, '')
142 v = context._defaults.get(key)
143 if v is None:
144 try:
145 v = context.process(key, mapping)
146 except TemplateNotFound:
147 v = ''
143 if util.safehasattr(v, '__call__'):
148 if util.safehasattr(v, '__call__'):
144 return v(**mapping)
149 return v(**mapping)
145 if isinstance(v, types.GeneratorType):
150 if isinstance(v, types.GeneratorType):
146 v = list(v)
151 v = list(v)
147 mapping[key] = v
152 mapping[key] = v
148 return v
153 return v
149 return v
154 return v
150
155
151 def buildfilter(exp, context):
156 def buildfilter(exp, context):
152 func, data = compileexp(exp[1], context)
157 func, data = compileexp(exp[1], context)
153 filt = getfilter(exp[2], context)
158 filt = getfilter(exp[2], context)
154 return (runfilter, (func, data, filt))
159 return (runfilter, (func, data, filt))
155
160
156 def runfilter(context, mapping, data):
161 def runfilter(context, mapping, data):
157 func, data, filt = data
162 func, data, filt = data
158 try:
163 try:
159 return filt(func(context, mapping, data))
164 return filt(func(context, mapping, data))
160 except (ValueError, AttributeError, TypeError):
165 except (ValueError, AttributeError, TypeError):
161 if isinstance(data, tuple):
166 if isinstance(data, tuple):
162 dt = data[1]
167 dt = data[1]
163 else:
168 else:
164 dt = data
169 dt = data
165 raise util.Abort(_("template filter '%s' is not compatible with "
170 raise util.Abort(_("template filter '%s' is not compatible with "
166 "keyword '%s'") % (filt.func_name, dt))
171 "keyword '%s'") % (filt.func_name, dt))
167
172
168 def buildmap(exp, context):
173 def buildmap(exp, context):
169 func, data = compileexp(exp[1], context)
174 func, data = compileexp(exp[1], context)
170 ctmpl = gettemplate(exp[2], context)
175 ctmpl = gettemplate(exp[2], context)
171 return (runmap, (func, data, ctmpl))
176 return (runmap, (func, data, ctmpl))
172
177
173 def runtemplate(context, mapping, template):
178 def runtemplate(context, mapping, template):
174 for func, data in template:
179 for func, data in template:
175 yield func(context, mapping, data)
180 yield func(context, mapping, data)
176
181
177 def runmap(context, mapping, data):
182 def runmap(context, mapping, data):
178 func, data, ctmpl = data
183 func, data, ctmpl = data
179 d = func(context, mapping, data)
184 d = func(context, mapping, data)
180 if util.safehasattr(d, '__call__'):
185 if util.safehasattr(d, '__call__'):
181 d = d()
186 d = d()
182
187
183 lm = mapping.copy()
188 lm = mapping.copy()
184
189
185 for i in d:
190 for i in d:
186 if isinstance(i, dict):
191 if isinstance(i, dict):
187 lm.update(i)
192 lm.update(i)
188 lm['originalnode'] = mapping.get('node')
193 lm['originalnode'] = mapping.get('node')
189 yield runtemplate(context, lm, ctmpl)
194 yield runtemplate(context, lm, ctmpl)
190 else:
195 else:
191 # v is not an iterable of dicts, this happen when 'key'
196 # v is not an iterable of dicts, this happen when 'key'
192 # has been fully expanded already and format is useless.
197 # has been fully expanded already and format is useless.
193 # If so, return the expanded value.
198 # If so, return the expanded value.
194 yield i
199 yield i
195
200
196 def buildfunc(exp, context):
201 def buildfunc(exp, context):
197 n = getsymbol(exp[1])
202 n = getsymbol(exp[1])
198 args = [compileexp(x, context) for x in getlist(exp[2])]
203 args = [compileexp(x, context) for x in getlist(exp[2])]
199 if n in funcs:
204 if n in funcs:
200 f = funcs[n]
205 f = funcs[n]
201 return (f, args)
206 return (f, args)
202 if n in context._filters:
207 if n in context._filters:
203 if len(args) != 1:
208 if len(args) != 1:
204 raise error.ParseError(_("filter %s expects one argument") % n)
209 raise error.ParseError(_("filter %s expects one argument") % n)
205 f = context._filters[n]
210 f = context._filters[n]
206 return (runfilter, (args[0][0], args[0][1], f))
211 return (runfilter, (args[0][0], args[0][1], f))
207
212
208 def date(context, mapping, args):
213 def date(context, mapping, args):
209 if not (1 <= len(args) <= 2):
214 if not (1 <= len(args) <= 2):
210 raise error.ParseError(_("date expects one or two arguments"))
215 raise error.ParseError(_("date expects one or two arguments"))
211
216
212 date = args[0][0](context, mapping, args[0][1])
217 date = args[0][0](context, mapping, args[0][1])
213 if len(args) == 2:
218 if len(args) == 2:
214 fmt = stringify(args[1][0](context, mapping, args[1][1]))
219 fmt = stringify(args[1][0](context, mapping, args[1][1]))
215 return util.datestr(date, fmt)
220 return util.datestr(date, fmt)
216 return util.datestr(date)
221 return util.datestr(date)
217
222
218 def fill(context, mapping, args):
223 def fill(context, mapping, args):
219 if not (1 <= len(args) <= 4):
224 if not (1 <= len(args) <= 4):
220 raise error.ParseError(_("fill expects one to four arguments"))
225 raise error.ParseError(_("fill expects one to four arguments"))
221
226
222 text = stringify(args[0][0](context, mapping, args[0][1]))
227 text = stringify(args[0][0](context, mapping, args[0][1]))
223 width = 76
228 width = 76
224 initindent = ''
229 initindent = ''
225 hangindent = ''
230 hangindent = ''
226 if 2 <= len(args) <= 4:
231 if 2 <= len(args) <= 4:
227 try:
232 try:
228 width = int(stringify(args[1][0](context, mapping, args[1][1])))
233 width = int(stringify(args[1][0](context, mapping, args[1][1])))
229 except ValueError:
234 except ValueError:
230 raise error.ParseError(_("fill expects an integer width"))
235 raise error.ParseError(_("fill expects an integer width"))
231 try:
236 try:
232 initindent = stringify(args[2][0](context, mapping, args[2][1]))
237 initindent = stringify(args[2][0](context, mapping, args[2][1]))
233 initindent = stringify(runtemplate(context, mapping,
238 initindent = stringify(runtemplate(context, mapping,
234 compiletemplate(initindent, context)))
239 compiletemplate(initindent, context)))
235 hangindent = stringify(args[3][0](context, mapping, args[3][1]))
240 hangindent = stringify(args[3][0](context, mapping, args[3][1]))
236 hangindent = stringify(runtemplate(context, mapping,
241 hangindent = stringify(runtemplate(context, mapping,
237 compiletemplate(hangindent, context)))
242 compiletemplate(hangindent, context)))
238 except IndexError:
243 except IndexError:
239 pass
244 pass
240
245
241 return templatefilters.fill(text, width, initindent, hangindent)
246 return templatefilters.fill(text, width, initindent, hangindent)
242
247
243 def get(context, mapping, args):
248 def get(context, mapping, args):
244 if len(args) != 2:
249 if len(args) != 2:
245 # i18n: "get" is a keyword
250 # i18n: "get" is a keyword
246 raise error.ParseError(_("get() expects two arguments"))
251 raise error.ParseError(_("get() expects two arguments"))
247
252
248 dictarg = args[0][0](context, mapping, args[0][1])
253 dictarg = args[0][0](context, mapping, args[0][1])
249 if not util.safehasattr(dictarg, 'get'):
254 if not util.safehasattr(dictarg, 'get'):
250 # i18n: "get" is a keyword
255 # i18n: "get" is a keyword
251 raise error.ParseError(_("get() expects a dict as first argument"))
256 raise error.ParseError(_("get() expects a dict as first argument"))
252
257
253 key = args[1][0](context, mapping, args[1][1])
258 key = args[1][0](context, mapping, args[1][1])
254 yield dictarg.get(key)
259 yield dictarg.get(key)
255
260
256 def if_(context, mapping, args):
261 def if_(context, mapping, args):
257 if not (2 <= len(args) <= 3):
262 if not (2 <= len(args) <= 3):
258 # i18n: "if" is a keyword
263 # i18n: "if" is a keyword
259 raise error.ParseError(_("if expects two or three arguments"))
264 raise error.ParseError(_("if expects two or three arguments"))
260
265
261 test = stringify(args[0][0](context, mapping, args[0][1]))
266 test = stringify(args[0][0](context, mapping, args[0][1]))
262 if test:
267 if test:
263 t = stringify(args[1][0](context, mapping, args[1][1]))
268 t = stringify(args[1][0](context, mapping, args[1][1]))
264 yield runtemplate(context, mapping, compiletemplate(t, context))
269 yield runtemplate(context, mapping, compiletemplate(t, context))
265 elif len(args) == 3:
270 elif len(args) == 3:
266 t = stringify(args[2][0](context, mapping, args[2][1]))
271 t = stringify(args[2][0](context, mapping, args[2][1]))
267 yield runtemplate(context, mapping, compiletemplate(t, context))
272 yield runtemplate(context, mapping, compiletemplate(t, context))
268
273
269 def ifeq(context, mapping, args):
274 def ifeq(context, mapping, args):
270 if not (3 <= len(args) <= 4):
275 if not (3 <= len(args) <= 4):
271 # i18n: "ifeq" is a keyword
276 # i18n: "ifeq" is a keyword
272 raise error.ParseError(_("ifeq expects three or four arguments"))
277 raise error.ParseError(_("ifeq expects three or four arguments"))
273
278
274 test = stringify(args[0][0](context, mapping, args[0][1]))
279 test = stringify(args[0][0](context, mapping, args[0][1]))
275 match = stringify(args[1][0](context, mapping, args[1][1]))
280 match = stringify(args[1][0](context, mapping, args[1][1]))
276 if test == match:
281 if test == match:
277 t = stringify(args[2][0](context, mapping, args[2][1]))
282 t = stringify(args[2][0](context, mapping, args[2][1]))
278 yield runtemplate(context, mapping, compiletemplate(t, context))
283 yield runtemplate(context, mapping, compiletemplate(t, context))
279 elif len(args) == 4:
284 elif len(args) == 4:
280 t = stringify(args[3][0](context, mapping, args[3][1]))
285 t = stringify(args[3][0](context, mapping, args[3][1]))
281 yield runtemplate(context, mapping, compiletemplate(t, context))
286 yield runtemplate(context, mapping, compiletemplate(t, context))
282
287
283 def join(context, mapping, args):
288 def join(context, mapping, args):
284 if not (1 <= len(args) <= 2):
289 if not (1 <= len(args) <= 2):
285 # i18n: "join" is a keyword
290 # i18n: "join" is a keyword
286 raise error.ParseError(_("join expects one or two arguments"))
291 raise error.ParseError(_("join expects one or two arguments"))
287
292
288 joinset = args[0][0](context, mapping, args[0][1])
293 joinset = args[0][0](context, mapping, args[0][1])
289 if util.safehasattr(joinset, '__call__'):
294 if util.safehasattr(joinset, '__call__'):
290 jf = joinset.joinfmt
295 jf = joinset.joinfmt
291 joinset = [jf(x) for x in joinset()]
296 joinset = [jf(x) for x in joinset()]
292
297
293 joiner = " "
298 joiner = " "
294 if len(args) > 1:
299 if len(args) > 1:
295 joiner = args[1][0](context, mapping, args[1][1])
300 joiner = args[1][0](context, mapping, args[1][1])
296
301
297 first = True
302 first = True
298 for x in joinset:
303 for x in joinset:
299 if first:
304 if first:
300 first = False
305 first = False
301 else:
306 else:
302 yield joiner
307 yield joiner
303 yield x
308 yield x
304
309
305 def label(context, mapping, args):
310 def label(context, mapping, args):
306 if len(args) != 2:
311 if len(args) != 2:
307 # i18n: "label" is a keyword
312 # i18n: "label" is a keyword
308 raise error.ParseError(_("label expects two arguments"))
313 raise error.ParseError(_("label expects two arguments"))
309
314
310 # ignore args[0] (the label string) since this is supposed to be a a no-op
315 # ignore args[0] (the label string) since this is supposed to be a a no-op
311 t = stringify(args[1][0](context, mapping, args[1][1]))
316 t = stringify(args[1][0](context, mapping, args[1][1]))
312 yield runtemplate(context, mapping, compiletemplate(t, context))
317 yield runtemplate(context, mapping, compiletemplate(t, context))
313
318
314 def rstdoc(context, mapping, args):
319 def rstdoc(context, mapping, args):
315 if len(args) != 2:
320 if len(args) != 2:
316 # i18n: "rstdoc" is a keyword
321 # i18n: "rstdoc" is a keyword
317 raise error.ParseError(_("rstdoc expects two arguments"))
322 raise error.ParseError(_("rstdoc expects two arguments"))
318
323
319 text = stringify(args[0][0](context, mapping, args[0][1]))
324 text = stringify(args[0][0](context, mapping, args[0][1]))
320 style = stringify(args[1][0](context, mapping, args[1][1]))
325 style = stringify(args[1][0](context, mapping, args[1][1]))
321
326
322 return minirst.format(text, style=style, keep=['verbose'])
327 return minirst.format(text, style=style, keep=['verbose'])
323
328
324 def strip(context, mapping, args):
329 def strip(context, mapping, args):
325 if not (1 <= len(args) <= 2):
330 if not (1 <= len(args) <= 2):
326 raise error.ParseError(_("strip expects one or two arguments"))
331 raise error.ParseError(_("strip expects one or two arguments"))
327
332
328 text = args[0][0](context, mapping, args[0][1])
333 text = args[0][0](context, mapping, args[0][1])
329 if len(args) == 2:
334 if len(args) == 2:
330 chars = args[1][0](context, mapping, args[1][1])
335 chars = args[1][0](context, mapping, args[1][1])
331 return text.strip(chars)
336 return text.strip(chars)
332 return text.strip()
337 return text.strip()
333
338
334 def sub(context, mapping, args):
339 def sub(context, mapping, args):
335 if len(args) != 3:
340 if len(args) != 3:
336 # i18n: "sub" is a keyword
341 # i18n: "sub" is a keyword
337 raise error.ParseError(_("sub expects three arguments"))
342 raise error.ParseError(_("sub expects three arguments"))
338
343
339 pat = stringify(args[0][0](context, mapping, args[0][1]))
344 pat = stringify(args[0][0](context, mapping, args[0][1]))
340 rpl = stringify(args[1][0](context, mapping, args[1][1]))
345 rpl = stringify(args[1][0](context, mapping, args[1][1]))
341 src = stringify(args[2][0](context, mapping, args[2][1]))
346 src = stringify(args[2][0](context, mapping, args[2][1]))
342 src = stringify(runtemplate(context, mapping,
347 src = stringify(runtemplate(context, mapping,
343 compiletemplate(src, context)))
348 compiletemplate(src, context)))
344 yield re.sub(pat, rpl, src)
349 yield re.sub(pat, rpl, src)
345
350
346 methods = {
351 methods = {
347 "string": lambda e, c: (runstring, e[1]),
352 "string": lambda e, c: (runstring, e[1]),
348 "symbol": lambda e, c: (runsymbol, e[1]),
353 "symbol": lambda e, c: (runsymbol, e[1]),
349 "group": lambda e, c: compileexp(e[1], c),
354 "group": lambda e, c: compileexp(e[1], c),
350 # ".": buildmember,
355 # ".": buildmember,
351 "|": buildfilter,
356 "|": buildfilter,
352 "%": buildmap,
357 "%": buildmap,
353 "func": buildfunc,
358 "func": buildfunc,
354 }
359 }
355
360
356 funcs = {
361 funcs = {
357 "date": date,
362 "date": date,
358 "fill": fill,
363 "fill": fill,
359 "get": get,
364 "get": get,
360 "if": if_,
365 "if": if_,
361 "ifeq": ifeq,
366 "ifeq": ifeq,
362 "join": join,
367 "join": join,
363 "label": label,
368 "label": label,
364 "rstdoc": rstdoc,
369 "rstdoc": rstdoc,
365 "strip": strip,
370 "strip": strip,
366 "sub": sub,
371 "sub": sub,
367 }
372 }
368
373
369 # template engine
374 # template engine
370
375
371 path = ['templates', '../templates']
376 path = ['templates', '../templates']
372 stringify = templatefilters.stringify
377 stringify = templatefilters.stringify
373
378
374 def _flatten(thing):
379 def _flatten(thing):
375 '''yield a single stream from a possibly nested set of iterators'''
380 '''yield a single stream from a possibly nested set of iterators'''
376 if isinstance(thing, str):
381 if isinstance(thing, str):
377 yield thing
382 yield thing
378 elif not util.safehasattr(thing, '__iter__'):
383 elif not util.safehasattr(thing, '__iter__'):
379 if thing is not None:
384 if thing is not None:
380 yield str(thing)
385 yield str(thing)
381 else:
386 else:
382 for i in thing:
387 for i in thing:
383 if isinstance(i, str):
388 if isinstance(i, str):
384 yield i
389 yield i
385 elif not util.safehasattr(i, '__iter__'):
390 elif not util.safehasattr(i, '__iter__'):
386 if i is not None:
391 if i is not None:
387 yield str(i)
392 yield str(i)
388 elif i is not None:
393 elif i is not None:
389 for j in _flatten(i):
394 for j in _flatten(i):
390 yield j
395 yield j
391
396
392 def parsestring(s, quoted=True):
397 def parsestring(s, quoted=True):
393 '''parse a string using simple c-like syntax.
398 '''parse a string using simple c-like syntax.
394 string must be in quotes if quoted is True.'''
399 string must be in quotes if quoted is True.'''
395 if quoted:
400 if quoted:
396 if len(s) < 2 or s[0] != s[-1]:
401 if len(s) < 2 or s[0] != s[-1]:
397 raise SyntaxError(_('unmatched quotes'))
402 raise SyntaxError(_('unmatched quotes'))
398 return s[1:-1].decode('string_escape')
403 return s[1:-1].decode('string_escape')
399
404
400 return s.decode('string_escape')
405 return s.decode('string_escape')
401
406
402 class engine(object):
407 class engine(object):
403 '''template expansion engine.
408 '''template expansion engine.
404
409
405 template expansion works like this. a map file contains key=value
410 template expansion works like this. a map file contains key=value
406 pairs. if value is quoted, it is treated as string. otherwise, it
411 pairs. if value is quoted, it is treated as string. otherwise, it
407 is treated as name of template file.
412 is treated as name of template file.
408
413
409 templater is asked to expand a key in map. it looks up key, and
414 templater is asked to expand a key in map. it looks up key, and
410 looks for strings like this: {foo}. it expands {foo} by looking up
415 looks for strings like this: {foo}. it expands {foo} by looking up
411 foo in map, and substituting it. expansion is recursive: it stops
416 foo in map, and substituting it. expansion is recursive: it stops
412 when there is no more {foo} to replace.
417 when there is no more {foo} to replace.
413
418
414 expansion also allows formatting and filtering.
419 expansion also allows formatting and filtering.
415
420
416 format uses key to expand each item in list. syntax is
421 format uses key to expand each item in list. syntax is
417 {key%format}.
422 {key%format}.
418
423
419 filter uses function to transform value. syntax is
424 filter uses function to transform value. syntax is
420 {key|filter1|filter2|...}.'''
425 {key|filter1|filter2|...}.'''
421
426
422 def __init__(self, loader, filters={}, defaults={}):
427 def __init__(self, loader, filters={}, defaults={}):
423 self._loader = loader
428 self._loader = loader
424 self._filters = filters
429 self._filters = filters
425 self._defaults = defaults
430 self._defaults = defaults
426 self._cache = {}
431 self._cache = {}
427
432
428 def _load(self, t):
433 def _load(self, t):
429 '''load, parse, and cache a template'''
434 '''load, parse, and cache a template'''
430 if t not in self._cache:
435 if t not in self._cache:
431 self._cache[t] = compiletemplate(self._loader(t), self)
436 self._cache[t] = compiletemplate(self._loader(t), self)
432 return self._cache[t]
437 return self._cache[t]
433
438
434 def process(self, t, mapping):
439 def process(self, t, mapping):
435 '''Perform expansion. t is name of map element to expand.
440 '''Perform expansion. t is name of map element to expand.
436 mapping contains added elements for use during expansion. Is a
441 mapping contains added elements for use during expansion. Is a
437 generator.'''
442 generator.'''
438 return _flatten(runtemplate(self, mapping, self._load(t)))
443 return _flatten(runtemplate(self, mapping, self._load(t)))
439
444
440 engines = {'default': engine}
445 engines = {'default': engine}
441
446
442 def stylelist():
447 def stylelist():
443 path = templatepath()[0]
448 path = templatepath()[0]
444 dirlist = os.listdir(path)
449 dirlist = os.listdir(path)
445 stylelist = []
450 stylelist = []
446 for file in dirlist:
451 for file in dirlist:
447 split = file.split(".")
452 split = file.split(".")
448 if split[0] == "map-cmdline":
453 if split[0] == "map-cmdline":
449 stylelist.append(split[1])
454 stylelist.append(split[1])
450 return ", ".join(sorted(stylelist))
455 return ", ".join(sorted(stylelist))
451
456
457 class TemplateNotFound(util.Abort):
458 pass
459
452 class templater(object):
460 class templater(object):
453
461
454 def __init__(self, mapfile, filters={}, defaults={}, cache={},
462 def __init__(self, mapfile, filters={}, defaults={}, cache={},
455 minchunk=1024, maxchunk=65536):
463 minchunk=1024, maxchunk=65536):
456 '''set up template engine.
464 '''set up template engine.
457 mapfile is name of file to read map definitions from.
465 mapfile is name of file to read map definitions from.
458 filters is dict of functions. each transforms a value into another.
466 filters is dict of functions. each transforms a value into another.
459 defaults is dict of default map definitions.'''
467 defaults is dict of default map definitions.'''
460 self.mapfile = mapfile or 'template'
468 self.mapfile = mapfile or 'template'
461 self.cache = cache.copy()
469 self.cache = cache.copy()
462 self.map = {}
470 self.map = {}
463 self.base = (mapfile and os.path.dirname(mapfile)) or ''
471 self.base = (mapfile and os.path.dirname(mapfile)) or ''
464 self.filters = templatefilters.filters.copy()
472 self.filters = templatefilters.filters.copy()
465 self.filters.update(filters)
473 self.filters.update(filters)
466 self.defaults = defaults
474 self.defaults = defaults
467 self.minchunk, self.maxchunk = minchunk, maxchunk
475 self.minchunk, self.maxchunk = minchunk, maxchunk
468 self.ecache = {}
476 self.ecache = {}
469
477
470 if not mapfile:
478 if not mapfile:
471 return
479 return
472 if not os.path.exists(mapfile):
480 if not os.path.exists(mapfile):
473 raise util.Abort(_("style '%s' not found") % mapfile,
481 raise util.Abort(_("style '%s' not found") % mapfile,
474 hint=_("available styles: %s") % stylelist())
482 hint=_("available styles: %s") % stylelist())
475
483
476 conf = config.config()
484 conf = config.config()
477 conf.read(mapfile)
485 conf.read(mapfile)
478
486
479 for key, val in conf[''].items():
487 for key, val in conf[''].items():
480 if not val:
488 if not val:
481 raise SyntaxError(_('%s: missing value') % conf.source('', key))
489 raise SyntaxError(_('%s: missing value') % conf.source('', key))
482 if val[0] in "'\"":
490 if val[0] in "'\"":
483 try:
491 try:
484 self.cache[key] = parsestring(val)
492 self.cache[key] = parsestring(val)
485 except SyntaxError, inst:
493 except SyntaxError, inst:
486 raise SyntaxError('%s: %s' %
494 raise SyntaxError('%s: %s' %
487 (conf.source('', key), inst.args[0]))
495 (conf.source('', key), inst.args[0]))
488 else:
496 else:
489 val = 'default', val
497 val = 'default', val
490 if ':' in val[1]:
498 if ':' in val[1]:
491 val = val[1].split(':', 1)
499 val = val[1].split(':', 1)
492 self.map[key] = val[0], os.path.join(self.base, val[1])
500 self.map[key] = val[0], os.path.join(self.base, val[1])
493
501
494 def __contains__(self, key):
502 def __contains__(self, key):
495 return key in self.cache or key in self.map
503 return key in self.cache or key in self.map
496
504
497 def load(self, t):
505 def load(self, t):
498 '''Get the template for the given template name. Use a local cache.'''
506 '''Get the template for the given template name. Use a local cache.'''
499 if t not in self.cache:
507 if t not in self.cache:
500 try:
508 try:
501 self.cache[t] = util.readfile(self.map[t][1])
509 self.cache[t] = util.readfile(self.map[t][1])
502 except KeyError, inst:
510 except KeyError, inst:
503 raise util.Abort(_('"%s" not in template map') % inst.args[0])
511 raise TemplateNotFound(_('"%s" not in template map') %
512 inst.args[0])
504 except IOError, inst:
513 except IOError, inst:
505 raise IOError(inst.args[0], _('template file %s: %s') %
514 raise IOError(inst.args[0], _('template file %s: %s') %
506 (self.map[t][1], inst.args[1]))
515 (self.map[t][1], inst.args[1]))
507 return self.cache[t]
516 return self.cache[t]
508
517
509 def __call__(self, t, **mapping):
518 def __call__(self, t, **mapping):
510 ttype = t in self.map and self.map[t][0] or 'default'
519 ttype = t in self.map and self.map[t][0] or 'default'
511 if ttype not in self.ecache:
520 if ttype not in self.ecache:
512 self.ecache[ttype] = engines[ttype](self.load,
521 self.ecache[ttype] = engines[ttype](self.load,
513 self.filters, self.defaults)
522 self.filters, self.defaults)
514 proc = self.ecache[ttype]
523 proc = self.ecache[ttype]
515
524
516 stream = proc.process(t, mapping)
525 stream = proc.process(t, mapping)
517 if self.minchunk:
526 if self.minchunk:
518 stream = util.increasingchunks(stream, min=self.minchunk,
527 stream = util.increasingchunks(stream, min=self.minchunk,
519 max=self.maxchunk)
528 max=self.maxchunk)
520 return stream
529 return stream
521
530
522 def templatepath(name=None):
531 def templatepath(name=None):
523 '''return location of template file or directory (if no name).
532 '''return location of template file or directory (if no name).
524 returns None if not found.'''
533 returns None if not found.'''
525 normpaths = []
534 normpaths = []
526
535
527 # executable version (py2exe) doesn't support __file__
536 # executable version (py2exe) doesn't support __file__
528 if util.mainfrozen():
537 if util.mainfrozen():
529 module = sys.executable
538 module = sys.executable
530 else:
539 else:
531 module = __file__
540 module = __file__
532 for f in path:
541 for f in path:
533 if f.startswith('/'):
542 if f.startswith('/'):
534 p = f
543 p = f
535 else:
544 else:
536 fl = f.split('/')
545 fl = f.split('/')
537 p = os.path.join(os.path.dirname(module), *fl)
546 p = os.path.join(os.path.dirname(module), *fl)
538 if name:
547 if name:
539 p = os.path.join(p, name)
548 p = os.path.join(p, name)
540 if name and os.path.exists(p):
549 if name and os.path.exists(p):
541 return os.path.normpath(p)
550 return os.path.normpath(p)
542 elif os.path.isdir(p):
551 elif os.path.isdir(p):
543 normpaths.append(os.path.normpath(p))
552 normpaths.append(os.path.normpath(p))
544
553
545 return normpaths
554 return normpaths
546
555
547 def stylemap(styles, paths=None):
556 def stylemap(styles, paths=None):
548 """Return path to mapfile for a given style.
557 """Return path to mapfile for a given style.
549
558
550 Searches mapfile in the following locations:
559 Searches mapfile in the following locations:
551 1. templatepath/style/map
560 1. templatepath/style/map
552 2. templatepath/map-style
561 2. templatepath/map-style
553 3. templatepath/map
562 3. templatepath/map
554 """
563 """
555
564
556 if paths is None:
565 if paths is None:
557 paths = templatepath()
566 paths = templatepath()
558 elif isinstance(paths, str):
567 elif isinstance(paths, str):
559 paths = [paths]
568 paths = [paths]
560
569
561 if isinstance(styles, str):
570 if isinstance(styles, str):
562 styles = [styles]
571 styles = [styles]
563
572
564 for style in styles:
573 for style in styles:
565 if not style:
574 if not style:
566 continue
575 continue
567 locations = [os.path.join(style, 'map'), 'map-' + style]
576 locations = [os.path.join(style, 'map'), 'map-' + style]
568 locations.append('map')
577 locations.append('map')
569
578
570 for path in paths:
579 for path in paths:
571 for location in locations:
580 for location in locations:
572 mapfile = os.path.join(path, location)
581 mapfile = os.path.join(path, location)
573 if os.path.isfile(mapfile):
582 if os.path.isfile(mapfile):
574 return style, mapfile
583 return style, mapfile
575
584
576 raise RuntimeError("No hgweb templates found in %r" % paths)
585 raise RuntimeError("No hgweb templates found in %r" % paths)
@@ -1,1566 +1,1588
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 --template '{file_copies % "{source} -> {name}\n"}' -r .
48 $ hg log --template '{file_copies % "{source} -> {name}\n"}' -r .
49 second -> fourth
49 second -> fourth
50
50
51 Quoting for ui.logtemplate
51 Quoting for ui.logtemplate
52
52
53 $ hg tip --config "ui.logtemplate={rev}\n"
53 $ hg tip --config "ui.logtemplate={rev}\n"
54 8
54 8
55 $ hg tip --config "ui.logtemplate='{rev}\n'"
55 $ hg tip --config "ui.logtemplate='{rev}\n'"
56 8
56 8
57 $ hg tip --config 'ui.logtemplate="{rev}\n"'
57 $ hg tip --config 'ui.logtemplate="{rev}\n"'
58 8
58 8
59
59
60 Make sure user/global hgrc does not affect tests
60 Make sure user/global hgrc does not affect tests
61
61
62 $ echo '[ui]' > .hg/hgrc
62 $ echo '[ui]' > .hg/hgrc
63 $ echo 'logtemplate =' >> .hg/hgrc
63 $ echo 'logtemplate =' >> .hg/hgrc
64 $ echo 'style =' >> .hg/hgrc
64 $ echo 'style =' >> .hg/hgrc
65
65
66 Default style is like normal output:
66 Default style is like normal output:
67
67
68 $ hg log > log.out
68 $ hg log > log.out
69 $ hg log --style default > style.out
69 $ hg log --style default > style.out
70 $ cmp log.out style.out || diff -u log.out style.out
70 $ cmp log.out style.out || diff -u log.out style.out
71
71
72 $ hg log -v > log.out
72 $ hg log -v > log.out
73 $ hg log -v --style default > style.out
73 $ hg log -v --style default > style.out
74 $ cmp log.out style.out || diff -u log.out style.out
74 $ cmp log.out style.out || diff -u log.out style.out
75
75
76 $ hg log --debug > log.out
76 $ hg log --debug > log.out
77 $ hg log --debug --style default > style.out
77 $ hg log --debug --style default > style.out
78 $ cmp log.out style.out || diff -u log.out style.out
78 $ cmp log.out style.out || diff -u log.out style.out
79
79
80 Revision with no copies (used to print a traceback):
80 Revision with no copies (used to print a traceback):
81
81
82 $ hg tip -v --template '\n'
82 $ hg tip -v --template '\n'
83
83
84
84
85 Compact style works:
85 Compact style works:
86
86
87 $ hg log --style compact
87 $ hg log --style compact
88 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
88 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
89 third
89 third
90
90
91 7:-1 29114dbae42b 1970-01-12 13:46 +0000 user
91 7:-1 29114dbae42b 1970-01-12 13:46 +0000 user
92 second
92 second
93
93
94 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
94 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
95 merge
95 merge
96
96
97 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
97 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
98 new head
98 new head
99
99
100 4 bbe44766e73d 1970-01-17 04:53 +0000 person
100 4 bbe44766e73d 1970-01-17 04:53 +0000 person
101 new branch
101 new branch
102
102
103 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
103 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
104 no user, no domain
104 no user, no domain
105
105
106 2 97054abb4ab8 1970-01-14 21:20 +0000 other
106 2 97054abb4ab8 1970-01-14 21:20 +0000 other
107 no person
107 no person
108
108
109 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
109 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
110 other 1
110 other 1
111
111
112 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
112 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
113 line 1
113 line 1
114
114
115
115
116 $ hg log -v --style compact
116 $ hg log -v --style compact
117 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
117 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
118 third
118 third
119
119
120 7:-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
120 7:-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
121 second
121 second
122
122
123 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
123 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
124 merge
124 merge
125
125
126 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
126 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
127 new head
127 new head
128
128
129 4 bbe44766e73d 1970-01-17 04:53 +0000 person
129 4 bbe44766e73d 1970-01-17 04:53 +0000 person
130 new branch
130 new branch
131
131
132 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
132 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
133 no user, no domain
133 no user, no domain
134
134
135 2 97054abb4ab8 1970-01-14 21:20 +0000 other@place
135 2 97054abb4ab8 1970-01-14 21:20 +0000 other@place
136 no person
136 no person
137
137
138 1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
138 1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
139 other 1
139 other 1
140 other 2
140 other 2
141
141
142 other 3
142 other 3
143
143
144 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
144 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
145 line 1
145 line 1
146 line 2
146 line 2
147
147
148
148
149 $ hg log --debug --style compact
149 $ hg log --debug --style compact
150 8[tip]:7,-1 95c24699272e 2020-01-01 10:01 +0000 test
150 8[tip]:7,-1 95c24699272e 2020-01-01 10:01 +0000 test
151 third
151 third
152
152
153 7:-1,-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
153 7:-1,-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
154 second
154 second
155
155
156 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
156 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
157 merge
157 merge
158
158
159 5:3,-1 13207e5a10d9 1970-01-18 08:40 +0000 person
159 5:3,-1 13207e5a10d9 1970-01-18 08:40 +0000 person
160 new head
160 new head
161
161
162 4:3,-1 bbe44766e73d 1970-01-17 04:53 +0000 person
162 4:3,-1 bbe44766e73d 1970-01-17 04:53 +0000 person
163 new branch
163 new branch
164
164
165 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
165 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
166 no user, no domain
166 no user, no domain
167
167
168 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other@place
168 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other@place
169 no person
169 no person
170
170
171 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
171 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
172 other 1
172 other 1
173 other 2
173 other 2
174
174
175 other 3
175 other 3
176
176
177 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
177 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
178 line 1
178 line 1
179 line 2
179 line 2
180
180
181
181
182 Test xml styles:
182 Test xml styles:
183
183
184 $ hg log --style xml
184 $ hg log --style xml
185 <?xml version="1.0"?>
185 <?xml version="1.0"?>
186 <log>
186 <log>
187 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
187 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
188 <tag>tip</tag>
188 <tag>tip</tag>
189 <author email="test">test</author>
189 <author email="test">test</author>
190 <date>2020-01-01T10:01:00+00:00</date>
190 <date>2020-01-01T10:01:00+00:00</date>
191 <msg xml:space="preserve">third</msg>
191 <msg xml:space="preserve">third</msg>
192 </logentry>
192 </logentry>
193 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
193 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
194 <parent revision="-1" node="0000000000000000000000000000000000000000" />
194 <parent revision="-1" node="0000000000000000000000000000000000000000" />
195 <author email="user@hostname">User Name</author>
195 <author email="user@hostname">User Name</author>
196 <date>1970-01-12T13:46:40+00:00</date>
196 <date>1970-01-12T13:46:40+00:00</date>
197 <msg xml:space="preserve">second</msg>
197 <msg xml:space="preserve">second</msg>
198 </logentry>
198 </logentry>
199 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
199 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
200 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
200 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
201 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
201 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
202 <author email="person">person</author>
202 <author email="person">person</author>
203 <date>1970-01-18T08:40:01+00:00</date>
203 <date>1970-01-18T08:40:01+00:00</date>
204 <msg xml:space="preserve">merge</msg>
204 <msg xml:space="preserve">merge</msg>
205 </logentry>
205 </logentry>
206 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
206 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
207 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
207 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
208 <author email="person">person</author>
208 <author email="person">person</author>
209 <date>1970-01-18T08:40:00+00:00</date>
209 <date>1970-01-18T08:40:00+00:00</date>
210 <msg xml:space="preserve">new head</msg>
210 <msg xml:space="preserve">new head</msg>
211 </logentry>
211 </logentry>
212 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
212 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
213 <branch>foo</branch>
213 <branch>foo</branch>
214 <author email="person">person</author>
214 <author email="person">person</author>
215 <date>1970-01-17T04:53:20+00:00</date>
215 <date>1970-01-17T04:53:20+00:00</date>
216 <msg xml:space="preserve">new branch</msg>
216 <msg xml:space="preserve">new branch</msg>
217 </logentry>
217 </logentry>
218 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
218 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
219 <author email="person">person</author>
219 <author email="person">person</author>
220 <date>1970-01-16T01:06:40+00:00</date>
220 <date>1970-01-16T01:06:40+00:00</date>
221 <msg xml:space="preserve">no user, no domain</msg>
221 <msg xml:space="preserve">no user, no domain</msg>
222 </logentry>
222 </logentry>
223 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
223 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
224 <author email="other@place">other</author>
224 <author email="other@place">other</author>
225 <date>1970-01-14T21:20:00+00:00</date>
225 <date>1970-01-14T21:20:00+00:00</date>
226 <msg xml:space="preserve">no person</msg>
226 <msg xml:space="preserve">no person</msg>
227 </logentry>
227 </logentry>
228 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
228 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
229 <author email="other@place">A. N. Other</author>
229 <author email="other@place">A. N. Other</author>
230 <date>1970-01-13T17:33:20+00:00</date>
230 <date>1970-01-13T17:33:20+00:00</date>
231 <msg xml:space="preserve">other 1
231 <msg xml:space="preserve">other 1
232 other 2
232 other 2
233
233
234 other 3</msg>
234 other 3</msg>
235 </logentry>
235 </logentry>
236 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
236 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
237 <author email="user@hostname">User Name</author>
237 <author email="user@hostname">User Name</author>
238 <date>1970-01-12T13:46:40+00:00</date>
238 <date>1970-01-12T13:46:40+00:00</date>
239 <msg xml:space="preserve">line 1
239 <msg xml:space="preserve">line 1
240 line 2</msg>
240 line 2</msg>
241 </logentry>
241 </logentry>
242 </log>
242 </log>
243
243
244 $ hg log -v --style xml
244 $ hg log -v --style xml
245 <?xml version="1.0"?>
245 <?xml version="1.0"?>
246 <log>
246 <log>
247 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
247 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
248 <tag>tip</tag>
248 <tag>tip</tag>
249 <author email="test">test</author>
249 <author email="test">test</author>
250 <date>2020-01-01T10:01:00+00:00</date>
250 <date>2020-01-01T10:01:00+00:00</date>
251 <msg xml:space="preserve">third</msg>
251 <msg xml:space="preserve">third</msg>
252 <paths>
252 <paths>
253 <path action="A">fourth</path>
253 <path action="A">fourth</path>
254 <path action="A">third</path>
254 <path action="A">third</path>
255 <path action="R">second</path>
255 <path action="R">second</path>
256 </paths>
256 </paths>
257 <copies>
257 <copies>
258 <copy source="second">fourth</copy>
258 <copy source="second">fourth</copy>
259 </copies>
259 </copies>
260 </logentry>
260 </logentry>
261 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
261 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
262 <parent revision="-1" node="0000000000000000000000000000000000000000" />
262 <parent revision="-1" node="0000000000000000000000000000000000000000" />
263 <author email="user@hostname">User Name</author>
263 <author email="user@hostname">User Name</author>
264 <date>1970-01-12T13:46:40+00:00</date>
264 <date>1970-01-12T13:46:40+00:00</date>
265 <msg xml:space="preserve">second</msg>
265 <msg xml:space="preserve">second</msg>
266 <paths>
266 <paths>
267 <path action="A">second</path>
267 <path action="A">second</path>
268 </paths>
268 </paths>
269 </logentry>
269 </logentry>
270 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
270 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
271 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
271 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
272 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
272 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
273 <author email="person">person</author>
273 <author email="person">person</author>
274 <date>1970-01-18T08:40:01+00:00</date>
274 <date>1970-01-18T08:40:01+00:00</date>
275 <msg xml:space="preserve">merge</msg>
275 <msg xml:space="preserve">merge</msg>
276 <paths>
276 <paths>
277 </paths>
277 </paths>
278 </logentry>
278 </logentry>
279 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
279 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
280 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
280 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
281 <author email="person">person</author>
281 <author email="person">person</author>
282 <date>1970-01-18T08:40:00+00:00</date>
282 <date>1970-01-18T08:40:00+00:00</date>
283 <msg xml:space="preserve">new head</msg>
283 <msg xml:space="preserve">new head</msg>
284 <paths>
284 <paths>
285 <path action="A">d</path>
285 <path action="A">d</path>
286 </paths>
286 </paths>
287 </logentry>
287 </logentry>
288 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
288 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
289 <branch>foo</branch>
289 <branch>foo</branch>
290 <author email="person">person</author>
290 <author email="person">person</author>
291 <date>1970-01-17T04:53:20+00:00</date>
291 <date>1970-01-17T04:53:20+00:00</date>
292 <msg xml:space="preserve">new branch</msg>
292 <msg xml:space="preserve">new branch</msg>
293 <paths>
293 <paths>
294 </paths>
294 </paths>
295 </logentry>
295 </logentry>
296 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
296 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
297 <author email="person">person</author>
297 <author email="person">person</author>
298 <date>1970-01-16T01:06:40+00:00</date>
298 <date>1970-01-16T01:06:40+00:00</date>
299 <msg xml:space="preserve">no user, no domain</msg>
299 <msg xml:space="preserve">no user, no domain</msg>
300 <paths>
300 <paths>
301 <path action="M">c</path>
301 <path action="M">c</path>
302 </paths>
302 </paths>
303 </logentry>
303 </logentry>
304 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
304 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
305 <author email="other@place">other</author>
305 <author email="other@place">other</author>
306 <date>1970-01-14T21:20:00+00:00</date>
306 <date>1970-01-14T21:20:00+00:00</date>
307 <msg xml:space="preserve">no person</msg>
307 <msg xml:space="preserve">no person</msg>
308 <paths>
308 <paths>
309 <path action="A">c</path>
309 <path action="A">c</path>
310 </paths>
310 </paths>
311 </logentry>
311 </logentry>
312 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
312 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
313 <author email="other@place">A. N. Other</author>
313 <author email="other@place">A. N. Other</author>
314 <date>1970-01-13T17:33:20+00:00</date>
314 <date>1970-01-13T17:33:20+00:00</date>
315 <msg xml:space="preserve">other 1
315 <msg xml:space="preserve">other 1
316 other 2
316 other 2
317
317
318 other 3</msg>
318 other 3</msg>
319 <paths>
319 <paths>
320 <path action="A">b</path>
320 <path action="A">b</path>
321 </paths>
321 </paths>
322 </logentry>
322 </logentry>
323 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
323 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
324 <author email="user@hostname">User Name</author>
324 <author email="user@hostname">User Name</author>
325 <date>1970-01-12T13:46:40+00:00</date>
325 <date>1970-01-12T13:46:40+00:00</date>
326 <msg xml:space="preserve">line 1
326 <msg xml:space="preserve">line 1
327 line 2</msg>
327 line 2</msg>
328 <paths>
328 <paths>
329 <path action="A">a</path>
329 <path action="A">a</path>
330 </paths>
330 </paths>
331 </logentry>
331 </logentry>
332 </log>
332 </log>
333
333
334 $ hg log --debug --style xml
334 $ hg log --debug --style xml
335 <?xml version="1.0"?>
335 <?xml version="1.0"?>
336 <log>
336 <log>
337 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
337 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
338 <tag>tip</tag>
338 <tag>tip</tag>
339 <parent revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453" />
339 <parent revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453" />
340 <parent revision="-1" node="0000000000000000000000000000000000000000" />
340 <parent revision="-1" node="0000000000000000000000000000000000000000" />
341 <author email="test">test</author>
341 <author email="test">test</author>
342 <date>2020-01-01T10:01:00+00:00</date>
342 <date>2020-01-01T10:01:00+00:00</date>
343 <msg xml:space="preserve">third</msg>
343 <msg xml:space="preserve">third</msg>
344 <paths>
344 <paths>
345 <path action="A">fourth</path>
345 <path action="A">fourth</path>
346 <path action="A">third</path>
346 <path action="A">third</path>
347 <path action="R">second</path>
347 <path action="R">second</path>
348 </paths>
348 </paths>
349 <copies>
349 <copies>
350 <copy source="second">fourth</copy>
350 <copy source="second">fourth</copy>
351 </copies>
351 </copies>
352 <extra key="branch">default</extra>
352 <extra key="branch">default</extra>
353 </logentry>
353 </logentry>
354 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
354 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
355 <parent revision="-1" node="0000000000000000000000000000000000000000" />
355 <parent revision="-1" node="0000000000000000000000000000000000000000" />
356 <parent revision="-1" node="0000000000000000000000000000000000000000" />
356 <parent revision="-1" node="0000000000000000000000000000000000000000" />
357 <author email="user@hostname">User Name</author>
357 <author email="user@hostname">User Name</author>
358 <date>1970-01-12T13:46:40+00:00</date>
358 <date>1970-01-12T13:46:40+00:00</date>
359 <msg xml:space="preserve">second</msg>
359 <msg xml:space="preserve">second</msg>
360 <paths>
360 <paths>
361 <path action="A">second</path>
361 <path action="A">second</path>
362 </paths>
362 </paths>
363 <extra key="branch">default</extra>
363 <extra key="branch">default</extra>
364 </logentry>
364 </logentry>
365 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
365 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
366 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
366 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
367 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
367 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
368 <author email="person">person</author>
368 <author email="person">person</author>
369 <date>1970-01-18T08:40:01+00:00</date>
369 <date>1970-01-18T08:40:01+00:00</date>
370 <msg xml:space="preserve">merge</msg>
370 <msg xml:space="preserve">merge</msg>
371 <paths>
371 <paths>
372 </paths>
372 </paths>
373 <extra key="branch">default</extra>
373 <extra key="branch">default</extra>
374 </logentry>
374 </logentry>
375 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
375 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
376 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
376 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
377 <parent revision="-1" node="0000000000000000000000000000000000000000" />
377 <parent revision="-1" node="0000000000000000000000000000000000000000" />
378 <author email="person">person</author>
378 <author email="person">person</author>
379 <date>1970-01-18T08:40:00+00:00</date>
379 <date>1970-01-18T08:40:00+00:00</date>
380 <msg xml:space="preserve">new head</msg>
380 <msg xml:space="preserve">new head</msg>
381 <paths>
381 <paths>
382 <path action="A">d</path>
382 <path action="A">d</path>
383 </paths>
383 </paths>
384 <extra key="branch">default</extra>
384 <extra key="branch">default</extra>
385 </logentry>
385 </logentry>
386 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
386 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
387 <branch>foo</branch>
387 <branch>foo</branch>
388 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
388 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
389 <parent revision="-1" node="0000000000000000000000000000000000000000" />
389 <parent revision="-1" node="0000000000000000000000000000000000000000" />
390 <author email="person">person</author>
390 <author email="person">person</author>
391 <date>1970-01-17T04:53:20+00:00</date>
391 <date>1970-01-17T04:53:20+00:00</date>
392 <msg xml:space="preserve">new branch</msg>
392 <msg xml:space="preserve">new branch</msg>
393 <paths>
393 <paths>
394 </paths>
394 </paths>
395 <extra key="branch">foo</extra>
395 <extra key="branch">foo</extra>
396 </logentry>
396 </logentry>
397 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
397 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
398 <parent revision="2" node="97054abb4ab824450e9164180baf491ae0078465" />
398 <parent revision="2" node="97054abb4ab824450e9164180baf491ae0078465" />
399 <parent revision="-1" node="0000000000000000000000000000000000000000" />
399 <parent revision="-1" node="0000000000000000000000000000000000000000" />
400 <author email="person">person</author>
400 <author email="person">person</author>
401 <date>1970-01-16T01:06:40+00:00</date>
401 <date>1970-01-16T01:06:40+00:00</date>
402 <msg xml:space="preserve">no user, no domain</msg>
402 <msg xml:space="preserve">no user, no domain</msg>
403 <paths>
403 <paths>
404 <path action="M">c</path>
404 <path action="M">c</path>
405 </paths>
405 </paths>
406 <extra key="branch">default</extra>
406 <extra key="branch">default</extra>
407 </logentry>
407 </logentry>
408 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
408 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
409 <parent revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965" />
409 <parent revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965" />
410 <parent revision="-1" node="0000000000000000000000000000000000000000" />
410 <parent revision="-1" node="0000000000000000000000000000000000000000" />
411 <author email="other@place">other</author>
411 <author email="other@place">other</author>
412 <date>1970-01-14T21:20:00+00:00</date>
412 <date>1970-01-14T21:20:00+00:00</date>
413 <msg xml:space="preserve">no person</msg>
413 <msg xml:space="preserve">no person</msg>
414 <paths>
414 <paths>
415 <path action="A">c</path>
415 <path action="A">c</path>
416 </paths>
416 </paths>
417 <extra key="branch">default</extra>
417 <extra key="branch">default</extra>
418 </logentry>
418 </logentry>
419 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
419 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
420 <parent revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f" />
420 <parent revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f" />
421 <parent revision="-1" node="0000000000000000000000000000000000000000" />
421 <parent revision="-1" node="0000000000000000000000000000000000000000" />
422 <author email="other@place">A. N. Other</author>
422 <author email="other@place">A. N. Other</author>
423 <date>1970-01-13T17:33:20+00:00</date>
423 <date>1970-01-13T17:33:20+00:00</date>
424 <msg xml:space="preserve">other 1
424 <msg xml:space="preserve">other 1
425 other 2
425 other 2
426
426
427 other 3</msg>
427 other 3</msg>
428 <paths>
428 <paths>
429 <path action="A">b</path>
429 <path action="A">b</path>
430 </paths>
430 </paths>
431 <extra key="branch">default</extra>
431 <extra key="branch">default</extra>
432 </logentry>
432 </logentry>
433 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
433 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
434 <parent revision="-1" node="0000000000000000000000000000000000000000" />
434 <parent revision="-1" node="0000000000000000000000000000000000000000" />
435 <parent revision="-1" node="0000000000000000000000000000000000000000" />
435 <parent revision="-1" node="0000000000000000000000000000000000000000" />
436 <author email="user@hostname">User Name</author>
436 <author email="user@hostname">User Name</author>
437 <date>1970-01-12T13:46:40+00:00</date>
437 <date>1970-01-12T13:46:40+00:00</date>
438 <msg xml:space="preserve">line 1
438 <msg xml:space="preserve">line 1
439 line 2</msg>
439 line 2</msg>
440 <paths>
440 <paths>
441 <path action="A">a</path>
441 <path action="A">a</path>
442 </paths>
442 </paths>
443 <extra key="branch">default</extra>
443 <extra key="branch">default</extra>
444 </logentry>
444 </logentry>
445 </log>
445 </log>
446
446
447
447
448 Error if style not readable:
448 Error if style not readable:
449
449
450 #if unix-permissions
450 #if unix-permissions
451 $ touch q
451 $ touch q
452 $ chmod 0 q
452 $ chmod 0 q
453 $ hg log --style ./q
453 $ hg log --style ./q
454 abort: Permission denied: ./q
454 abort: Permission denied: ./q
455 [255]
455 [255]
456 #endif
456 #endif
457
457
458 Error if no style:
458 Error if no style:
459
459
460 $ hg log --style notexist
460 $ hg log --style notexist
461 abort: style 'notexist' not found
461 abort: style 'notexist' not found
462 (available styles: bisect, changelog, compact, default, phases, xml)
462 (available styles: bisect, changelog, compact, default, phases, xml)
463 [255]
463 [255]
464
464
465 Error if style missing key:
465 Error if style missing key:
466
466
467 $ echo 'q = q' > t
467 $ echo 'q = q' > t
468 $ hg log --style ./t
468 $ hg log --style ./t
469 abort: "changeset" not in template map
469 abort: "changeset" not in template map
470 [255]
470 [255]
471
471
472 Error if style missing value:
472 Error if style missing value:
473
473
474 $ echo 'changeset =' > t
474 $ echo 'changeset =' > t
475 $ hg log --style t
475 $ hg log --style t
476 abort: t:1: missing value
476 abort: t:1: missing value
477 [255]
477 [255]
478
478
479 Error if include fails:
479 Error if include fails:
480
480
481 $ echo 'changeset = q' >> t
481 $ echo 'changeset = q' >> t
482 #if unix-permissions
482 #if unix-permissions
483 $ hg log --style ./t
483 $ hg log --style ./t
484 abort: template file ./q: Permission denied
484 abort: template file ./q: Permission denied
485 [255]
485 [255]
486 $ rm q
486 $ rm q
487 #endif
487 #endif
488
488
489 Include works:
489 Include works:
490
490
491 $ echo '{rev}' > q
491 $ echo '{rev}' > q
492 $ hg log --style ./t
492 $ hg log --style ./t
493 8
493 8
494 7
494 7
495 6
495 6
496 5
496 5
497 4
497 4
498 3
498 3
499 2
499 2
500 1
500 1
501 0
501 0
502
502
503 Missing non-standard names give no error (backward compatibility):
504
505 $ echo "changeset = '{c}'" > t
506 $ hg log --style ./t
507
508 Defining non-standard name works:
509
510 $ cat <<EOF > t
511 > changeset = '{c}'
512 > c = q
513 > EOF
514 $ hg log --style ./t
515 8
516 7
517 6
518 5
519 4
520 3
521 2
522 1
523 0
524
503 ui.style works:
525 ui.style works:
504
526
505 $ echo '[ui]' > .hg/hgrc
527 $ echo '[ui]' > .hg/hgrc
506 $ echo 'style = t' >> .hg/hgrc
528 $ echo 'style = t' >> .hg/hgrc
507 $ hg log
529 $ hg log
508 8
530 8
509 7
531 7
510 6
532 6
511 5
533 5
512 4
534 4
513 3
535 3
514 2
536 2
515 1
537 1
516 0
538 0
517
539
518
540
519 Issue338:
541 Issue338:
520
542
521 $ hg log --style=changelog > changelog
543 $ hg log --style=changelog > changelog
522
544
523 $ cat changelog
545 $ cat changelog
524 2020-01-01 test <test>
546 2020-01-01 test <test>
525
547
526 * fourth, second, third:
548 * fourth, second, third:
527 third
549 third
528 [95c24699272e] [tip]
550 [95c24699272e] [tip]
529
551
530 1970-01-12 User Name <user@hostname>
552 1970-01-12 User Name <user@hostname>
531
553
532 * second:
554 * second:
533 second
555 second
534 [29114dbae42b]
556 [29114dbae42b]
535
557
536 1970-01-18 person <person>
558 1970-01-18 person <person>
537
559
538 * merge
560 * merge
539 [d41e714fe50d]
561 [d41e714fe50d]
540
562
541 * d:
563 * d:
542 new head
564 new head
543 [13207e5a10d9]
565 [13207e5a10d9]
544
566
545 1970-01-17 person <person>
567 1970-01-17 person <person>
546
568
547 * new branch
569 * new branch
548 [bbe44766e73d] <foo>
570 [bbe44766e73d] <foo>
549
571
550 1970-01-16 person <person>
572 1970-01-16 person <person>
551
573
552 * c:
574 * c:
553 no user, no domain
575 no user, no domain
554 [10e46f2dcbf4]
576 [10e46f2dcbf4]
555
577
556 1970-01-14 other <other@place>
578 1970-01-14 other <other@place>
557
579
558 * c:
580 * c:
559 no person
581 no person
560 [97054abb4ab8]
582 [97054abb4ab8]
561
583
562 1970-01-13 A. N. Other <other@place>
584 1970-01-13 A. N. Other <other@place>
563
585
564 * b:
586 * b:
565 other 1 other 2
587 other 1 other 2
566
588
567 other 3
589 other 3
568 [b608e9d1a3f0]
590 [b608e9d1a3f0]
569
591
570 1970-01-12 User Name <user@hostname>
592 1970-01-12 User Name <user@hostname>
571
593
572 * a:
594 * a:
573 line 1 line 2
595 line 1 line 2
574 [1e4e1b8f71e0]
596 [1e4e1b8f71e0]
575
597
576
598
577 Issue2130: xml output for 'hg heads' is malformed
599 Issue2130: xml output for 'hg heads' is malformed
578
600
579 $ hg heads --style changelog
601 $ hg heads --style changelog
580 2020-01-01 test <test>
602 2020-01-01 test <test>
581
603
582 * fourth, second, third:
604 * fourth, second, third:
583 third
605 third
584 [95c24699272e] [tip]
606 [95c24699272e] [tip]
585
607
586 1970-01-18 person <person>
608 1970-01-18 person <person>
587
609
588 * merge
610 * merge
589 [d41e714fe50d]
611 [d41e714fe50d]
590
612
591 1970-01-17 person <person>
613 1970-01-17 person <person>
592
614
593 * new branch
615 * new branch
594 [bbe44766e73d] <foo>
616 [bbe44766e73d] <foo>
595
617
596
618
597 Keys work:
619 Keys work:
598
620
599 $ for key in author branch branches date desc file_adds file_dels file_mods \
621 $ for key in author branch branches date desc file_adds file_dels file_mods \
600 > file_copies file_copies_switch files \
622 > file_copies file_copies_switch files \
601 > manifest node parents rev tags diffstat extras \
623 > manifest node parents rev tags diffstat extras \
602 > p1rev p2rev p1node p2node; do
624 > p1rev p2rev p1node p2node; do
603 > for mode in '' --verbose --debug; do
625 > for mode in '' --verbose --debug; do
604 > hg log $mode --template "$key$mode: {$key}\n"
626 > hg log $mode --template "$key$mode: {$key}\n"
605 > done
627 > done
606 > done
628 > done
607 author: test
629 author: test
608 author: User Name <user@hostname>
630 author: User Name <user@hostname>
609 author: person
631 author: person
610 author: person
632 author: person
611 author: person
633 author: person
612 author: person
634 author: person
613 author: other@place
635 author: other@place
614 author: A. N. Other <other@place>
636 author: A. N. Other <other@place>
615 author: User Name <user@hostname>
637 author: User Name <user@hostname>
616 author--verbose: test
638 author--verbose: test
617 author--verbose: User Name <user@hostname>
639 author--verbose: User Name <user@hostname>
618 author--verbose: person
640 author--verbose: person
619 author--verbose: person
641 author--verbose: person
620 author--verbose: person
642 author--verbose: person
621 author--verbose: person
643 author--verbose: person
622 author--verbose: other@place
644 author--verbose: other@place
623 author--verbose: A. N. Other <other@place>
645 author--verbose: A. N. Other <other@place>
624 author--verbose: User Name <user@hostname>
646 author--verbose: User Name <user@hostname>
625 author--debug: test
647 author--debug: test
626 author--debug: User Name <user@hostname>
648 author--debug: User Name <user@hostname>
627 author--debug: person
649 author--debug: person
628 author--debug: person
650 author--debug: person
629 author--debug: person
651 author--debug: person
630 author--debug: person
652 author--debug: person
631 author--debug: other@place
653 author--debug: other@place
632 author--debug: A. N. Other <other@place>
654 author--debug: A. N. Other <other@place>
633 author--debug: User Name <user@hostname>
655 author--debug: User Name <user@hostname>
634 branch: default
656 branch: default
635 branch: default
657 branch: default
636 branch: default
658 branch: default
637 branch: default
659 branch: default
638 branch: foo
660 branch: foo
639 branch: default
661 branch: default
640 branch: default
662 branch: default
641 branch: default
663 branch: default
642 branch: default
664 branch: default
643 branch--verbose: default
665 branch--verbose: default
644 branch--verbose: default
666 branch--verbose: default
645 branch--verbose: default
667 branch--verbose: default
646 branch--verbose: default
668 branch--verbose: default
647 branch--verbose: foo
669 branch--verbose: foo
648 branch--verbose: default
670 branch--verbose: default
649 branch--verbose: default
671 branch--verbose: default
650 branch--verbose: default
672 branch--verbose: default
651 branch--verbose: default
673 branch--verbose: default
652 branch--debug: default
674 branch--debug: default
653 branch--debug: default
675 branch--debug: default
654 branch--debug: default
676 branch--debug: default
655 branch--debug: default
677 branch--debug: default
656 branch--debug: foo
678 branch--debug: foo
657 branch--debug: default
679 branch--debug: default
658 branch--debug: default
680 branch--debug: default
659 branch--debug: default
681 branch--debug: default
660 branch--debug: default
682 branch--debug: default
661 branches:
683 branches:
662 branches:
684 branches:
663 branches:
685 branches:
664 branches:
686 branches:
665 branches: foo
687 branches: foo
666 branches:
688 branches:
667 branches:
689 branches:
668 branches:
690 branches:
669 branches:
691 branches:
670 branches--verbose:
692 branches--verbose:
671 branches--verbose:
693 branches--verbose:
672 branches--verbose:
694 branches--verbose:
673 branches--verbose:
695 branches--verbose:
674 branches--verbose: foo
696 branches--verbose: foo
675 branches--verbose:
697 branches--verbose:
676 branches--verbose:
698 branches--verbose:
677 branches--verbose:
699 branches--verbose:
678 branches--verbose:
700 branches--verbose:
679 branches--debug:
701 branches--debug:
680 branches--debug:
702 branches--debug:
681 branches--debug:
703 branches--debug:
682 branches--debug:
704 branches--debug:
683 branches--debug: foo
705 branches--debug: foo
684 branches--debug:
706 branches--debug:
685 branches--debug:
707 branches--debug:
686 branches--debug:
708 branches--debug:
687 branches--debug:
709 branches--debug:
688 date: 1577872860.00
710 date: 1577872860.00
689 date: 1000000.00
711 date: 1000000.00
690 date: 1500001.00
712 date: 1500001.00
691 date: 1500000.00
713 date: 1500000.00
692 date: 1400000.00
714 date: 1400000.00
693 date: 1300000.00
715 date: 1300000.00
694 date: 1200000.00
716 date: 1200000.00
695 date: 1100000.00
717 date: 1100000.00
696 date: 1000000.00
718 date: 1000000.00
697 date--verbose: 1577872860.00
719 date--verbose: 1577872860.00
698 date--verbose: 1000000.00
720 date--verbose: 1000000.00
699 date--verbose: 1500001.00
721 date--verbose: 1500001.00
700 date--verbose: 1500000.00
722 date--verbose: 1500000.00
701 date--verbose: 1400000.00
723 date--verbose: 1400000.00
702 date--verbose: 1300000.00
724 date--verbose: 1300000.00
703 date--verbose: 1200000.00
725 date--verbose: 1200000.00
704 date--verbose: 1100000.00
726 date--verbose: 1100000.00
705 date--verbose: 1000000.00
727 date--verbose: 1000000.00
706 date--debug: 1577872860.00
728 date--debug: 1577872860.00
707 date--debug: 1000000.00
729 date--debug: 1000000.00
708 date--debug: 1500001.00
730 date--debug: 1500001.00
709 date--debug: 1500000.00
731 date--debug: 1500000.00
710 date--debug: 1400000.00
732 date--debug: 1400000.00
711 date--debug: 1300000.00
733 date--debug: 1300000.00
712 date--debug: 1200000.00
734 date--debug: 1200000.00
713 date--debug: 1100000.00
735 date--debug: 1100000.00
714 date--debug: 1000000.00
736 date--debug: 1000000.00
715 desc: third
737 desc: third
716 desc: second
738 desc: second
717 desc: merge
739 desc: merge
718 desc: new head
740 desc: new head
719 desc: new branch
741 desc: new branch
720 desc: no user, no domain
742 desc: no user, no domain
721 desc: no person
743 desc: no person
722 desc: other 1
744 desc: other 1
723 other 2
745 other 2
724
746
725 other 3
747 other 3
726 desc: line 1
748 desc: line 1
727 line 2
749 line 2
728 desc--verbose: third
750 desc--verbose: third
729 desc--verbose: second
751 desc--verbose: second
730 desc--verbose: merge
752 desc--verbose: merge
731 desc--verbose: new head
753 desc--verbose: new head
732 desc--verbose: new branch
754 desc--verbose: new branch
733 desc--verbose: no user, no domain
755 desc--verbose: no user, no domain
734 desc--verbose: no person
756 desc--verbose: no person
735 desc--verbose: other 1
757 desc--verbose: other 1
736 other 2
758 other 2
737
759
738 other 3
760 other 3
739 desc--verbose: line 1
761 desc--verbose: line 1
740 line 2
762 line 2
741 desc--debug: third
763 desc--debug: third
742 desc--debug: second
764 desc--debug: second
743 desc--debug: merge
765 desc--debug: merge
744 desc--debug: new head
766 desc--debug: new head
745 desc--debug: new branch
767 desc--debug: new branch
746 desc--debug: no user, no domain
768 desc--debug: no user, no domain
747 desc--debug: no person
769 desc--debug: no person
748 desc--debug: other 1
770 desc--debug: other 1
749 other 2
771 other 2
750
772
751 other 3
773 other 3
752 desc--debug: line 1
774 desc--debug: line 1
753 line 2
775 line 2
754 file_adds: fourth third
776 file_adds: fourth third
755 file_adds: second
777 file_adds: second
756 file_adds:
778 file_adds:
757 file_adds: d
779 file_adds: d
758 file_adds:
780 file_adds:
759 file_adds:
781 file_adds:
760 file_adds: c
782 file_adds: c
761 file_adds: b
783 file_adds: b
762 file_adds: a
784 file_adds: a
763 file_adds--verbose: fourth third
785 file_adds--verbose: fourth third
764 file_adds--verbose: second
786 file_adds--verbose: second
765 file_adds--verbose:
787 file_adds--verbose:
766 file_adds--verbose: d
788 file_adds--verbose: d
767 file_adds--verbose:
789 file_adds--verbose:
768 file_adds--verbose:
790 file_adds--verbose:
769 file_adds--verbose: c
791 file_adds--verbose: c
770 file_adds--verbose: b
792 file_adds--verbose: b
771 file_adds--verbose: a
793 file_adds--verbose: a
772 file_adds--debug: fourth third
794 file_adds--debug: fourth third
773 file_adds--debug: second
795 file_adds--debug: second
774 file_adds--debug:
796 file_adds--debug:
775 file_adds--debug: d
797 file_adds--debug: d
776 file_adds--debug:
798 file_adds--debug:
777 file_adds--debug:
799 file_adds--debug:
778 file_adds--debug: c
800 file_adds--debug: c
779 file_adds--debug: b
801 file_adds--debug: b
780 file_adds--debug: a
802 file_adds--debug: a
781 file_dels: second
803 file_dels: second
782 file_dels:
804 file_dels:
783 file_dels:
805 file_dels:
784 file_dels:
806 file_dels:
785 file_dels:
807 file_dels:
786 file_dels:
808 file_dels:
787 file_dels:
809 file_dels:
788 file_dels:
810 file_dels:
789 file_dels:
811 file_dels:
790 file_dels--verbose: second
812 file_dels--verbose: second
791 file_dels--verbose:
813 file_dels--verbose:
792 file_dels--verbose:
814 file_dels--verbose:
793 file_dels--verbose:
815 file_dels--verbose:
794 file_dels--verbose:
816 file_dels--verbose:
795 file_dels--verbose:
817 file_dels--verbose:
796 file_dels--verbose:
818 file_dels--verbose:
797 file_dels--verbose:
819 file_dels--verbose:
798 file_dels--verbose:
820 file_dels--verbose:
799 file_dels--debug: second
821 file_dels--debug: second
800 file_dels--debug:
822 file_dels--debug:
801 file_dels--debug:
823 file_dels--debug:
802 file_dels--debug:
824 file_dels--debug:
803 file_dels--debug:
825 file_dels--debug:
804 file_dels--debug:
826 file_dels--debug:
805 file_dels--debug:
827 file_dels--debug:
806 file_dels--debug:
828 file_dels--debug:
807 file_dels--debug:
829 file_dels--debug:
808 file_mods:
830 file_mods:
809 file_mods:
831 file_mods:
810 file_mods:
832 file_mods:
811 file_mods:
833 file_mods:
812 file_mods:
834 file_mods:
813 file_mods: c
835 file_mods: c
814 file_mods:
836 file_mods:
815 file_mods:
837 file_mods:
816 file_mods:
838 file_mods:
817 file_mods--verbose:
839 file_mods--verbose:
818 file_mods--verbose:
840 file_mods--verbose:
819 file_mods--verbose:
841 file_mods--verbose:
820 file_mods--verbose:
842 file_mods--verbose:
821 file_mods--verbose:
843 file_mods--verbose:
822 file_mods--verbose: c
844 file_mods--verbose: c
823 file_mods--verbose:
845 file_mods--verbose:
824 file_mods--verbose:
846 file_mods--verbose:
825 file_mods--verbose:
847 file_mods--verbose:
826 file_mods--debug:
848 file_mods--debug:
827 file_mods--debug:
849 file_mods--debug:
828 file_mods--debug:
850 file_mods--debug:
829 file_mods--debug:
851 file_mods--debug:
830 file_mods--debug:
852 file_mods--debug:
831 file_mods--debug: c
853 file_mods--debug: c
832 file_mods--debug:
854 file_mods--debug:
833 file_mods--debug:
855 file_mods--debug:
834 file_mods--debug:
856 file_mods--debug:
835 file_copies: fourth (second)
857 file_copies: fourth (second)
836 file_copies:
858 file_copies:
837 file_copies:
859 file_copies:
838 file_copies:
860 file_copies:
839 file_copies:
861 file_copies:
840 file_copies:
862 file_copies:
841 file_copies:
863 file_copies:
842 file_copies:
864 file_copies:
843 file_copies:
865 file_copies:
844 file_copies--verbose: fourth (second)
866 file_copies--verbose: fourth (second)
845 file_copies--verbose:
867 file_copies--verbose:
846 file_copies--verbose:
868 file_copies--verbose:
847 file_copies--verbose:
869 file_copies--verbose:
848 file_copies--verbose:
870 file_copies--verbose:
849 file_copies--verbose:
871 file_copies--verbose:
850 file_copies--verbose:
872 file_copies--verbose:
851 file_copies--verbose:
873 file_copies--verbose:
852 file_copies--verbose:
874 file_copies--verbose:
853 file_copies--debug: fourth (second)
875 file_copies--debug: fourth (second)
854 file_copies--debug:
876 file_copies--debug:
855 file_copies--debug:
877 file_copies--debug:
856 file_copies--debug:
878 file_copies--debug:
857 file_copies--debug:
879 file_copies--debug:
858 file_copies--debug:
880 file_copies--debug:
859 file_copies--debug:
881 file_copies--debug:
860 file_copies--debug:
882 file_copies--debug:
861 file_copies--debug:
883 file_copies--debug:
862 file_copies_switch:
884 file_copies_switch:
863 file_copies_switch:
885 file_copies_switch:
864 file_copies_switch:
886 file_copies_switch:
865 file_copies_switch:
887 file_copies_switch:
866 file_copies_switch:
888 file_copies_switch:
867 file_copies_switch:
889 file_copies_switch:
868 file_copies_switch:
890 file_copies_switch:
869 file_copies_switch:
891 file_copies_switch:
870 file_copies_switch:
892 file_copies_switch:
871 file_copies_switch--verbose:
893 file_copies_switch--verbose:
872 file_copies_switch--verbose:
894 file_copies_switch--verbose:
873 file_copies_switch--verbose:
895 file_copies_switch--verbose:
874 file_copies_switch--verbose:
896 file_copies_switch--verbose:
875 file_copies_switch--verbose:
897 file_copies_switch--verbose:
876 file_copies_switch--verbose:
898 file_copies_switch--verbose:
877 file_copies_switch--verbose:
899 file_copies_switch--verbose:
878 file_copies_switch--verbose:
900 file_copies_switch--verbose:
879 file_copies_switch--verbose:
901 file_copies_switch--verbose:
880 file_copies_switch--debug:
902 file_copies_switch--debug:
881 file_copies_switch--debug:
903 file_copies_switch--debug:
882 file_copies_switch--debug:
904 file_copies_switch--debug:
883 file_copies_switch--debug:
905 file_copies_switch--debug:
884 file_copies_switch--debug:
906 file_copies_switch--debug:
885 file_copies_switch--debug:
907 file_copies_switch--debug:
886 file_copies_switch--debug:
908 file_copies_switch--debug:
887 file_copies_switch--debug:
909 file_copies_switch--debug:
888 file_copies_switch--debug:
910 file_copies_switch--debug:
889 files: fourth second third
911 files: fourth second third
890 files: second
912 files: second
891 files:
913 files:
892 files: d
914 files: d
893 files:
915 files:
894 files: c
916 files: c
895 files: c
917 files: c
896 files: b
918 files: b
897 files: a
919 files: a
898 files--verbose: fourth second third
920 files--verbose: fourth second third
899 files--verbose: second
921 files--verbose: second
900 files--verbose:
922 files--verbose:
901 files--verbose: d
923 files--verbose: d
902 files--verbose:
924 files--verbose:
903 files--verbose: c
925 files--verbose: c
904 files--verbose: c
926 files--verbose: c
905 files--verbose: b
927 files--verbose: b
906 files--verbose: a
928 files--verbose: a
907 files--debug: fourth second third
929 files--debug: fourth second third
908 files--debug: second
930 files--debug: second
909 files--debug:
931 files--debug:
910 files--debug: d
932 files--debug: d
911 files--debug:
933 files--debug:
912 files--debug: c
934 files--debug: c
913 files--debug: c
935 files--debug: c
914 files--debug: b
936 files--debug: b
915 files--debug: a
937 files--debug: a
916 manifest: 6:94961b75a2da
938 manifest: 6:94961b75a2da
917 manifest: 5:f2dbc354b94e
939 manifest: 5:f2dbc354b94e
918 manifest: 4:4dc3def4f9b4
940 manifest: 4:4dc3def4f9b4
919 manifest: 4:4dc3def4f9b4
941 manifest: 4:4dc3def4f9b4
920 manifest: 3:cb5a1327723b
942 manifest: 3:cb5a1327723b
921 manifest: 3:cb5a1327723b
943 manifest: 3:cb5a1327723b
922 manifest: 2:6e0e82995c35
944 manifest: 2:6e0e82995c35
923 manifest: 1:4e8d705b1e53
945 manifest: 1:4e8d705b1e53
924 manifest: 0:a0c8bcbbb45c
946 manifest: 0:a0c8bcbbb45c
925 manifest--verbose: 6:94961b75a2da
947 manifest--verbose: 6:94961b75a2da
926 manifest--verbose: 5:f2dbc354b94e
948 manifest--verbose: 5:f2dbc354b94e
927 manifest--verbose: 4:4dc3def4f9b4
949 manifest--verbose: 4:4dc3def4f9b4
928 manifest--verbose: 4:4dc3def4f9b4
950 manifest--verbose: 4:4dc3def4f9b4
929 manifest--verbose: 3:cb5a1327723b
951 manifest--verbose: 3:cb5a1327723b
930 manifest--verbose: 3:cb5a1327723b
952 manifest--verbose: 3:cb5a1327723b
931 manifest--verbose: 2:6e0e82995c35
953 manifest--verbose: 2:6e0e82995c35
932 manifest--verbose: 1:4e8d705b1e53
954 manifest--verbose: 1:4e8d705b1e53
933 manifest--verbose: 0:a0c8bcbbb45c
955 manifest--verbose: 0:a0c8bcbbb45c
934 manifest--debug: 6:94961b75a2da554b4df6fb599e5bfc7d48de0c64
956 manifest--debug: 6:94961b75a2da554b4df6fb599e5bfc7d48de0c64
935 manifest--debug: 5:f2dbc354b94e5ec0b4f10680ee0cee816101d0bf
957 manifest--debug: 5:f2dbc354b94e5ec0b4f10680ee0cee816101d0bf
936 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
958 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
937 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
959 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
938 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
960 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
939 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
961 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
940 manifest--debug: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
962 manifest--debug: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
941 manifest--debug: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
963 manifest--debug: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
942 manifest--debug: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
964 manifest--debug: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
943 node: 95c24699272ef57d062b8bccc32c878bf841784a
965 node: 95c24699272ef57d062b8bccc32c878bf841784a
944 node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
966 node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
945 node: d41e714fe50d9e4a5f11b4d595d543481b5f980b
967 node: d41e714fe50d9e4a5f11b4d595d543481b5f980b
946 node: 13207e5a10d9fd28ec424934298e176197f2c67f
968 node: 13207e5a10d9fd28ec424934298e176197f2c67f
947 node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
969 node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
948 node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
970 node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
949 node: 97054abb4ab824450e9164180baf491ae0078465
971 node: 97054abb4ab824450e9164180baf491ae0078465
950 node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
972 node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
951 node: 1e4e1b8f71e05681d422154f5421e385fec3454f
973 node: 1e4e1b8f71e05681d422154f5421e385fec3454f
952 node--verbose: 95c24699272ef57d062b8bccc32c878bf841784a
974 node--verbose: 95c24699272ef57d062b8bccc32c878bf841784a
953 node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
975 node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
954 node--verbose: d41e714fe50d9e4a5f11b4d595d543481b5f980b
976 node--verbose: d41e714fe50d9e4a5f11b4d595d543481b5f980b
955 node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
977 node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
956 node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
978 node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
957 node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
979 node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
958 node--verbose: 97054abb4ab824450e9164180baf491ae0078465
980 node--verbose: 97054abb4ab824450e9164180baf491ae0078465
959 node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
981 node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
960 node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
982 node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
961 node--debug: 95c24699272ef57d062b8bccc32c878bf841784a
983 node--debug: 95c24699272ef57d062b8bccc32c878bf841784a
962 node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
984 node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
963 node--debug: d41e714fe50d9e4a5f11b4d595d543481b5f980b
985 node--debug: d41e714fe50d9e4a5f11b4d595d543481b5f980b
964 node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
986 node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
965 node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
987 node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
966 node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
988 node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
967 node--debug: 97054abb4ab824450e9164180baf491ae0078465
989 node--debug: 97054abb4ab824450e9164180baf491ae0078465
968 node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
990 node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
969 node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
991 node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
970 parents:
992 parents:
971 parents: -1:000000000000
993 parents: -1:000000000000
972 parents: 5:13207e5a10d9 4:bbe44766e73d
994 parents: 5:13207e5a10d9 4:bbe44766e73d
973 parents: 3:10e46f2dcbf4
995 parents: 3:10e46f2dcbf4
974 parents:
996 parents:
975 parents:
997 parents:
976 parents:
998 parents:
977 parents:
999 parents:
978 parents:
1000 parents:
979 parents--verbose:
1001 parents--verbose:
980 parents--verbose: -1:000000000000
1002 parents--verbose: -1:000000000000
981 parents--verbose: 5:13207e5a10d9 4:bbe44766e73d
1003 parents--verbose: 5:13207e5a10d9 4:bbe44766e73d
982 parents--verbose: 3:10e46f2dcbf4
1004 parents--verbose: 3:10e46f2dcbf4
983 parents--verbose:
1005 parents--verbose:
984 parents--verbose:
1006 parents--verbose:
985 parents--verbose:
1007 parents--verbose:
986 parents--verbose:
1008 parents--verbose:
987 parents--verbose:
1009 parents--verbose:
988 parents--debug: 7:29114dbae42b9f078cf2714dbe3a86bba8ec7453 -1:0000000000000000000000000000000000000000
1010 parents--debug: 7:29114dbae42b9f078cf2714dbe3a86bba8ec7453 -1:0000000000000000000000000000000000000000
989 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1011 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
990 parents--debug: 5:13207e5a10d9fd28ec424934298e176197f2c67f 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
1012 parents--debug: 5:13207e5a10d9fd28ec424934298e176197f2c67f 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
991 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1013 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
992 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1014 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
993 parents--debug: 2:97054abb4ab824450e9164180baf491ae0078465 -1:0000000000000000000000000000000000000000
1015 parents--debug: 2:97054abb4ab824450e9164180baf491ae0078465 -1:0000000000000000000000000000000000000000
994 parents--debug: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965 -1:0000000000000000000000000000000000000000
1016 parents--debug: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965 -1:0000000000000000000000000000000000000000
995 parents--debug: 0:1e4e1b8f71e05681d422154f5421e385fec3454f -1:0000000000000000000000000000000000000000
1017 parents--debug: 0:1e4e1b8f71e05681d422154f5421e385fec3454f -1:0000000000000000000000000000000000000000
996 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1018 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
997 rev: 8
1019 rev: 8
998 rev: 7
1020 rev: 7
999 rev: 6
1021 rev: 6
1000 rev: 5
1022 rev: 5
1001 rev: 4
1023 rev: 4
1002 rev: 3
1024 rev: 3
1003 rev: 2
1025 rev: 2
1004 rev: 1
1026 rev: 1
1005 rev: 0
1027 rev: 0
1006 rev--verbose: 8
1028 rev--verbose: 8
1007 rev--verbose: 7
1029 rev--verbose: 7
1008 rev--verbose: 6
1030 rev--verbose: 6
1009 rev--verbose: 5
1031 rev--verbose: 5
1010 rev--verbose: 4
1032 rev--verbose: 4
1011 rev--verbose: 3
1033 rev--verbose: 3
1012 rev--verbose: 2
1034 rev--verbose: 2
1013 rev--verbose: 1
1035 rev--verbose: 1
1014 rev--verbose: 0
1036 rev--verbose: 0
1015 rev--debug: 8
1037 rev--debug: 8
1016 rev--debug: 7
1038 rev--debug: 7
1017 rev--debug: 6
1039 rev--debug: 6
1018 rev--debug: 5
1040 rev--debug: 5
1019 rev--debug: 4
1041 rev--debug: 4
1020 rev--debug: 3
1042 rev--debug: 3
1021 rev--debug: 2
1043 rev--debug: 2
1022 rev--debug: 1
1044 rev--debug: 1
1023 rev--debug: 0
1045 rev--debug: 0
1024 tags: tip
1046 tags: tip
1025 tags:
1047 tags:
1026 tags:
1048 tags:
1027 tags:
1049 tags:
1028 tags:
1050 tags:
1029 tags:
1051 tags:
1030 tags:
1052 tags:
1031 tags:
1053 tags:
1032 tags:
1054 tags:
1033 tags--verbose: tip
1055 tags--verbose: tip
1034 tags--verbose:
1056 tags--verbose:
1035 tags--verbose:
1057 tags--verbose:
1036 tags--verbose:
1058 tags--verbose:
1037 tags--verbose:
1059 tags--verbose:
1038 tags--verbose:
1060 tags--verbose:
1039 tags--verbose:
1061 tags--verbose:
1040 tags--verbose:
1062 tags--verbose:
1041 tags--verbose:
1063 tags--verbose:
1042 tags--debug: tip
1064 tags--debug: tip
1043 tags--debug:
1065 tags--debug:
1044 tags--debug:
1066 tags--debug:
1045 tags--debug:
1067 tags--debug:
1046 tags--debug:
1068 tags--debug:
1047 tags--debug:
1069 tags--debug:
1048 tags--debug:
1070 tags--debug:
1049 tags--debug:
1071 tags--debug:
1050 tags--debug:
1072 tags--debug:
1051 diffstat: 3: +2/-1
1073 diffstat: 3: +2/-1
1052 diffstat: 1: +1/-0
1074 diffstat: 1: +1/-0
1053 diffstat: 0: +0/-0
1075 diffstat: 0: +0/-0
1054 diffstat: 1: +1/-0
1076 diffstat: 1: +1/-0
1055 diffstat: 0: +0/-0
1077 diffstat: 0: +0/-0
1056 diffstat: 1: +1/-0
1078 diffstat: 1: +1/-0
1057 diffstat: 1: +4/-0
1079 diffstat: 1: +4/-0
1058 diffstat: 1: +2/-0
1080 diffstat: 1: +2/-0
1059 diffstat: 1: +1/-0
1081 diffstat: 1: +1/-0
1060 diffstat--verbose: 3: +2/-1
1082 diffstat--verbose: 3: +2/-1
1061 diffstat--verbose: 1: +1/-0
1083 diffstat--verbose: 1: +1/-0
1062 diffstat--verbose: 0: +0/-0
1084 diffstat--verbose: 0: +0/-0
1063 diffstat--verbose: 1: +1/-0
1085 diffstat--verbose: 1: +1/-0
1064 diffstat--verbose: 0: +0/-0
1086 diffstat--verbose: 0: +0/-0
1065 diffstat--verbose: 1: +1/-0
1087 diffstat--verbose: 1: +1/-0
1066 diffstat--verbose: 1: +4/-0
1088 diffstat--verbose: 1: +4/-0
1067 diffstat--verbose: 1: +2/-0
1089 diffstat--verbose: 1: +2/-0
1068 diffstat--verbose: 1: +1/-0
1090 diffstat--verbose: 1: +1/-0
1069 diffstat--debug: 3: +2/-1
1091 diffstat--debug: 3: +2/-1
1070 diffstat--debug: 1: +1/-0
1092 diffstat--debug: 1: +1/-0
1071 diffstat--debug: 0: +0/-0
1093 diffstat--debug: 0: +0/-0
1072 diffstat--debug: 1: +1/-0
1094 diffstat--debug: 1: +1/-0
1073 diffstat--debug: 0: +0/-0
1095 diffstat--debug: 0: +0/-0
1074 diffstat--debug: 1: +1/-0
1096 diffstat--debug: 1: +1/-0
1075 diffstat--debug: 1: +4/-0
1097 diffstat--debug: 1: +4/-0
1076 diffstat--debug: 1: +2/-0
1098 diffstat--debug: 1: +2/-0
1077 diffstat--debug: 1: +1/-0
1099 diffstat--debug: 1: +1/-0
1078 extras: branch=default
1100 extras: branch=default
1079 extras: branch=default
1101 extras: branch=default
1080 extras: branch=default
1102 extras: branch=default
1081 extras: branch=default
1103 extras: branch=default
1082 extras: branch=foo
1104 extras: branch=foo
1083 extras: branch=default
1105 extras: branch=default
1084 extras: branch=default
1106 extras: branch=default
1085 extras: branch=default
1107 extras: branch=default
1086 extras: branch=default
1108 extras: branch=default
1087 extras--verbose: branch=default
1109 extras--verbose: branch=default
1088 extras--verbose: branch=default
1110 extras--verbose: branch=default
1089 extras--verbose: branch=default
1111 extras--verbose: branch=default
1090 extras--verbose: branch=default
1112 extras--verbose: branch=default
1091 extras--verbose: branch=foo
1113 extras--verbose: branch=foo
1092 extras--verbose: branch=default
1114 extras--verbose: branch=default
1093 extras--verbose: branch=default
1115 extras--verbose: branch=default
1094 extras--verbose: branch=default
1116 extras--verbose: branch=default
1095 extras--verbose: branch=default
1117 extras--verbose: branch=default
1096 extras--debug: branch=default
1118 extras--debug: branch=default
1097 extras--debug: branch=default
1119 extras--debug: branch=default
1098 extras--debug: branch=default
1120 extras--debug: branch=default
1099 extras--debug: branch=default
1121 extras--debug: branch=default
1100 extras--debug: branch=foo
1122 extras--debug: branch=foo
1101 extras--debug: branch=default
1123 extras--debug: branch=default
1102 extras--debug: branch=default
1124 extras--debug: branch=default
1103 extras--debug: branch=default
1125 extras--debug: branch=default
1104 extras--debug: branch=default
1126 extras--debug: branch=default
1105 p1rev: 7
1127 p1rev: 7
1106 p1rev: -1
1128 p1rev: -1
1107 p1rev: 5
1129 p1rev: 5
1108 p1rev: 3
1130 p1rev: 3
1109 p1rev: 3
1131 p1rev: 3
1110 p1rev: 2
1132 p1rev: 2
1111 p1rev: 1
1133 p1rev: 1
1112 p1rev: 0
1134 p1rev: 0
1113 p1rev: -1
1135 p1rev: -1
1114 p1rev--verbose: 7
1136 p1rev--verbose: 7
1115 p1rev--verbose: -1
1137 p1rev--verbose: -1
1116 p1rev--verbose: 5
1138 p1rev--verbose: 5
1117 p1rev--verbose: 3
1139 p1rev--verbose: 3
1118 p1rev--verbose: 3
1140 p1rev--verbose: 3
1119 p1rev--verbose: 2
1141 p1rev--verbose: 2
1120 p1rev--verbose: 1
1142 p1rev--verbose: 1
1121 p1rev--verbose: 0
1143 p1rev--verbose: 0
1122 p1rev--verbose: -1
1144 p1rev--verbose: -1
1123 p1rev--debug: 7
1145 p1rev--debug: 7
1124 p1rev--debug: -1
1146 p1rev--debug: -1
1125 p1rev--debug: 5
1147 p1rev--debug: 5
1126 p1rev--debug: 3
1148 p1rev--debug: 3
1127 p1rev--debug: 3
1149 p1rev--debug: 3
1128 p1rev--debug: 2
1150 p1rev--debug: 2
1129 p1rev--debug: 1
1151 p1rev--debug: 1
1130 p1rev--debug: 0
1152 p1rev--debug: 0
1131 p1rev--debug: -1
1153 p1rev--debug: -1
1132 p2rev: -1
1154 p2rev: -1
1133 p2rev: -1
1155 p2rev: -1
1134 p2rev: 4
1156 p2rev: 4
1135 p2rev: -1
1157 p2rev: -1
1136 p2rev: -1
1158 p2rev: -1
1137 p2rev: -1
1159 p2rev: -1
1138 p2rev: -1
1160 p2rev: -1
1139 p2rev: -1
1161 p2rev: -1
1140 p2rev: -1
1162 p2rev: -1
1141 p2rev--verbose: -1
1163 p2rev--verbose: -1
1142 p2rev--verbose: -1
1164 p2rev--verbose: -1
1143 p2rev--verbose: 4
1165 p2rev--verbose: 4
1144 p2rev--verbose: -1
1166 p2rev--verbose: -1
1145 p2rev--verbose: -1
1167 p2rev--verbose: -1
1146 p2rev--verbose: -1
1168 p2rev--verbose: -1
1147 p2rev--verbose: -1
1169 p2rev--verbose: -1
1148 p2rev--verbose: -1
1170 p2rev--verbose: -1
1149 p2rev--verbose: -1
1171 p2rev--verbose: -1
1150 p2rev--debug: -1
1172 p2rev--debug: -1
1151 p2rev--debug: -1
1173 p2rev--debug: -1
1152 p2rev--debug: 4
1174 p2rev--debug: 4
1153 p2rev--debug: -1
1175 p2rev--debug: -1
1154 p2rev--debug: -1
1176 p2rev--debug: -1
1155 p2rev--debug: -1
1177 p2rev--debug: -1
1156 p2rev--debug: -1
1178 p2rev--debug: -1
1157 p2rev--debug: -1
1179 p2rev--debug: -1
1158 p2rev--debug: -1
1180 p2rev--debug: -1
1159 p1node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1181 p1node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1160 p1node: 0000000000000000000000000000000000000000
1182 p1node: 0000000000000000000000000000000000000000
1161 p1node: 13207e5a10d9fd28ec424934298e176197f2c67f
1183 p1node: 13207e5a10d9fd28ec424934298e176197f2c67f
1162 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1184 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1163 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1185 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1164 p1node: 97054abb4ab824450e9164180baf491ae0078465
1186 p1node: 97054abb4ab824450e9164180baf491ae0078465
1165 p1node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1187 p1node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1166 p1node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1188 p1node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1167 p1node: 0000000000000000000000000000000000000000
1189 p1node: 0000000000000000000000000000000000000000
1168 p1node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1190 p1node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1169 p1node--verbose: 0000000000000000000000000000000000000000
1191 p1node--verbose: 0000000000000000000000000000000000000000
1170 p1node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1192 p1node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1171 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1193 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1172 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1194 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1173 p1node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1195 p1node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1174 p1node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1196 p1node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1175 p1node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1197 p1node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1176 p1node--verbose: 0000000000000000000000000000000000000000
1198 p1node--verbose: 0000000000000000000000000000000000000000
1177 p1node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1199 p1node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1178 p1node--debug: 0000000000000000000000000000000000000000
1200 p1node--debug: 0000000000000000000000000000000000000000
1179 p1node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1201 p1node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1180 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1202 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1181 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1203 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1182 p1node--debug: 97054abb4ab824450e9164180baf491ae0078465
1204 p1node--debug: 97054abb4ab824450e9164180baf491ae0078465
1183 p1node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1205 p1node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1184 p1node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1206 p1node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1185 p1node--debug: 0000000000000000000000000000000000000000
1207 p1node--debug: 0000000000000000000000000000000000000000
1186 p2node: 0000000000000000000000000000000000000000
1208 p2node: 0000000000000000000000000000000000000000
1187 p2node: 0000000000000000000000000000000000000000
1209 p2node: 0000000000000000000000000000000000000000
1188 p2node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1210 p2node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1189 p2node: 0000000000000000000000000000000000000000
1211 p2node: 0000000000000000000000000000000000000000
1190 p2node: 0000000000000000000000000000000000000000
1212 p2node: 0000000000000000000000000000000000000000
1191 p2node: 0000000000000000000000000000000000000000
1213 p2node: 0000000000000000000000000000000000000000
1192 p2node: 0000000000000000000000000000000000000000
1214 p2node: 0000000000000000000000000000000000000000
1193 p2node: 0000000000000000000000000000000000000000
1215 p2node: 0000000000000000000000000000000000000000
1194 p2node: 0000000000000000000000000000000000000000
1216 p2node: 0000000000000000000000000000000000000000
1195 p2node--verbose: 0000000000000000000000000000000000000000
1217 p2node--verbose: 0000000000000000000000000000000000000000
1196 p2node--verbose: 0000000000000000000000000000000000000000
1218 p2node--verbose: 0000000000000000000000000000000000000000
1197 p2node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1219 p2node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1198 p2node--verbose: 0000000000000000000000000000000000000000
1220 p2node--verbose: 0000000000000000000000000000000000000000
1199 p2node--verbose: 0000000000000000000000000000000000000000
1221 p2node--verbose: 0000000000000000000000000000000000000000
1200 p2node--verbose: 0000000000000000000000000000000000000000
1222 p2node--verbose: 0000000000000000000000000000000000000000
1201 p2node--verbose: 0000000000000000000000000000000000000000
1223 p2node--verbose: 0000000000000000000000000000000000000000
1202 p2node--verbose: 0000000000000000000000000000000000000000
1224 p2node--verbose: 0000000000000000000000000000000000000000
1203 p2node--verbose: 0000000000000000000000000000000000000000
1225 p2node--verbose: 0000000000000000000000000000000000000000
1204 p2node--debug: 0000000000000000000000000000000000000000
1226 p2node--debug: 0000000000000000000000000000000000000000
1205 p2node--debug: 0000000000000000000000000000000000000000
1227 p2node--debug: 0000000000000000000000000000000000000000
1206 p2node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1228 p2node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1207 p2node--debug: 0000000000000000000000000000000000000000
1229 p2node--debug: 0000000000000000000000000000000000000000
1208 p2node--debug: 0000000000000000000000000000000000000000
1230 p2node--debug: 0000000000000000000000000000000000000000
1209 p2node--debug: 0000000000000000000000000000000000000000
1231 p2node--debug: 0000000000000000000000000000000000000000
1210 p2node--debug: 0000000000000000000000000000000000000000
1232 p2node--debug: 0000000000000000000000000000000000000000
1211 p2node--debug: 0000000000000000000000000000000000000000
1233 p2node--debug: 0000000000000000000000000000000000000000
1212 p2node--debug: 0000000000000000000000000000000000000000
1234 p2node--debug: 0000000000000000000000000000000000000000
1213
1235
1214 Filters work:
1236 Filters work:
1215
1237
1216 $ hg log --template '{author|domain}\n'
1238 $ hg log --template '{author|domain}\n'
1217
1239
1218 hostname
1240 hostname
1219
1241
1220
1242
1221
1243
1222
1244
1223 place
1245 place
1224 place
1246 place
1225 hostname
1247 hostname
1226
1248
1227 $ hg log --template '{author|person}\n'
1249 $ hg log --template '{author|person}\n'
1228 test
1250 test
1229 User Name
1251 User Name
1230 person
1252 person
1231 person
1253 person
1232 person
1254 person
1233 person
1255 person
1234 other
1256 other
1235 A. N. Other
1257 A. N. Other
1236 User Name
1258 User Name
1237
1259
1238 $ hg log --template '{author|user}\n'
1260 $ hg log --template '{author|user}\n'
1239 test
1261 test
1240 user
1262 user
1241 person
1263 person
1242 person
1264 person
1243 person
1265 person
1244 person
1266 person
1245 other
1267 other
1246 other
1268 other
1247 user
1269 user
1248
1270
1249 $ hg log --template '{date|date}\n'
1271 $ hg log --template '{date|date}\n'
1250 Wed Jan 01 10:01:00 2020 +0000
1272 Wed Jan 01 10:01:00 2020 +0000
1251 Mon Jan 12 13:46:40 1970 +0000
1273 Mon Jan 12 13:46:40 1970 +0000
1252 Sun Jan 18 08:40:01 1970 +0000
1274 Sun Jan 18 08:40:01 1970 +0000
1253 Sun Jan 18 08:40:00 1970 +0000
1275 Sun Jan 18 08:40:00 1970 +0000
1254 Sat Jan 17 04:53:20 1970 +0000
1276 Sat Jan 17 04:53:20 1970 +0000
1255 Fri Jan 16 01:06:40 1970 +0000
1277 Fri Jan 16 01:06:40 1970 +0000
1256 Wed Jan 14 21:20:00 1970 +0000
1278 Wed Jan 14 21:20:00 1970 +0000
1257 Tue Jan 13 17:33:20 1970 +0000
1279 Tue Jan 13 17:33:20 1970 +0000
1258 Mon Jan 12 13:46:40 1970 +0000
1280 Mon Jan 12 13:46:40 1970 +0000
1259
1281
1260 $ hg log --template '{date|isodate}\n'
1282 $ hg log --template '{date|isodate}\n'
1261 2020-01-01 10:01 +0000
1283 2020-01-01 10:01 +0000
1262 1970-01-12 13:46 +0000
1284 1970-01-12 13:46 +0000
1263 1970-01-18 08:40 +0000
1285 1970-01-18 08:40 +0000
1264 1970-01-18 08:40 +0000
1286 1970-01-18 08:40 +0000
1265 1970-01-17 04:53 +0000
1287 1970-01-17 04:53 +0000
1266 1970-01-16 01:06 +0000
1288 1970-01-16 01:06 +0000
1267 1970-01-14 21:20 +0000
1289 1970-01-14 21:20 +0000
1268 1970-01-13 17:33 +0000
1290 1970-01-13 17:33 +0000
1269 1970-01-12 13:46 +0000
1291 1970-01-12 13:46 +0000
1270
1292
1271 $ hg log --template '{date|isodatesec}\n'
1293 $ hg log --template '{date|isodatesec}\n'
1272 2020-01-01 10:01:00 +0000
1294 2020-01-01 10:01:00 +0000
1273 1970-01-12 13:46:40 +0000
1295 1970-01-12 13:46:40 +0000
1274 1970-01-18 08:40:01 +0000
1296 1970-01-18 08:40:01 +0000
1275 1970-01-18 08:40:00 +0000
1297 1970-01-18 08:40:00 +0000
1276 1970-01-17 04:53:20 +0000
1298 1970-01-17 04:53:20 +0000
1277 1970-01-16 01:06:40 +0000
1299 1970-01-16 01:06:40 +0000
1278 1970-01-14 21:20:00 +0000
1300 1970-01-14 21:20:00 +0000
1279 1970-01-13 17:33:20 +0000
1301 1970-01-13 17:33:20 +0000
1280 1970-01-12 13:46:40 +0000
1302 1970-01-12 13:46:40 +0000
1281
1303
1282 $ hg log --template '{date|rfc822date}\n'
1304 $ hg log --template '{date|rfc822date}\n'
1283 Wed, 01 Jan 2020 10:01:00 +0000
1305 Wed, 01 Jan 2020 10:01:00 +0000
1284 Mon, 12 Jan 1970 13:46:40 +0000
1306 Mon, 12 Jan 1970 13:46:40 +0000
1285 Sun, 18 Jan 1970 08:40:01 +0000
1307 Sun, 18 Jan 1970 08:40:01 +0000
1286 Sun, 18 Jan 1970 08:40:00 +0000
1308 Sun, 18 Jan 1970 08:40:00 +0000
1287 Sat, 17 Jan 1970 04:53:20 +0000
1309 Sat, 17 Jan 1970 04:53:20 +0000
1288 Fri, 16 Jan 1970 01:06:40 +0000
1310 Fri, 16 Jan 1970 01:06:40 +0000
1289 Wed, 14 Jan 1970 21:20:00 +0000
1311 Wed, 14 Jan 1970 21:20:00 +0000
1290 Tue, 13 Jan 1970 17:33:20 +0000
1312 Tue, 13 Jan 1970 17:33:20 +0000
1291 Mon, 12 Jan 1970 13:46:40 +0000
1313 Mon, 12 Jan 1970 13:46:40 +0000
1292
1314
1293 $ hg log --template '{desc|firstline}\n'
1315 $ hg log --template '{desc|firstline}\n'
1294 third
1316 third
1295 second
1317 second
1296 merge
1318 merge
1297 new head
1319 new head
1298 new branch
1320 new branch
1299 no user, no domain
1321 no user, no domain
1300 no person
1322 no person
1301 other 1
1323 other 1
1302 line 1
1324 line 1
1303
1325
1304 $ hg log --template '{node|short}\n'
1326 $ hg log --template '{node|short}\n'
1305 95c24699272e
1327 95c24699272e
1306 29114dbae42b
1328 29114dbae42b
1307 d41e714fe50d
1329 d41e714fe50d
1308 13207e5a10d9
1330 13207e5a10d9
1309 bbe44766e73d
1331 bbe44766e73d
1310 10e46f2dcbf4
1332 10e46f2dcbf4
1311 97054abb4ab8
1333 97054abb4ab8
1312 b608e9d1a3f0
1334 b608e9d1a3f0
1313 1e4e1b8f71e0
1335 1e4e1b8f71e0
1314
1336
1315 $ hg log --template '<changeset author="{author|xmlescape}"/>\n'
1337 $ hg log --template '<changeset author="{author|xmlescape}"/>\n'
1316 <changeset author="test"/>
1338 <changeset author="test"/>
1317 <changeset author="User Name &lt;user@hostname&gt;"/>
1339 <changeset author="User Name &lt;user@hostname&gt;"/>
1318 <changeset author="person"/>
1340 <changeset author="person"/>
1319 <changeset author="person"/>
1341 <changeset author="person"/>
1320 <changeset author="person"/>
1342 <changeset author="person"/>
1321 <changeset author="person"/>
1343 <changeset author="person"/>
1322 <changeset author="other@place"/>
1344 <changeset author="other@place"/>
1323 <changeset author="A. N. Other &lt;other@place&gt;"/>
1345 <changeset author="A. N. Other &lt;other@place&gt;"/>
1324 <changeset author="User Name &lt;user@hostname&gt;"/>
1346 <changeset author="User Name &lt;user@hostname&gt;"/>
1325
1347
1326 $ hg log --template '{rev}: {children}\n'
1348 $ hg log --template '{rev}: {children}\n'
1327 8:
1349 8:
1328 7: 8:95c24699272e
1350 7: 8:95c24699272e
1329 6:
1351 6:
1330 5: 6:d41e714fe50d
1352 5: 6:d41e714fe50d
1331 4: 6:d41e714fe50d
1353 4: 6:d41e714fe50d
1332 3: 4:bbe44766e73d 5:13207e5a10d9
1354 3: 4:bbe44766e73d 5:13207e5a10d9
1333 2: 3:10e46f2dcbf4
1355 2: 3:10e46f2dcbf4
1334 1: 2:97054abb4ab8
1356 1: 2:97054abb4ab8
1335 0: 1:b608e9d1a3f0
1357 0: 1:b608e9d1a3f0
1336
1358
1337 Formatnode filter works:
1359 Formatnode filter works:
1338
1360
1339 $ hg -q log -r 0 --template '{node|formatnode}\n'
1361 $ hg -q log -r 0 --template '{node|formatnode}\n'
1340 1e4e1b8f71e0
1362 1e4e1b8f71e0
1341
1363
1342 $ hg log -r 0 --template '{node|formatnode}\n'
1364 $ hg log -r 0 --template '{node|formatnode}\n'
1343 1e4e1b8f71e0
1365 1e4e1b8f71e0
1344
1366
1345 $ hg -v log -r 0 --template '{node|formatnode}\n'
1367 $ hg -v log -r 0 --template '{node|formatnode}\n'
1346 1e4e1b8f71e0
1368 1e4e1b8f71e0
1347
1369
1348 $ hg --debug log -r 0 --template '{node|formatnode}\n'
1370 $ hg --debug log -r 0 --template '{node|formatnode}\n'
1349 1e4e1b8f71e05681d422154f5421e385fec3454f
1371 1e4e1b8f71e05681d422154f5421e385fec3454f
1350
1372
1351 Age filter:
1373 Age filter:
1352
1374
1353 $ hg log --template '{date|age}\n' > /dev/null || exit 1
1375 $ hg log --template '{date|age}\n' > /dev/null || exit 1
1354
1376
1355 >>> from datetime import datetime, timedelta
1377 >>> from datetime import datetime, timedelta
1356 >>> fp = open('a', 'w')
1378 >>> fp = open('a', 'w')
1357 >>> n = datetime.now() + timedelta(366 * 7)
1379 >>> n = datetime.now() + timedelta(366 * 7)
1358 >>> fp.write('%d-%d-%d 00:00' % (n.year, n.month, n.day))
1380 >>> fp.write('%d-%d-%d 00:00' % (n.year, n.month, n.day))
1359 >>> fp.close()
1381 >>> fp.close()
1360 $ hg add a
1382 $ hg add a
1361 $ hg commit -m future -d "`cat a`"
1383 $ hg commit -m future -d "`cat a`"
1362
1384
1363 $ hg log -l1 --template '{date|age}\n'
1385 $ hg log -l1 --template '{date|age}\n'
1364 7 years from now
1386 7 years from now
1365
1387
1366 Error on syntax:
1388 Error on syntax:
1367
1389
1368 $ echo 'x = "f' >> t
1390 $ echo 'x = "f' >> t
1369 $ hg log
1391 $ hg log
1370 abort: t:3: unmatched quotes
1392 abort: t:3: unmatched quotes
1371 [255]
1393 [255]
1372
1394
1373 Behind the scenes, this will throw TypeError
1395 Behind the scenes, this will throw TypeError
1374
1396
1375 $ hg log -l 3 --template '{date|obfuscate}\n'
1397 $ hg log -l 3 --template '{date|obfuscate}\n'
1376 abort: template filter 'obfuscate' is not compatible with keyword 'date'
1398 abort: template filter 'obfuscate' is not compatible with keyword 'date'
1377 [255]
1399 [255]
1378
1400
1379 Behind the scenes, this will throw a ValueError
1401 Behind the scenes, this will throw a ValueError
1380
1402
1381 $ hg log -l 3 --template 'line: {desc|shortdate}\n'
1403 $ hg log -l 3 --template 'line: {desc|shortdate}\n'
1382 abort: template filter 'shortdate' is not compatible with keyword 'desc'
1404 abort: template filter 'shortdate' is not compatible with keyword 'desc'
1383 [255]
1405 [255]
1384
1406
1385 Behind the scenes, this will throw AttributeError
1407 Behind the scenes, this will throw AttributeError
1386
1408
1387 $ hg log -l 3 --template 'line: {date|escape}\n'
1409 $ hg log -l 3 --template 'line: {date|escape}\n'
1388 abort: template filter 'escape' is not compatible with keyword 'date'
1410 abort: template filter 'escape' is not compatible with keyword 'date'
1389 [255]
1411 [255]
1390
1412
1391 Behind the scenes, this will throw ValueError
1413 Behind the scenes, this will throw ValueError
1392
1414
1393 $ hg tip --template '{author|email|date}\n'
1415 $ hg tip --template '{author|email|date}\n'
1394 abort: template filter 'datefilter' is not compatible with keyword 'author'
1416 abort: template filter 'datefilter' is not compatible with keyword 'author'
1395 [255]
1417 [255]
1396
1418
1397 $ cd ..
1419 $ cd ..
1398
1420
1399
1421
1400 latesttag:
1422 latesttag:
1401
1423
1402 $ hg init latesttag
1424 $ hg init latesttag
1403 $ cd latesttag
1425 $ cd latesttag
1404
1426
1405 $ echo a > file
1427 $ echo a > file
1406 $ hg ci -Am a -d '0 0'
1428 $ hg ci -Am a -d '0 0'
1407 adding file
1429 adding file
1408
1430
1409 $ echo b >> file
1431 $ echo b >> file
1410 $ hg ci -m b -d '1 0'
1432 $ hg ci -m b -d '1 0'
1411
1433
1412 $ echo c >> head1
1434 $ echo c >> head1
1413 $ hg ci -Am h1c -d '2 0'
1435 $ hg ci -Am h1c -d '2 0'
1414 adding head1
1436 adding head1
1415
1437
1416 $ hg update -q 1
1438 $ hg update -q 1
1417 $ echo d >> head2
1439 $ echo d >> head2
1418 $ hg ci -Am h2d -d '3 0'
1440 $ hg ci -Am h2d -d '3 0'
1419 adding head2
1441 adding head2
1420 created new head
1442 created new head
1421
1443
1422 $ echo e >> head2
1444 $ echo e >> head2
1423 $ hg ci -m h2e -d '4 0'
1445 $ hg ci -m h2e -d '4 0'
1424
1446
1425 $ hg merge -q
1447 $ hg merge -q
1426 $ hg ci -m merge -d '5 0'
1448 $ hg ci -m merge -d '5 0'
1427
1449
1428 No tag set:
1450 No tag set:
1429
1451
1430 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1452 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1431 5: null+5
1453 5: null+5
1432 4: null+4
1454 4: null+4
1433 3: null+3
1455 3: null+3
1434 2: null+3
1456 2: null+3
1435 1: null+2
1457 1: null+2
1436 0: null+1
1458 0: null+1
1437
1459
1438 One common tag: longuest path wins:
1460 One common tag: longuest path wins:
1439
1461
1440 $ hg tag -r 1 -m t1 -d '6 0' t1
1462 $ hg tag -r 1 -m t1 -d '6 0' t1
1441 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1463 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1442 6: t1+4
1464 6: t1+4
1443 5: t1+3
1465 5: t1+3
1444 4: t1+2
1466 4: t1+2
1445 3: t1+1
1467 3: t1+1
1446 2: t1+1
1468 2: t1+1
1447 1: t1+0
1469 1: t1+0
1448 0: null+1
1470 0: null+1
1449
1471
1450 One ancestor tag: more recent wins:
1472 One ancestor tag: more recent wins:
1451
1473
1452 $ hg tag -r 2 -m t2 -d '7 0' t2
1474 $ hg tag -r 2 -m t2 -d '7 0' t2
1453 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1475 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1454 7: t2+3
1476 7: t2+3
1455 6: t2+2
1477 6: t2+2
1456 5: t2+1
1478 5: t2+1
1457 4: t1+2
1479 4: t1+2
1458 3: t1+1
1480 3: t1+1
1459 2: t2+0
1481 2: t2+0
1460 1: t1+0
1482 1: t1+0
1461 0: null+1
1483 0: null+1
1462
1484
1463 Two branch tags: more recent wins:
1485 Two branch tags: more recent wins:
1464
1486
1465 $ hg tag -r 3 -m t3 -d '8 0' t3
1487 $ hg tag -r 3 -m t3 -d '8 0' t3
1466 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1488 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1467 8: t3+5
1489 8: t3+5
1468 7: t3+4
1490 7: t3+4
1469 6: t3+3
1491 6: t3+3
1470 5: t3+2
1492 5: t3+2
1471 4: t3+1
1493 4: t3+1
1472 3: t3+0
1494 3: t3+0
1473 2: t2+0
1495 2: t2+0
1474 1: t1+0
1496 1: t1+0
1475 0: null+1
1497 0: null+1
1476
1498
1477 Merged tag overrides:
1499 Merged tag overrides:
1478
1500
1479 $ hg tag -r 5 -m t5 -d '9 0' t5
1501 $ hg tag -r 5 -m t5 -d '9 0' t5
1480 $ hg tag -r 3 -m at3 -d '10 0' at3
1502 $ hg tag -r 3 -m at3 -d '10 0' at3
1481 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1503 $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
1482 10: t5+5
1504 10: t5+5
1483 9: t5+4
1505 9: t5+4
1484 8: t5+3
1506 8: t5+3
1485 7: t5+2
1507 7: t5+2
1486 6: t5+1
1508 6: t5+1
1487 5: t5+0
1509 5: t5+0
1488 4: at3:t3+1
1510 4: at3:t3+1
1489 3: at3:t3+0
1511 3: at3:t3+0
1490 2: t2+0
1512 2: t2+0
1491 1: t1+0
1513 1: t1+0
1492 0: null+1
1514 0: null+1
1493
1515
1494 $ cd ..
1516 $ cd ..
1495
1517
1496
1518
1497 Style path expansion: issue1948 - ui.style option doesn't work on OSX
1519 Style path expansion: issue1948 - ui.style option doesn't work on OSX
1498 if it is a relative path
1520 if it is a relative path
1499
1521
1500 $ mkdir -p home/styles
1522 $ mkdir -p home/styles
1501
1523
1502 $ cat > home/styles/teststyle <<EOF
1524 $ cat > home/styles/teststyle <<EOF
1503 > changeset = 'test {rev}:{node|short}\n'
1525 > changeset = 'test {rev}:{node|short}\n'
1504 > EOF
1526 > EOF
1505
1527
1506 $ HOME=`pwd`/home; export HOME
1528 $ HOME=`pwd`/home; export HOME
1507
1529
1508 $ cat > latesttag/.hg/hgrc <<EOF
1530 $ cat > latesttag/.hg/hgrc <<EOF
1509 > [ui]
1531 > [ui]
1510 > style = ~/styles/teststyle
1532 > style = ~/styles/teststyle
1511 > EOF
1533 > EOF
1512
1534
1513 $ hg -R latesttag tip
1535 $ hg -R latesttag tip
1514 test 10:dee8f28249af
1536 test 10:dee8f28249af
1515
1537
1516 Test recursive showlist template (issue1989):
1538 Test recursive showlist template (issue1989):
1517
1539
1518 $ cat > style1989 <<EOF
1540 $ cat > style1989 <<EOF
1519 > changeset = '{file_mods}{manifest}{extras}'
1541 > changeset = '{file_mods}{manifest}{extras}'
1520 > file_mod = 'M|{author|person}\n'
1542 > file_mod = 'M|{author|person}\n'
1521 > manifest = '{rev},{author}\n'
1543 > manifest = '{rev},{author}\n'
1522 > extra = '{key}: {author}\n'
1544 > extra = '{key}: {author}\n'
1523 > EOF
1545 > EOF
1524
1546
1525 $ hg -R latesttag log -r tip --style=style1989
1547 $ hg -R latesttag log -r tip --style=style1989
1526 M|test
1548 M|test
1527 10,test
1549 10,test
1528 branch: test
1550 branch: test
1529
1551
1530 Test new-style inline templating:
1552 Test new-style inline templating:
1531
1553
1532 $ hg log -R latesttag -r tip --template 'modified files: {file_mods % " {file}\n"}\n'
1554 $ hg log -R latesttag -r tip --template 'modified files: {file_mods % " {file}\n"}\n'
1533 modified files: .hgtags
1555 modified files: .hgtags
1534
1556
1535 Test the sub function of templating for expansion:
1557 Test the sub function of templating for expansion:
1536
1558
1537 $ hg log -R latesttag -r 10 --template '{sub("[0-9]", "x", "{rev}")}\n'
1559 $ hg log -R latesttag -r 10 --template '{sub("[0-9]", "x", "{rev}")}\n'
1538 xx
1560 xx
1539
1561
1540 Test the strip function with chars specified:
1562 Test the strip function with chars specified:
1541
1563
1542 $ hg log -R latesttag --template '{desc}\n'
1564 $ hg log -R latesttag --template '{desc}\n'
1543 at3
1565 at3
1544 t5
1566 t5
1545 t3
1567 t3
1546 t2
1568 t2
1547 t1
1569 t1
1548 merge
1570 merge
1549 h2e
1571 h2e
1550 h2d
1572 h2d
1551 h1c
1573 h1c
1552 b
1574 b
1553 a
1575 a
1554
1576
1555 $ hg log -R latesttag --template '{strip(desc, "te")}\n'
1577 $ hg log -R latesttag --template '{strip(desc, "te")}\n'
1556 at3
1578 at3
1557 5
1579 5
1558 3
1580 3
1559 2
1581 2
1560 1
1582 1
1561 merg
1583 merg
1562 h2
1584 h2
1563 h2d
1585 h2d
1564 h1c
1586 h1c
1565 b
1587 b
1566 a
1588 a
General Comments 0
You need to be logged in to leave comments. Login now