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