##// END OF EJS Templates
templatekw: add verbosity keyword to select template by -q/-v/--debug flag...
Yuya Nishihara -
r34994:625d5ebc default
parent child Browse files
Show More
@@ -1,895 +1,908 b''
1 1 # templatekw.py - common changeset template keywords
2 2 #
3 3 # Copyright 2005-2009 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 __future__ import absolute_import
9 9
10 10 from .i18n import _
11 11 from .node import (
12 12 hex,
13 13 nullid,
14 14 )
15 15
16 16 from . import (
17 17 encoding,
18 18 error,
19 19 hbisect,
20 20 obsutil,
21 21 patch,
22 22 pycompat,
23 23 registrar,
24 24 scmutil,
25 25 util,
26 26 )
27 27
28 28 class _hybrid(object):
29 29 """Wrapper for list or dict to support legacy template
30 30
31 31 This class allows us to handle both:
32 32 - "{files}" (legacy command-line-specific list hack) and
33 33 - "{files % '{file}\n'}" (hgweb-style with inlining and function support)
34 34 and to access raw values:
35 35 - "{ifcontains(file, files, ...)}", "{ifcontains(key, extras, ...)}"
36 36 - "{get(extras, key)}"
37 37 - "{files|json}"
38 38 """
39 39
40 40 def __init__(self, gen, values, makemap, joinfmt, keytype=None):
41 41 if gen is not None:
42 42 self.gen = gen # generator or function returning generator
43 43 self._values = values
44 44 self._makemap = makemap
45 45 self.joinfmt = joinfmt
46 46 self.keytype = keytype # hint for 'x in y' where type(x) is unresolved
47 47 def gen(self):
48 48 """Default generator to stringify this as {join(self, ' ')}"""
49 49 for i, x in enumerate(self._values):
50 50 if i > 0:
51 51 yield ' '
52 52 yield self.joinfmt(x)
53 53 def itermaps(self):
54 54 makemap = self._makemap
55 55 for x in self._values:
56 56 yield makemap(x)
57 57 def __contains__(self, x):
58 58 return x in self._values
59 59 def __getitem__(self, key):
60 60 return self._values[key]
61 61 def __len__(self):
62 62 return len(self._values)
63 63 def __iter__(self):
64 64 return iter(self._values)
65 65 def __getattr__(self, name):
66 66 if name not in ('get', 'items', 'iteritems', 'iterkeys', 'itervalues',
67 67 'keys', 'values'):
68 68 raise AttributeError(name)
69 69 return getattr(self._values, name)
70 70
71 71 class _mappable(object):
72 72 """Wrapper for non-list/dict object to support map operation
73 73
74 74 This class allows us to handle both:
75 75 - "{manifest}"
76 76 - "{manifest % '{rev}:{node}'}"
77 77 - "{manifest.rev}"
78 78
79 79 Unlike a _hybrid, this does not simulate the behavior of the underling
80 80 value. Use unwrapvalue() or unwraphybrid() to obtain the inner object.
81 81 """
82 82
83 83 def __init__(self, gen, key, value, makemap):
84 84 if gen is not None:
85 85 self.gen = gen # generator or function returning generator
86 86 self._key = key
87 87 self._value = value # may be generator of strings
88 88 self._makemap = makemap
89 89
90 90 def gen(self):
91 91 yield pycompat.bytestr(self._value)
92 92
93 93 def tomap(self):
94 94 return self._makemap(self._key)
95 95
96 96 def itermaps(self):
97 97 yield self.tomap()
98 98
99 99 def hybriddict(data, key='key', value='value', fmt='%s=%s', gen=None):
100 100 """Wrap data to support both dict-like and string-like operations"""
101 101 return _hybrid(gen, data, lambda k: {key: k, value: data[k]},
102 102 lambda k: fmt % (k, data[k]))
103 103
104 104 def hybridlist(data, name, fmt='%s', gen=None):
105 105 """Wrap data to support both list-like and string-like operations"""
106 106 return _hybrid(gen, data, lambda x: {name: x}, lambda x: fmt % x)
107 107
108 108 def unwraphybrid(thing):
109 109 """Return an object which can be stringified possibly by using a legacy
110 110 template"""
111 111 gen = getattr(thing, 'gen', None)
112 112 if gen is None:
113 113 return thing
114 114 if callable(gen):
115 115 return gen()
116 116 return gen
117 117
118 118 def unwrapvalue(thing):
119 119 """Move the inner value object out of the wrapper"""
120 120 if not util.safehasattr(thing, '_value'):
121 121 return thing
122 122 return thing._value
123 123
124 124 def wraphybridvalue(container, key, value):
125 125 """Wrap an element of hybrid container to be mappable
126 126
127 127 The key is passed to the makemap function of the given container, which
128 128 should be an item generated by iter(container).
129 129 """
130 130 makemap = getattr(container, '_makemap', None)
131 131 if makemap is None:
132 132 return value
133 133 if util.safehasattr(value, '_makemap'):
134 134 # a nested hybrid list/dict, which has its own way of map operation
135 135 return value
136 136 return _mappable(None, key, value, makemap)
137 137
138 138 def showdict(name, data, mapping, plural=None, key='key', value='value',
139 139 fmt='%s=%s', separator=' '):
140 140 c = [{key: k, value: v} for k, v in data.iteritems()]
141 141 f = _showlist(name, c, mapping, plural, separator)
142 142 return hybriddict(data, key=key, value=value, fmt=fmt, gen=f)
143 143
144 144 def showlist(name, values, mapping, plural=None, element=None, separator=' '):
145 145 if not element:
146 146 element = name
147 147 f = _showlist(name, values, mapping, plural, separator)
148 148 return hybridlist(values, name=element, gen=f)
149 149
150 150 def _showlist(name, values, mapping, plural=None, separator=' '):
151 151 '''expand set of values.
152 152 name is name of key in template map.
153 153 values is list of strings or dicts.
154 154 plural is plural of name, if not simply name + 's'.
155 155 separator is used to join values as a string
156 156
157 157 expansion works like this, given name 'foo'.
158 158
159 159 if values is empty, expand 'no_foos'.
160 160
161 161 if 'foo' not in template map, return values as a string,
162 162 joined by 'separator'.
163 163
164 164 expand 'start_foos'.
165 165
166 166 for each value, expand 'foo'. if 'last_foo' in template
167 167 map, expand it instead of 'foo' for last key.
168 168
169 169 expand 'end_foos'.
170 170 '''
171 171 templ = mapping['templ']
172 172 strmapping = pycompat.strkwargs(mapping)
173 173 if not plural:
174 174 plural = name + 's'
175 175 if not values:
176 176 noname = 'no_' + plural
177 177 if noname in templ:
178 178 yield templ(noname, **strmapping)
179 179 return
180 180 if name not in templ:
181 181 if isinstance(values[0], bytes):
182 182 yield separator.join(values)
183 183 else:
184 184 for v in values:
185 185 yield dict(v, **strmapping)
186 186 return
187 187 startname = 'start_' + plural
188 188 if startname in templ:
189 189 yield templ(startname, **strmapping)
190 190 vmapping = mapping.copy()
191 191 def one(v, tag=name):
192 192 try:
193 193 vmapping.update(v)
194 194 except (AttributeError, ValueError):
195 195 try:
196 196 for a, b in v:
197 197 vmapping[a] = b
198 198 except ValueError:
199 199 vmapping[name] = v
200 200 return templ(tag, **pycompat.strkwargs(vmapping))
201 201 lastname = 'last_' + name
202 202 if lastname in templ:
203 203 last = values.pop()
204 204 else:
205 205 last = None
206 206 for v in values:
207 207 yield one(v)
208 208 if last is not None:
209 209 yield one(last, tag=lastname)
210 210 endname = 'end_' + plural
211 211 if endname in templ:
212 212 yield templ(endname, **strmapping)
213 213
214 214 def getfiles(repo, ctx, revcache):
215 215 if 'files' not in revcache:
216 216 revcache['files'] = repo.status(ctx.p1(), ctx)[:3]
217 217 return revcache['files']
218 218
219 219 def getlatesttags(repo, ctx, cache, pattern=None):
220 220 '''return date, distance and name for the latest tag of rev'''
221 221
222 222 cachename = 'latesttags'
223 223 if pattern is not None:
224 224 cachename += '-' + pattern
225 225 match = util.stringmatcher(pattern)[2]
226 226 else:
227 227 match = util.always
228 228
229 229 if cachename not in cache:
230 230 # Cache mapping from rev to a tuple with tag date, tag
231 231 # distance and tag name
232 232 cache[cachename] = {-1: (0, 0, ['null'])}
233 233 latesttags = cache[cachename]
234 234
235 235 rev = ctx.rev()
236 236 todo = [rev]
237 237 while todo:
238 238 rev = todo.pop()
239 239 if rev in latesttags:
240 240 continue
241 241 ctx = repo[rev]
242 242 tags = [t for t in ctx.tags()
243 243 if (repo.tagtype(t) and repo.tagtype(t) != 'local'
244 244 and match(t))]
245 245 if tags:
246 246 latesttags[rev] = ctx.date()[0], 0, [t for t in sorted(tags)]
247 247 continue
248 248 try:
249 249 ptags = [latesttags[p.rev()] for p in ctx.parents()]
250 250 if len(ptags) > 1:
251 251 if ptags[0][2] == ptags[1][2]:
252 252 # The tuples are laid out so the right one can be found by
253 253 # comparison in this case.
254 254 pdate, pdist, ptag = max(ptags)
255 255 else:
256 256 def key(x):
257 257 changessincetag = len(repo.revs('only(%d, %s)',
258 258 ctx.rev(), x[2][0]))
259 259 # Smallest number of changes since tag wins. Date is
260 260 # used as tiebreaker.
261 261 return [-changessincetag, x[0]]
262 262 pdate, pdist, ptag = max(ptags, key=key)
263 263 else:
264 264 pdate, pdist, ptag = ptags[0]
265 265 except KeyError:
266 266 # Cache miss - recurse
267 267 todo.append(rev)
268 268 todo.extend(p.rev() for p in ctx.parents())
269 269 continue
270 270 latesttags[rev] = pdate, pdist + 1, ptag
271 271 return latesttags[rev]
272 272
273 273 def getrenamedfn(repo, endrev=None):
274 274 rcache = {}
275 275 if endrev is None:
276 276 endrev = len(repo)
277 277
278 278 def getrenamed(fn, rev):
279 279 '''looks up all renames for a file (up to endrev) the first
280 280 time the file is given. It indexes on the changerev and only
281 281 parses the manifest if linkrev != changerev.
282 282 Returns rename info for fn at changerev rev.'''
283 283 if fn not in rcache:
284 284 rcache[fn] = {}
285 285 fl = repo.file(fn)
286 286 for i in fl:
287 287 lr = fl.linkrev(i)
288 288 renamed = fl.renamed(fl.node(i))
289 289 rcache[fn][lr] = renamed
290 290 if lr >= endrev:
291 291 break
292 292 if rev in rcache[fn]:
293 293 return rcache[fn][rev]
294 294
295 295 # If linkrev != rev (i.e. rev not found in rcache) fallback to
296 296 # filectx logic.
297 297 try:
298 298 return repo[rev][fn].renamed()
299 299 except error.LookupError:
300 300 return None
301 301
302 302 return getrenamed
303 303
304 304 # default templates internally used for rendering of lists
305 305 defaulttempl = {
306 306 'parent': '{rev}:{node|formatnode} ',
307 307 'manifest': '{rev}:{node|formatnode}',
308 308 'file_copy': '{name} ({source})',
309 309 'envvar': '{key}={value}',
310 310 'extra': '{key}={value|stringescape}'
311 311 }
312 312 # filecopy is preserved for compatibility reasons
313 313 defaulttempl['filecopy'] = defaulttempl['file_copy']
314 314
315 315 # keywords are callables like:
316 316 # fn(repo, ctx, templ, cache, revcache, **args)
317 317 # with:
318 318 # repo - current repository instance
319 319 # ctx - the changectx being displayed
320 320 # templ - the templater instance
321 321 # cache - a cache dictionary for the whole templater run
322 322 # revcache - a cache dictionary for the current revision
323 323 keywords = {}
324 324
325 325 templatekeyword = registrar.templatekeyword(keywords)
326 326
327 327 @templatekeyword('author')
328 328 def showauthor(repo, ctx, templ, **args):
329 329 """String. The unmodified author of the changeset."""
330 330 return ctx.user()
331 331
332 332 @templatekeyword('bisect')
333 333 def showbisect(repo, ctx, templ, **args):
334 334 """String. The changeset bisection status."""
335 335 return hbisect.label(repo, ctx.node())
336 336
337 337 @templatekeyword('branch')
338 338 def showbranch(**args):
339 339 """String. The name of the branch on which the changeset was
340 340 committed.
341 341 """
342 342 return args[r'ctx'].branch()
343 343
344 344 @templatekeyword('branches')
345 345 def showbranches(**args):
346 346 """List of strings. The name of the branch on which the
347 347 changeset was committed. Will be empty if the branch name was
348 348 default. (DEPRECATED)
349 349 """
350 350 args = pycompat.byteskwargs(args)
351 351 branch = args['ctx'].branch()
352 352 if branch != 'default':
353 353 return showlist('branch', [branch], args, plural='branches')
354 354 return showlist('branch', [], args, plural='branches')
355 355
356 356 @templatekeyword('bookmarks')
357 357 def showbookmarks(**args):
358 358 """List of strings. Any bookmarks associated with the
359 359 changeset. Also sets 'active', the name of the active bookmark.
360 360 """
361 361 args = pycompat.byteskwargs(args)
362 362 repo = args['ctx']._repo
363 363 bookmarks = args['ctx'].bookmarks()
364 364 active = repo._activebookmark
365 365 makemap = lambda v: {'bookmark': v, 'active': active, 'current': active}
366 366 f = _showlist('bookmark', bookmarks, args)
367 367 return _hybrid(f, bookmarks, makemap, pycompat.identity)
368 368
369 369 @templatekeyword('children')
370 370 def showchildren(**args):
371 371 """List of strings. The children of the changeset."""
372 372 args = pycompat.byteskwargs(args)
373 373 ctx = args['ctx']
374 374 childrevs = ['%d:%s' % (cctx, cctx) for cctx in ctx.children()]
375 375 return showlist('children', childrevs, args, element='child')
376 376
377 377 # Deprecated, but kept alive for help generation a purpose.
378 378 @templatekeyword('currentbookmark')
379 379 def showcurrentbookmark(**args):
380 380 """String. The active bookmark, if it is associated with the changeset.
381 381 (DEPRECATED)"""
382 382 return showactivebookmark(**args)
383 383
384 384 @templatekeyword('activebookmark')
385 385 def showactivebookmark(**args):
386 386 """String. The active bookmark, if it is associated with the changeset."""
387 387 active = args[r'repo']._activebookmark
388 388 if active and active in args[r'ctx'].bookmarks():
389 389 return active
390 390 return ''
391 391
392 392 @templatekeyword('date')
393 393 def showdate(repo, ctx, templ, **args):
394 394 """Date information. The date when the changeset was committed."""
395 395 return ctx.date()
396 396
397 397 @templatekeyword('desc')
398 398 def showdescription(repo, ctx, templ, **args):
399 399 """String. The text of the changeset description."""
400 400 s = ctx.description()
401 401 if isinstance(s, encoding.localstr):
402 402 # try hard to preserve utf-8 bytes
403 403 return encoding.tolocal(encoding.fromlocal(s).strip())
404 404 else:
405 405 return s.strip()
406 406
407 407 @templatekeyword('diffstat')
408 408 def showdiffstat(repo, ctx, templ, **args):
409 409 """String. Statistics of changes with the following format:
410 410 "modified files: +added/-removed lines"
411 411 """
412 412 stats = patch.diffstatdata(util.iterlines(ctx.diff(noprefix=False)))
413 413 maxname, maxtotal, adds, removes, binary = patch.diffstatsum(stats)
414 414 return '%s: +%s/-%s' % (len(stats), adds, removes)
415 415
416 416 @templatekeyword('envvars')
417 417 def showenvvars(repo, **args):
418 418 """A dictionary of environment variables. (EXPERIMENTAL)"""
419 419 args = pycompat.byteskwargs(args)
420 420 env = repo.ui.exportableenviron()
421 421 env = util.sortdict((k, env[k]) for k in sorted(env))
422 422 return showdict('envvar', env, args, plural='envvars')
423 423
424 424 @templatekeyword('extras')
425 425 def showextras(**args):
426 426 """List of dicts with key, value entries of the 'extras'
427 427 field of this changeset."""
428 428 args = pycompat.byteskwargs(args)
429 429 extras = args['ctx'].extra()
430 430 extras = util.sortdict((k, extras[k]) for k in sorted(extras))
431 431 makemap = lambda k: {'key': k, 'value': extras[k]}
432 432 c = [makemap(k) for k in extras]
433 433 f = _showlist('extra', c, args, plural='extras')
434 434 return _hybrid(f, extras, makemap,
435 435 lambda k: '%s=%s' % (k, util.escapestr(extras[k])))
436 436
437 437 @templatekeyword('file_adds')
438 438 def showfileadds(**args):
439 439 """List of strings. Files added by this changeset."""
440 440 args = pycompat.byteskwargs(args)
441 441 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
442 442 return showlist('file_add', getfiles(repo, ctx, revcache)[1], args,
443 443 element='file')
444 444
445 445 @templatekeyword('file_copies')
446 446 def showfilecopies(**args):
447 447 """List of strings. Files copied in this changeset with
448 448 their sources.
449 449 """
450 450 args = pycompat.byteskwargs(args)
451 451 cache, ctx = args['cache'], args['ctx']
452 452 copies = args['revcache'].get('copies')
453 453 if copies is None:
454 454 if 'getrenamed' not in cache:
455 455 cache['getrenamed'] = getrenamedfn(args['repo'])
456 456 copies = []
457 457 getrenamed = cache['getrenamed']
458 458 for fn in ctx.files():
459 459 rename = getrenamed(fn, ctx.rev())
460 460 if rename:
461 461 copies.append((fn, rename[0]))
462 462
463 463 copies = util.sortdict(copies)
464 464 return showdict('file_copy', copies, args, plural='file_copies',
465 465 key='name', value='source', fmt='%s (%s)')
466 466
467 467 # showfilecopiesswitch() displays file copies only if copy records are
468 468 # provided before calling the templater, usually with a --copies
469 469 # command line switch.
470 470 @templatekeyword('file_copies_switch')
471 471 def showfilecopiesswitch(**args):
472 472 """List of strings. Like "file_copies" but displayed
473 473 only if the --copied switch is set.
474 474 """
475 475 args = pycompat.byteskwargs(args)
476 476 copies = args['revcache'].get('copies') or []
477 477 copies = util.sortdict(copies)
478 478 return showdict('file_copy', copies, args, plural='file_copies',
479 479 key='name', value='source', fmt='%s (%s)')
480 480
481 481 @templatekeyword('file_dels')
482 482 def showfiledels(**args):
483 483 """List of strings. Files removed by this changeset."""
484 484 args = pycompat.byteskwargs(args)
485 485 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
486 486 return showlist('file_del', getfiles(repo, ctx, revcache)[2], args,
487 487 element='file')
488 488
489 489 @templatekeyword('file_mods')
490 490 def showfilemods(**args):
491 491 """List of strings. Files modified by this changeset."""
492 492 args = pycompat.byteskwargs(args)
493 493 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
494 494 return showlist('file_mod', getfiles(repo, ctx, revcache)[0], args,
495 495 element='file')
496 496
497 497 @templatekeyword('files')
498 498 def showfiles(**args):
499 499 """List of strings. All files modified, added, or removed by this
500 500 changeset.
501 501 """
502 502 args = pycompat.byteskwargs(args)
503 503 return showlist('file', args['ctx'].files(), args)
504 504
505 505 @templatekeyword('graphnode')
506 506 def showgraphnode(repo, ctx, **args):
507 507 """String. The character representing the changeset node in an ASCII
508 508 revision graph."""
509 509 wpnodes = repo.dirstate.parents()
510 510 if wpnodes[1] == nullid:
511 511 wpnodes = wpnodes[:1]
512 512 if ctx.node() in wpnodes:
513 513 return '@'
514 514 elif ctx.obsolete():
515 515 return 'x'
516 516 elif ctx.closesbranch():
517 517 return '_'
518 518 else:
519 519 return 'o'
520 520
521 521 @templatekeyword('graphwidth')
522 522 def showgraphwidth(repo, ctx, templ, **args):
523 523 """Integer. The width of the graph drawn by 'log --graph' or zero."""
524 524 # The value args['graphwidth'] will be this function, so we use an internal
525 525 # name to pass the value through props into this function.
526 526 return args.get('_graphwidth', 0)
527 527
528 528 @templatekeyword('index')
529 529 def showindex(**args):
530 530 """Integer. The current iteration of the loop. (0 indexed)"""
531 531 # just hosts documentation; should be overridden by template mapping
532 532 raise error.Abort(_("can't use index in this context"))
533 533
534 534 @templatekeyword('latesttag')
535 535 def showlatesttag(**args):
536 536 """List of strings. The global tags on the most recent globally
537 537 tagged ancestor of this changeset. If no such tags exist, the list
538 538 consists of the single string "null".
539 539 """
540 540 return showlatesttags(None, **args)
541 541
542 542 def showlatesttags(pattern, **args):
543 543 """helper method for the latesttag keyword and function"""
544 544 args = pycompat.byteskwargs(args)
545 545 repo, ctx = args['repo'], args['ctx']
546 546 cache = args['cache']
547 547 latesttags = getlatesttags(repo, ctx, cache, pattern)
548 548
549 549 # latesttag[0] is an implementation detail for sorting csets on different
550 550 # branches in a stable manner- it is the date the tagged cset was created,
551 551 # not the date the tag was created. Therefore it isn't made visible here.
552 552 makemap = lambda v: {
553 553 'changes': _showchangessincetag,
554 554 'distance': latesttags[1],
555 555 'latesttag': v, # BC with {latesttag % '{latesttag}'}
556 556 'tag': v
557 557 }
558 558
559 559 tags = latesttags[2]
560 560 f = _showlist('latesttag', tags, args, separator=':')
561 561 return _hybrid(f, tags, makemap, pycompat.identity)
562 562
563 563 @templatekeyword('latesttagdistance')
564 564 def showlatesttagdistance(repo, ctx, templ, cache, **args):
565 565 """Integer. Longest path to the latest tag."""
566 566 return getlatesttags(repo, ctx, cache)[1]
567 567
568 568 @templatekeyword('changessincelatesttag')
569 569 def showchangessincelatesttag(repo, ctx, templ, cache, **args):
570 570 """Integer. All ancestors not in the latest tag."""
571 571 latesttag = getlatesttags(repo, ctx, cache)[2][0]
572 572
573 573 return _showchangessincetag(repo, ctx, tag=latesttag, **args)
574 574
575 575 def _showchangessincetag(repo, ctx, **args):
576 576 offset = 0
577 577 revs = [ctx.rev()]
578 578 tag = args[r'tag']
579 579
580 580 # The only() revset doesn't currently support wdir()
581 581 if ctx.rev() is None:
582 582 offset = 1
583 583 revs = [p.rev() for p in ctx.parents()]
584 584
585 585 return len(repo.revs('only(%ld, %s)', revs, tag)) + offset
586 586
587 587 @templatekeyword('manifest')
588 588 def showmanifest(**args):
589 589 repo, ctx, templ = args[r'repo'], args[r'ctx'], args[r'templ']
590 590 mnode = ctx.manifestnode()
591 591 if mnode is None:
592 592 # just avoid crash, we might want to use the 'ff...' hash in future
593 593 return
594 594 mrev = repo.manifestlog._revlog.rev(mnode)
595 595 mhex = hex(mnode)
596 596 args = args.copy()
597 597 args.update({r'rev': mrev, r'node': mhex})
598 598 f = templ('manifest', **args)
599 599 # TODO: perhaps 'ctx' should be dropped from mapping because manifest
600 600 # rev and node are completely different from changeset's.
601 601 return _mappable(f, None, f, lambda x: {'rev': mrev, 'node': mhex})
602 602
603 603 @templatekeyword('obsfate')
604 604 def showobsfate(**args):
605 605 # this function returns a list containing pre-formatted obsfate strings.
606 606 #
607 607 # This function will be replaced by templates fragments when we will have
608 608 # the verbosity templatekw available.
609 609 succsandmarkers = showsuccsandmarkers(**args)
610 610
611 611 ui = args['ui']
612 612
613 613 values = []
614 614
615 615 for x in succsandmarkers:
616 616 values.append(obsutil.obsfateprinter(x['successors'], x['markers'], ui))
617 617
618 618 return showlist("fate", values, args)
619 619
620 620 def shownames(namespace, **args):
621 621 """helper method to generate a template keyword for a namespace"""
622 622 args = pycompat.byteskwargs(args)
623 623 ctx = args['ctx']
624 624 repo = ctx.repo()
625 625 ns = repo.names[namespace]
626 626 names = ns.names(repo, ctx.node())
627 627 return showlist(ns.templatename, names, args, plural=namespace)
628 628
629 629 @templatekeyword('namespaces')
630 630 def shownamespaces(**args):
631 631 """Dict of lists. Names attached to this changeset per
632 632 namespace."""
633 633 args = pycompat.byteskwargs(args)
634 634 ctx = args['ctx']
635 635 repo = ctx.repo()
636 636
637 637 namespaces = util.sortdict()
638 638 def makensmapfn(ns):
639 639 # 'name' for iterating over namespaces, templatename for local reference
640 640 return lambda v: {'name': v, ns.templatename: v}
641 641
642 642 for k, ns in repo.names.iteritems():
643 643 names = ns.names(repo, ctx.node())
644 644 f = _showlist('name', names, args)
645 645 namespaces[k] = _hybrid(f, names, makensmapfn(ns), pycompat.identity)
646 646
647 647 f = _showlist('namespace', list(namespaces), args)
648 648
649 649 def makemap(ns):
650 650 return {
651 651 'namespace': ns,
652 652 'names': namespaces[ns],
653 653 'builtin': repo.names[ns].builtin,
654 654 'colorname': repo.names[ns].colorname,
655 655 }
656 656
657 657 return _hybrid(f, namespaces, makemap, pycompat.identity)
658 658
659 659 @templatekeyword('node')
660 660 def shownode(repo, ctx, templ, **args):
661 661 """String. The changeset identification hash, as a 40 hexadecimal
662 662 digit string.
663 663 """
664 664 return ctx.hex()
665 665
666 666 @templatekeyword('obsolete')
667 667 def showobsolete(repo, ctx, templ, **args):
668 668 """String. Whether the changeset is obsolete. (EXPERIMENTAL)"""
669 669 if ctx.obsolete():
670 670 return 'obsolete'
671 671 return ''
672 672
673 673 @templatekeyword('peerurls')
674 674 def showpeerurls(repo, **args):
675 675 """A dictionary of repository locations defined in the [paths] section
676 676 of your configuration file."""
677 677 # see commands.paths() for naming of dictionary keys
678 678 paths = repo.ui.paths
679 679 urls = util.sortdict((k, p.rawloc) for k, p in sorted(paths.iteritems()))
680 680 def makemap(k):
681 681 p = paths[k]
682 682 d = {'name': k, 'url': p.rawloc}
683 683 d.update((o, v) for o, v in sorted(p.suboptions.iteritems()))
684 684 return d
685 685 return _hybrid(None, urls, makemap, lambda k: '%s=%s' % (k, urls[k]))
686 686
687 687 @templatekeyword("predecessors")
688 688 def showpredecessors(repo, ctx, **args):
689 689 """Returns the list if the closest visible successors. (EXPERIMENTAL)"""
690 690 predecessors = sorted(obsutil.closestpredecessors(repo, ctx.node()))
691 691 predecessors = map(hex, predecessors)
692 692
693 693 return _hybrid(None, predecessors,
694 694 lambda x: {'ctx': repo[x], 'revcache': {}},
695 695 lambda x: scmutil.formatchangeid(repo[x]))
696 696
697 697 @templatekeyword("successorssets")
698 698 def showsuccessorssets(repo, ctx, **args):
699 699 """Returns a string of sets of successors for a changectx. Format used
700 700 is: [ctx1, ctx2], [ctx3] if ctx has been splitted into ctx1 and ctx2
701 701 while also diverged into ctx3. (EXPERIMENTAL)"""
702 702 if not ctx.obsolete():
703 703 return ''
704 704 args = pycompat.byteskwargs(args)
705 705
706 706 ssets = obsutil.successorssets(repo, ctx.node(), closest=True)
707 707 ssets = [[hex(n) for n in ss] for ss in ssets]
708 708
709 709 data = []
710 710 for ss in ssets:
711 711 h = _hybrid(None, ss, lambda x: {'ctx': repo[x], 'revcache': {}},
712 712 lambda x: scmutil.formatchangeid(repo[x]))
713 713 data.append(h)
714 714
715 715 # Format the successorssets
716 716 def render(d):
717 717 t = []
718 718 for i in d.gen():
719 719 t.append(i)
720 720 return "".join(t)
721 721
722 722 def gen(data):
723 723 yield "; ".join(render(d) for d in data)
724 724
725 725 return _hybrid(gen(data), data, lambda x: {'successorset': x},
726 726 pycompat.identity)
727 727
728 728 @templatekeyword("succsandmarkers")
729 729 def showsuccsandmarkers(repo, ctx, **args):
730 730 """Returns a list of dict for each final successor of ctx. The dict
731 731 contains successors node id in "successors" keys and the list of
732 732 obs-markers from ctx to the set of successors in "markers".
733 733 (EXPERIMENTAL)
734 734 """
735 735
736 736 values = obsutil.successorsandmarkers(repo, ctx)
737 737
738 738 if values is None:
739 739 values = []
740 740
741 741 # Format successors and markers to avoid exposing binary to templates
742 742 data = []
743 743 for i in values:
744 744 # Format successors
745 745 successors = i['successors']
746 746
747 747 successors = [hex(n) for n in successors]
748 748 successors = _hybrid(None, successors,
749 749 lambda x: {'ctx': repo[x], 'revcache': {}},
750 750 lambda x: scmutil.formatchangeid(repo[x]))
751 751
752 752 # Format markers
753 753 finalmarkers = []
754 754 for m in i['markers']:
755 755 hexprec = hex(m[0])
756 756 hexsucs = tuple(hex(n) for n in m[1])
757 757 hexparents = None
758 758 if m[5] is not None:
759 759 hexparents = tuple(hex(n) for n in m[5])
760 760 newmarker = (hexprec, hexsucs) + m[2:5] + (hexparents,) + m[6:]
761 761 finalmarkers.append(newmarker)
762 762
763 763 data.append({'successors': successors, 'markers': finalmarkers})
764 764
765 765 f = _showlist('succsandmarkers', data, args)
766 766 return _hybrid(f, data, lambda x: x, pycompat.identity)
767 767
768 768 @templatekeyword('p1rev')
769 769 def showp1rev(repo, ctx, templ, **args):
770 770 """Integer. The repository-local revision number of the changeset's
771 771 first parent, or -1 if the changeset has no parents."""
772 772 return ctx.p1().rev()
773 773
774 774 @templatekeyword('p2rev')
775 775 def showp2rev(repo, ctx, templ, **args):
776 776 """Integer. The repository-local revision number of the changeset's
777 777 second parent, or -1 if the changeset has no second parent."""
778 778 return ctx.p2().rev()
779 779
780 780 @templatekeyword('p1node')
781 781 def showp1node(repo, ctx, templ, **args):
782 782 """String. The identification hash of the changeset's first parent,
783 783 as a 40 digit hexadecimal string. If the changeset has no parents, all
784 784 digits are 0."""
785 785 return ctx.p1().hex()
786 786
787 787 @templatekeyword('p2node')
788 788 def showp2node(repo, ctx, templ, **args):
789 789 """String. The identification hash of the changeset's second
790 790 parent, as a 40 digit hexadecimal string. If the changeset has no second
791 791 parent, all digits are 0."""
792 792 return ctx.p2().hex()
793 793
794 794 @templatekeyword('parents')
795 795 def showparents(**args):
796 796 """List of strings. The parents of the changeset in "rev:node"
797 797 format. If the changeset has only one "natural" parent (the predecessor
798 798 revision) nothing is shown."""
799 799 args = pycompat.byteskwargs(args)
800 800 repo = args['repo']
801 801 ctx = args['ctx']
802 802 pctxs = scmutil.meaningfulparents(repo, ctx)
803 803 prevs = [p.rev() for p in pctxs]
804 804 parents = [[('rev', p.rev()),
805 805 ('node', p.hex()),
806 806 ('phase', p.phasestr())]
807 807 for p in pctxs]
808 808 f = _showlist('parent', parents, args)
809 809 return _hybrid(f, prevs, lambda x: {'ctx': repo[x], 'revcache': {}},
810 810 lambda x: scmutil.formatchangeid(repo[x]), keytype=int)
811 811
812 812 @templatekeyword('phase')
813 813 def showphase(repo, ctx, templ, **args):
814 814 """String. The changeset phase name."""
815 815 return ctx.phasestr()
816 816
817 817 @templatekeyword('phaseidx')
818 818 def showphaseidx(repo, ctx, templ, **args):
819 819 """Integer. The changeset phase index. (ADVANCED)"""
820 820 return ctx.phase()
821 821
822 822 @templatekeyword('rev')
823 823 def showrev(repo, ctx, templ, **args):
824 824 """Integer. The repository-local changeset revision number."""
825 825 return scmutil.intrev(ctx)
826 826
827 827 def showrevslist(name, revs, **args):
828 828 """helper to generate a list of revisions in which a mapped template will
829 829 be evaluated"""
830 830 args = pycompat.byteskwargs(args)
831 831 repo = args['ctx'].repo()
832 832 f = _showlist(name, ['%d' % r for r in revs], args)
833 833 return _hybrid(f, revs,
834 834 lambda x: {name: x, 'ctx': repo[x], 'revcache': {}},
835 835 pycompat.identity, keytype=int)
836 836
837 837 @templatekeyword('subrepos')
838 838 def showsubrepos(**args):
839 839 """List of strings. Updated subrepositories in the changeset."""
840 840 args = pycompat.byteskwargs(args)
841 841 ctx = args['ctx']
842 842 substate = ctx.substate
843 843 if not substate:
844 844 return showlist('subrepo', [], args)
845 845 psubstate = ctx.parents()[0].substate or {}
846 846 subrepos = []
847 847 for sub in substate:
848 848 if sub not in psubstate or substate[sub] != psubstate[sub]:
849 849 subrepos.append(sub) # modified or newly added in ctx
850 850 for sub in psubstate:
851 851 if sub not in substate:
852 852 subrepos.append(sub) # removed in ctx
853 853 return showlist('subrepo', sorted(subrepos), args)
854 854
855 855 # don't remove "showtags" definition, even though namespaces will put
856 856 # a helper function for "tags" keyword into "keywords" map automatically,
857 857 # because online help text is built without namespaces initialization
858 858 @templatekeyword('tags')
859 859 def showtags(**args):
860 860 """List of strings. Any tags associated with the changeset."""
861 861 return shownames('tags', **args)
862 862
863 863 @templatekeyword('termwidth')
864 864 def showtermwidth(repo, ctx, templ, **args):
865 865 """Integer. The width of the current terminal."""
866 866 return repo.ui.termwidth()
867 867
868 868 @templatekeyword('troubles')
869 869 def showtroubles(repo, **args):
870 870 """List of strings. Evolution troubles affecting the changeset.
871 871 (DEPRECATED)
872 872 """
873 873 msg = ("'troubles' is deprecated, "
874 874 "use 'instabilities'")
875 875 repo.ui.deprecwarn(msg, '4.4')
876 876
877 877 return showinstabilities(repo=repo, **args)
878 878
879 879 @templatekeyword('instabilities')
880 880 def showinstabilities(**args):
881 881 """List of strings. Evolution instabilities affecting the changeset.
882 882 (EXPERIMENTAL)
883 883 """
884 884 args = pycompat.byteskwargs(args)
885 885 return showlist('instability', args['ctx'].instabilities(), args,
886 886 plural='instabilities')
887 887
888 @templatekeyword('verbosity')
889 def showverbosity(ui, **args):
890 """String. The current output verbosity in 'debug', 'quiet', 'verbose',
891 or ''."""
892 # see cmdutil.changeset_templater for priority of these flags
893 if ui.debugflag:
894 return 'debug'
895 elif ui.quiet:
896 return 'quiet'
897 elif ui.verbose:
898 return 'verbose'
899 return ''
900
888 901 def loadkeyword(ui, extname, registrarobj):
889 902 """Load template keyword from specified registrarobj
890 903 """
891 904 for name, func in registrarobj._table.iteritems():
892 905 keywords[name] = func
893 906
894 907 # tell hggettext to extract docstrings from these functions:
895 908 i18nfunctions = keywords.values()
@@ -1,4696 +1,4707 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 Test arithmetic operators have the right precedence:
33 33
34 34 $ hg log -l 1 -T '{date(date, "%Y") + 5 * 10} {date(date, "%Y") - 2 * 3}\n'
35 35 2020 1964
36 36 $ hg log -l 1 -T '{date(date, "%Y") * 5 + 10} {date(date, "%Y") * 3 - 2}\n'
37 37 9860 5908
38 38
39 39 Test division:
40 40
41 41 $ hg debugtemplate -r0 -v '{5 / 2} {mod(5, 2)}\n'
42 42 (template
43 43 (/
44 44 (integer '5')
45 45 (integer '2'))
46 46 (string ' ')
47 47 (func
48 48 (symbol 'mod')
49 49 (list
50 50 (integer '5')
51 51 (integer '2')))
52 52 (string '\n'))
53 53 2 1
54 54 $ hg debugtemplate -r0 -v '{5 / -2} {mod(5, -2)}\n'
55 55 (template
56 56 (/
57 57 (integer '5')
58 58 (negate
59 59 (integer '2')))
60 60 (string ' ')
61 61 (func
62 62 (symbol 'mod')
63 63 (list
64 64 (integer '5')
65 65 (negate
66 66 (integer '2'))))
67 67 (string '\n'))
68 68 -3 -1
69 69 $ hg debugtemplate -r0 -v '{-5 / 2} {mod(-5, 2)}\n'
70 70 (template
71 71 (/
72 72 (negate
73 73 (integer '5'))
74 74 (integer '2'))
75 75 (string ' ')
76 76 (func
77 77 (symbol 'mod')
78 78 (list
79 79 (negate
80 80 (integer '5'))
81 81 (integer '2')))
82 82 (string '\n'))
83 83 -3 1
84 84 $ hg debugtemplate -r0 -v '{-5 / -2} {mod(-5, -2)}\n'
85 85 (template
86 86 (/
87 87 (negate
88 88 (integer '5'))
89 89 (negate
90 90 (integer '2')))
91 91 (string ' ')
92 92 (func
93 93 (symbol 'mod')
94 94 (list
95 95 (negate
96 96 (integer '5'))
97 97 (negate
98 98 (integer '2'))))
99 99 (string '\n'))
100 100 2 -1
101 101
102 102 Filters bind closer than arithmetic:
103 103
104 104 $ hg debugtemplate -r0 -v '{revset(".")|count - 1}\n'
105 105 (template
106 106 (-
107 107 (|
108 108 (func
109 109 (symbol 'revset')
110 110 (string '.'))
111 111 (symbol 'count'))
112 112 (integer '1'))
113 113 (string '\n'))
114 114 0
115 115
116 116 But negate binds closer still:
117 117
118 118 $ hg debugtemplate -r0 -v '{1-3|stringify}\n'
119 119 (template
120 120 (-
121 121 (integer '1')
122 122 (|
123 123 (integer '3')
124 124 (symbol 'stringify')))
125 125 (string '\n'))
126 126 hg: parse error: arithmetic only defined on integers
127 127 [255]
128 128 $ hg debugtemplate -r0 -v '{-3|stringify}\n'
129 129 (template
130 130 (|
131 131 (negate
132 132 (integer '3'))
133 133 (symbol 'stringify'))
134 134 (string '\n'))
135 135 -3
136 136
137 137 Filters bind as close as map operator:
138 138
139 139 $ hg debugtemplate -r0 -v '{desc|splitlines % "{line}\n"}'
140 140 (template
141 141 (%
142 142 (|
143 143 (symbol 'desc')
144 144 (symbol 'splitlines'))
145 145 (template
146 146 (symbol 'line')
147 147 (string '\n'))))
148 148 line 1
149 149 line 2
150 150
151 151 Keyword arguments:
152 152
153 153 $ hg debugtemplate -r0 -v '{foo=bar|baz}'
154 154 (template
155 155 (keyvalue
156 156 (symbol 'foo')
157 157 (|
158 158 (symbol 'bar')
159 159 (symbol 'baz'))))
160 160 hg: parse error: can't use a key-value pair in this context
161 161 [255]
162 162
163 163 $ hg debugtemplate '{pad("foo", width=10, left=true)}\n'
164 164 foo
165 165
166 166 Call function which takes named arguments by filter syntax:
167 167
168 168 $ hg debugtemplate '{" "|separate}'
169 169 $ hg debugtemplate '{("not", "an", "argument", "list")|separate}'
170 170 hg: parse error: unknown method 'list'
171 171 [255]
172 172
173 173 Second branch starting at nullrev:
174 174
175 175 $ hg update null
176 176 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
177 177 $ echo second > second
178 178 $ hg add second
179 179 $ hg commit -m second -d '1000000 0' -u 'User Name <user@hostname>'
180 180 created new head
181 181
182 182 $ echo third > third
183 183 $ hg add third
184 184 $ hg mv second fourth
185 185 $ hg commit -m third -d "2020-01-01 10:01"
186 186
187 187 $ hg log --template '{join(file_copies, ",\n")}\n' -r .
188 188 fourth (second)
189 189 $ hg log -T '{file_copies % "{source} -> {name}\n"}' -r .
190 190 second -> fourth
191 191 $ hg log -T '{rev} {ifcontains("fourth", file_copies, "t", "f")}\n' -r .:7
192 192 8 t
193 193 7 f
194 194
195 195 Working-directory revision has special identifiers, though they are still
196 196 experimental:
197 197
198 198 $ hg log -r 'wdir()' -T '{rev}:{node}\n'
199 199 2147483647:ffffffffffffffffffffffffffffffffffffffff
200 200
201 201 Some keywords are invalid for working-directory revision, but they should
202 202 never cause crash:
203 203
204 204 $ hg log -r 'wdir()' -T '{manifest}\n'
205 205
206 206
207 207 Quoting for ui.logtemplate
208 208
209 209 $ hg tip --config "ui.logtemplate={rev}\n"
210 210 8
211 211 $ hg tip --config "ui.logtemplate='{rev}\n'"
212 212 8
213 213 $ hg tip --config 'ui.logtemplate="{rev}\n"'
214 214 8
215 215 $ hg tip --config 'ui.logtemplate=n{rev}\n'
216 216 n8
217 217
218 218 Make sure user/global hgrc does not affect tests
219 219
220 220 $ echo '[ui]' > .hg/hgrc
221 221 $ echo 'logtemplate =' >> .hg/hgrc
222 222 $ echo 'style =' >> .hg/hgrc
223 223
224 224 Add some simple styles to settings
225 225
226 226 $ cat <<'EOF' >> .hg/hgrc
227 227 > [templates]
228 228 > simple = "{rev}\n"
229 229 > simple2 = {rev}\n
230 230 > rev = "should not precede {rev} keyword\n"
231 231 > EOF
232 232
233 233 $ hg log -l1 -Tsimple
234 234 8
235 235 $ hg log -l1 -Tsimple2
236 236 8
237 237 $ hg log -l1 -Trev
238 238 should not precede 8 keyword
239 239 $ hg log -l1 -T '{simple}'
240 240 8
241 241
242 242 Map file shouldn't see user templates:
243 243
244 244 $ cat <<EOF > tmpl
245 245 > changeset = 'nothing expanded:{simple}\n'
246 246 > EOF
247 247 $ hg log -l1 --style ./tmpl
248 248 nothing expanded:
249 249
250 250 Test templates and style maps in files:
251 251
252 252 $ echo "{rev}" > tmpl
253 253 $ hg log -l1 -T./tmpl
254 254 8
255 255 $ hg log -l1 -Tblah/blah
256 256 blah/blah (no-eol)
257 257
258 258 $ printf 'changeset = "{rev}\\n"\n' > map-simple
259 259 $ hg log -l1 -T./map-simple
260 260 8
261 261
262 262 a map file may have [templates] and [templatealias] sections:
263 263
264 264 $ cat <<'EOF' > map-simple
265 265 > [templates]
266 266 > changeset = "{a}\n"
267 267 > [templatealias]
268 268 > a = rev
269 269 > EOF
270 270 $ hg log -l1 -T./map-simple
271 271 8
272 272
273 273 so it can be included in hgrc
274 274
275 275 $ cat <<'EOF' > myhgrc
276 276 > %include map-simple
277 277 > [templates]
278 278 > foo = "{changeset}"
279 279 > EOF
280 280 $ HGRCPATH=./myhgrc hg log -l1 -Tfoo
281 281 8
282 282 $ HGRCPATH=./myhgrc hg log -l1 -T'{a}\n'
283 283 8
284 284
285 285 Test template map inheritance
286 286
287 287 $ echo "__base__ = map-cmdline.default" > map-simple
288 288 $ printf 'cset = "changeset: ***{rev}***\\n"\n' >> map-simple
289 289 $ hg log -l1 -T./map-simple
290 290 changeset: ***8***
291 291 tag: tip
292 292 user: test
293 293 date: Wed Jan 01 10:01:00 2020 +0000
294 294 summary: third
295 295
296 296
297 297 Test docheader, docfooter and separator in template map
298 298
299 299 $ cat <<'EOF' > map-myjson
300 300 > docheader = '\{\n'
301 301 > docfooter = '\n}\n'
302 302 > separator = ',\n'
303 303 > changeset = ' {dict(rev, node|short)|json}'
304 304 > EOF
305 305 $ hg log -l2 -T./map-myjson
306 306 {
307 307 {"node": "95c24699272e", "rev": 8},
308 308 {"node": "29114dbae42b", "rev": 7}
309 309 }
310 310
311 311 Test docheader, docfooter and separator in [templates] section
312 312
313 313 $ cat <<'EOF' >> .hg/hgrc
314 314 > [templates]
315 315 > myjson = ' {dict(rev, node|short)|json}'
316 316 > myjson:docheader = '\{\n'
317 317 > myjson:docfooter = '\n}\n'
318 318 > myjson:separator = ',\n'
319 319 > :docheader = 'should not be selected as a docheader for literal templates\n'
320 320 > EOF
321 321 $ hg log -l2 -Tmyjson
322 322 {
323 323 {"node": "95c24699272e", "rev": 8},
324 324 {"node": "29114dbae42b", "rev": 7}
325 325 }
326 326 $ hg log -l1 -T'{rev}\n'
327 327 8
328 328
329 329 Template should precede style option
330 330
331 331 $ hg log -l1 --style default -T '{rev}\n'
332 332 8
333 333
334 334 Add a commit with empty description, to ensure that the templates
335 335 below will omit the description line.
336 336
337 337 $ echo c >> c
338 338 $ hg add c
339 339 $ hg commit -qm ' '
340 340
341 341 Default style is like normal output. Phases style should be the same
342 342 as default style, except for extra phase lines.
343 343
344 344 $ hg log > log.out
345 345 $ hg log --style default > style.out
346 346 $ cmp log.out style.out || diff -u log.out style.out
347 347 $ hg log -T phases > phases.out
348 348 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
349 349 +phase: draft
350 350 +phase: draft
351 351 +phase: draft
352 352 +phase: draft
353 353 +phase: draft
354 354 +phase: draft
355 355 +phase: draft
356 356 +phase: draft
357 357 +phase: draft
358 358 +phase: draft
359 359
360 360 $ hg log -v > log.out
361 361 $ hg log -v --style default > style.out
362 362 $ cmp log.out style.out || diff -u log.out style.out
363 363 $ hg log -v -T phases > phases.out
364 364 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
365 365 +phase: draft
366 366 +phase: draft
367 367 +phase: draft
368 368 +phase: draft
369 369 +phase: draft
370 370 +phase: draft
371 371 +phase: draft
372 372 +phase: draft
373 373 +phase: draft
374 374 +phase: draft
375 375
376 376 $ hg log -q > log.out
377 377 $ hg log -q --style default > style.out
378 378 $ cmp log.out style.out || diff -u log.out style.out
379 379 $ hg log -q -T phases > phases.out
380 380 $ cmp log.out phases.out || diff -u log.out phases.out
381 381
382 382 $ hg log --debug > log.out
383 383 $ hg log --debug --style default > style.out
384 384 $ cmp log.out style.out || diff -u log.out style.out
385 385 $ hg log --debug -T phases > phases.out
386 386 $ cmp log.out phases.out || diff -u log.out phases.out
387 387
388 388 Default style of working-directory revision should also be the same (but
389 389 date may change while running tests):
390 390
391 391 $ hg log -r 'wdir()' | sed 's|^date:.*|date:|' > log.out
392 392 $ hg log -r 'wdir()' --style default | sed 's|^date:.*|date:|' > style.out
393 393 $ cmp log.out style.out || diff -u log.out style.out
394 394
395 395 $ hg log -r 'wdir()' -v | sed 's|^date:.*|date:|' > log.out
396 396 $ hg log -r 'wdir()' -v --style default | sed 's|^date:.*|date:|' > style.out
397 397 $ cmp log.out style.out || diff -u log.out style.out
398 398
399 399 $ hg log -r 'wdir()' -q > log.out
400 400 $ hg log -r 'wdir()' -q --style default > style.out
401 401 $ cmp log.out style.out || diff -u log.out style.out
402 402
403 403 $ hg log -r 'wdir()' --debug | sed 's|^date:.*|date:|' > log.out
404 404 $ hg log -r 'wdir()' --debug --style default \
405 405 > | sed 's|^date:.*|date:|' > style.out
406 406 $ cmp log.out style.out || diff -u log.out style.out
407 407
408 408 Default style should also preserve color information (issue2866):
409 409
410 410 $ cp $HGRCPATH $HGRCPATH-bak
411 411 $ cat <<EOF >> $HGRCPATH
412 412 > [extensions]
413 413 > color=
414 414 > EOF
415 415
416 416 $ hg --color=debug log > log.out
417 417 $ hg --color=debug log --style default > style.out
418 418 $ cmp log.out style.out || diff -u log.out style.out
419 419 $ hg --color=debug log -T phases > phases.out
420 420 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
421 421 +[log.phase|phase: draft]
422 422 +[log.phase|phase: draft]
423 423 +[log.phase|phase: draft]
424 424 +[log.phase|phase: draft]
425 425 +[log.phase|phase: draft]
426 426 +[log.phase|phase: draft]
427 427 +[log.phase|phase: draft]
428 428 +[log.phase|phase: draft]
429 429 +[log.phase|phase: draft]
430 430 +[log.phase|phase: draft]
431 431
432 432 $ hg --color=debug -v log > log.out
433 433 $ hg --color=debug -v log --style default > style.out
434 434 $ cmp log.out style.out || diff -u log.out style.out
435 435 $ hg --color=debug -v log -T phases > phases.out
436 436 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
437 437 +[log.phase|phase: draft]
438 438 +[log.phase|phase: draft]
439 439 +[log.phase|phase: draft]
440 440 +[log.phase|phase: draft]
441 441 +[log.phase|phase: draft]
442 442 +[log.phase|phase: draft]
443 443 +[log.phase|phase: draft]
444 444 +[log.phase|phase: draft]
445 445 +[log.phase|phase: draft]
446 446 +[log.phase|phase: draft]
447 447
448 448 $ hg --color=debug -q log > log.out
449 449 $ hg --color=debug -q log --style default > style.out
450 450 $ cmp log.out style.out || diff -u log.out style.out
451 451 $ hg --color=debug -q log -T phases > phases.out
452 452 $ cmp log.out phases.out || diff -u log.out phases.out
453 453
454 454 $ hg --color=debug --debug log > log.out
455 455 $ hg --color=debug --debug log --style default > style.out
456 456 $ cmp log.out style.out || diff -u log.out style.out
457 457 $ hg --color=debug --debug log -T phases > phases.out
458 458 $ cmp log.out phases.out || diff -u log.out phases.out
459 459
460 460 $ mv $HGRCPATH-bak $HGRCPATH
461 461
462 462 Remove commit with empty commit message, so as to not pollute further
463 463 tests.
464 464
465 465 $ hg --config extensions.strip= strip -q .
466 466
467 467 Revision with no copies (used to print a traceback):
468 468
469 469 $ hg tip -v --template '\n'
470 470
471 471
472 472 Compact style works:
473 473
474 474 $ hg log -Tcompact
475 475 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
476 476 third
477 477
478 478 7:-1 29114dbae42b 1970-01-12 13:46 +0000 user
479 479 second
480 480
481 481 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
482 482 merge
483 483
484 484 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
485 485 new head
486 486
487 487 4 bbe44766e73d 1970-01-17 04:53 +0000 person
488 488 new branch
489 489
490 490 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
491 491 no user, no domain
492 492
493 493 2 97054abb4ab8 1970-01-14 21:20 +0000 other
494 494 no person
495 495
496 496 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
497 497 other 1
498 498
499 499 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
500 500 line 1
501 501
502 502
503 503 $ hg log -v --style compact
504 504 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
505 505 third
506 506
507 507 7:-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
508 508 second
509 509
510 510 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
511 511 merge
512 512
513 513 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
514 514 new head
515 515
516 516 4 bbe44766e73d 1970-01-17 04:53 +0000 person
517 517 new branch
518 518
519 519 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
520 520 no user, no domain
521 521
522 522 2 97054abb4ab8 1970-01-14 21:20 +0000 other@place
523 523 no person
524 524
525 525 1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
526 526 other 1
527 527 other 2
528 528
529 529 other 3
530 530
531 531 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
532 532 line 1
533 533 line 2
534 534
535 535
536 536 $ hg log --debug --style compact
537 537 8[tip]:7,-1 95c24699272e 2020-01-01 10:01 +0000 test
538 538 third
539 539
540 540 7:-1,-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
541 541 second
542 542
543 543 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
544 544 merge
545 545
546 546 5:3,-1 13207e5a10d9 1970-01-18 08:40 +0000 person
547 547 new head
548 548
549 549 4:3,-1 bbe44766e73d 1970-01-17 04:53 +0000 person
550 550 new branch
551 551
552 552 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
553 553 no user, no domain
554 554
555 555 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other@place
556 556 no person
557 557
558 558 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
559 559 other 1
560 560 other 2
561 561
562 562 other 3
563 563
564 564 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
565 565 line 1
566 566 line 2
567 567
568 568
569 569 Test xml styles:
570 570
571 571 $ hg log --style xml -r 'not all()'
572 572 <?xml version="1.0"?>
573 573 <log>
574 574 </log>
575 575
576 576 $ hg log --style xml
577 577 <?xml version="1.0"?>
578 578 <log>
579 579 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
580 580 <tag>tip</tag>
581 581 <author email="test">test</author>
582 582 <date>2020-01-01T10:01:00+00:00</date>
583 583 <msg xml:space="preserve">third</msg>
584 584 </logentry>
585 585 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
586 586 <parent revision="-1" node="0000000000000000000000000000000000000000" />
587 587 <author email="user@hostname">User Name</author>
588 588 <date>1970-01-12T13:46:40+00:00</date>
589 589 <msg xml:space="preserve">second</msg>
590 590 </logentry>
591 591 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
592 592 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
593 593 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
594 594 <author email="person">person</author>
595 595 <date>1970-01-18T08:40:01+00:00</date>
596 596 <msg xml:space="preserve">merge</msg>
597 597 </logentry>
598 598 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
599 599 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
600 600 <author email="person">person</author>
601 601 <date>1970-01-18T08:40:00+00:00</date>
602 602 <msg xml:space="preserve">new head</msg>
603 603 </logentry>
604 604 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
605 605 <branch>foo</branch>
606 606 <author email="person">person</author>
607 607 <date>1970-01-17T04:53:20+00:00</date>
608 608 <msg xml:space="preserve">new branch</msg>
609 609 </logentry>
610 610 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
611 611 <author email="person">person</author>
612 612 <date>1970-01-16T01:06:40+00:00</date>
613 613 <msg xml:space="preserve">no user, no domain</msg>
614 614 </logentry>
615 615 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
616 616 <author email="other@place">other</author>
617 617 <date>1970-01-14T21:20:00+00:00</date>
618 618 <msg xml:space="preserve">no person</msg>
619 619 </logentry>
620 620 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
621 621 <author email="other@place">A. N. Other</author>
622 622 <date>1970-01-13T17:33:20+00:00</date>
623 623 <msg xml:space="preserve">other 1
624 624 other 2
625 625
626 626 other 3</msg>
627 627 </logentry>
628 628 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
629 629 <author email="user@hostname">User Name</author>
630 630 <date>1970-01-12T13:46:40+00:00</date>
631 631 <msg xml:space="preserve">line 1
632 632 line 2</msg>
633 633 </logentry>
634 634 </log>
635 635
636 636 $ hg log -v --style xml
637 637 <?xml version="1.0"?>
638 638 <log>
639 639 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
640 640 <tag>tip</tag>
641 641 <author email="test">test</author>
642 642 <date>2020-01-01T10:01:00+00:00</date>
643 643 <msg xml:space="preserve">third</msg>
644 644 <paths>
645 645 <path action="A">fourth</path>
646 646 <path action="A">third</path>
647 647 <path action="R">second</path>
648 648 </paths>
649 649 <copies>
650 650 <copy source="second">fourth</copy>
651 651 </copies>
652 652 </logentry>
653 653 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
654 654 <parent revision="-1" node="0000000000000000000000000000000000000000" />
655 655 <author email="user@hostname">User Name</author>
656 656 <date>1970-01-12T13:46:40+00:00</date>
657 657 <msg xml:space="preserve">second</msg>
658 658 <paths>
659 659 <path action="A">second</path>
660 660 </paths>
661 661 </logentry>
662 662 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
663 663 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
664 664 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
665 665 <author email="person">person</author>
666 666 <date>1970-01-18T08:40:01+00:00</date>
667 667 <msg xml:space="preserve">merge</msg>
668 668 <paths>
669 669 </paths>
670 670 </logentry>
671 671 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
672 672 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
673 673 <author email="person">person</author>
674 674 <date>1970-01-18T08:40:00+00:00</date>
675 675 <msg xml:space="preserve">new head</msg>
676 676 <paths>
677 677 <path action="A">d</path>
678 678 </paths>
679 679 </logentry>
680 680 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
681 681 <branch>foo</branch>
682 682 <author email="person">person</author>
683 683 <date>1970-01-17T04:53:20+00:00</date>
684 684 <msg xml:space="preserve">new branch</msg>
685 685 <paths>
686 686 </paths>
687 687 </logentry>
688 688 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
689 689 <author email="person">person</author>
690 690 <date>1970-01-16T01:06:40+00:00</date>
691 691 <msg xml:space="preserve">no user, no domain</msg>
692 692 <paths>
693 693 <path action="M">c</path>
694 694 </paths>
695 695 </logentry>
696 696 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
697 697 <author email="other@place">other</author>
698 698 <date>1970-01-14T21:20:00+00:00</date>
699 699 <msg xml:space="preserve">no person</msg>
700 700 <paths>
701 701 <path action="A">c</path>
702 702 </paths>
703 703 </logentry>
704 704 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
705 705 <author email="other@place">A. N. Other</author>
706 706 <date>1970-01-13T17:33:20+00:00</date>
707 707 <msg xml:space="preserve">other 1
708 708 other 2
709 709
710 710 other 3</msg>
711 711 <paths>
712 712 <path action="A">b</path>
713 713 </paths>
714 714 </logentry>
715 715 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
716 716 <author email="user@hostname">User Name</author>
717 717 <date>1970-01-12T13:46:40+00:00</date>
718 718 <msg xml:space="preserve">line 1
719 719 line 2</msg>
720 720 <paths>
721 721 <path action="A">a</path>
722 722 </paths>
723 723 </logentry>
724 724 </log>
725 725
726 726 $ hg log --debug --style xml
727 727 <?xml version="1.0"?>
728 728 <log>
729 729 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
730 730 <tag>tip</tag>
731 731 <parent revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453" />
732 732 <parent revision="-1" node="0000000000000000000000000000000000000000" />
733 733 <author email="test">test</author>
734 734 <date>2020-01-01T10:01:00+00:00</date>
735 735 <msg xml:space="preserve">third</msg>
736 736 <paths>
737 737 <path action="A">fourth</path>
738 738 <path action="A">third</path>
739 739 <path action="R">second</path>
740 740 </paths>
741 741 <copies>
742 742 <copy source="second">fourth</copy>
743 743 </copies>
744 744 <extra key="branch">default</extra>
745 745 </logentry>
746 746 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
747 747 <parent revision="-1" node="0000000000000000000000000000000000000000" />
748 748 <parent revision="-1" node="0000000000000000000000000000000000000000" />
749 749 <author email="user@hostname">User Name</author>
750 750 <date>1970-01-12T13:46:40+00:00</date>
751 751 <msg xml:space="preserve">second</msg>
752 752 <paths>
753 753 <path action="A">second</path>
754 754 </paths>
755 755 <extra key="branch">default</extra>
756 756 </logentry>
757 757 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
758 758 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
759 759 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
760 760 <author email="person">person</author>
761 761 <date>1970-01-18T08:40:01+00:00</date>
762 762 <msg xml:space="preserve">merge</msg>
763 763 <paths>
764 764 </paths>
765 765 <extra key="branch">default</extra>
766 766 </logentry>
767 767 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
768 768 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
769 769 <parent revision="-1" node="0000000000000000000000000000000000000000" />
770 770 <author email="person">person</author>
771 771 <date>1970-01-18T08:40:00+00:00</date>
772 772 <msg xml:space="preserve">new head</msg>
773 773 <paths>
774 774 <path action="A">d</path>
775 775 </paths>
776 776 <extra key="branch">default</extra>
777 777 </logentry>
778 778 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
779 779 <branch>foo</branch>
780 780 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
781 781 <parent revision="-1" node="0000000000000000000000000000000000000000" />
782 782 <author email="person">person</author>
783 783 <date>1970-01-17T04:53:20+00:00</date>
784 784 <msg xml:space="preserve">new branch</msg>
785 785 <paths>
786 786 </paths>
787 787 <extra key="branch">foo</extra>
788 788 </logentry>
789 789 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
790 790 <parent revision="2" node="97054abb4ab824450e9164180baf491ae0078465" />
791 791 <parent revision="-1" node="0000000000000000000000000000000000000000" />
792 792 <author email="person">person</author>
793 793 <date>1970-01-16T01:06:40+00:00</date>
794 794 <msg xml:space="preserve">no user, no domain</msg>
795 795 <paths>
796 796 <path action="M">c</path>
797 797 </paths>
798 798 <extra key="branch">default</extra>
799 799 </logentry>
800 800 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
801 801 <parent revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965" />
802 802 <parent revision="-1" node="0000000000000000000000000000000000000000" />
803 803 <author email="other@place">other</author>
804 804 <date>1970-01-14T21:20:00+00:00</date>
805 805 <msg xml:space="preserve">no person</msg>
806 806 <paths>
807 807 <path action="A">c</path>
808 808 </paths>
809 809 <extra key="branch">default</extra>
810 810 </logentry>
811 811 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
812 812 <parent revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f" />
813 813 <parent revision="-1" node="0000000000000000000000000000000000000000" />
814 814 <author email="other@place">A. N. Other</author>
815 815 <date>1970-01-13T17:33:20+00:00</date>
816 816 <msg xml:space="preserve">other 1
817 817 other 2
818 818
819 819 other 3</msg>
820 820 <paths>
821 821 <path action="A">b</path>
822 822 </paths>
823 823 <extra key="branch">default</extra>
824 824 </logentry>
825 825 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
826 826 <parent revision="-1" node="0000000000000000000000000000000000000000" />
827 827 <parent revision="-1" node="0000000000000000000000000000000000000000" />
828 828 <author email="user@hostname">User Name</author>
829 829 <date>1970-01-12T13:46:40+00:00</date>
830 830 <msg xml:space="preserve">line 1
831 831 line 2</msg>
832 832 <paths>
833 833 <path action="A">a</path>
834 834 </paths>
835 835 <extra key="branch">default</extra>
836 836 </logentry>
837 837 </log>
838 838
839 839
840 840 Test JSON style:
841 841
842 842 $ hg log -k nosuch -Tjson
843 843 []
844 844
845 845 $ hg log -qr . -Tjson
846 846 [
847 847 {
848 848 "rev": 8,
849 849 "node": "95c24699272ef57d062b8bccc32c878bf841784a"
850 850 }
851 851 ]
852 852
853 853 $ hg log -vpr . -Tjson --stat
854 854 [
855 855 {
856 856 "rev": 8,
857 857 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
858 858 "branch": "default",
859 859 "phase": "draft",
860 860 "user": "test",
861 861 "date": [1577872860, 0],
862 862 "desc": "third",
863 863 "bookmarks": [],
864 864 "tags": ["tip"],
865 865 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
866 866 "files": ["fourth", "second", "third"],
867 867 "diffstat": " fourth | 1 +\n second | 1 -\n third | 1 +\n 3 files changed, 2 insertions(+), 1 deletions(-)\n",
868 868 "diff": "diff -r 29114dbae42b -r 95c24699272e fourth\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/fourth\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+second\ndiff -r 29114dbae42b -r 95c24699272e second\n--- a/second\tMon Jan 12 13:46:40 1970 +0000\n+++ /dev/null\tThu Jan 01 00:00:00 1970 +0000\n@@ -1,1 +0,0 @@\n-second\ndiff -r 29114dbae42b -r 95c24699272e third\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/third\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+third\n"
869 869 }
870 870 ]
871 871
872 872 honor --git but not format-breaking diffopts
873 873 $ hg --config diff.noprefix=True log --git -vpr . -Tjson
874 874 [
875 875 {
876 876 "rev": 8,
877 877 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
878 878 "branch": "default",
879 879 "phase": "draft",
880 880 "user": "test",
881 881 "date": [1577872860, 0],
882 882 "desc": "third",
883 883 "bookmarks": [],
884 884 "tags": ["tip"],
885 885 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
886 886 "files": ["fourth", "second", "third"],
887 887 "diff": "diff --git a/second b/fourth\nrename from second\nrename to fourth\ndiff --git a/third b/third\nnew file mode 100644\n--- /dev/null\n+++ b/third\n@@ -0,0 +1,1 @@\n+third\n"
888 888 }
889 889 ]
890 890
891 891 $ hg log -T json
892 892 [
893 893 {
894 894 "rev": 8,
895 895 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
896 896 "branch": "default",
897 897 "phase": "draft",
898 898 "user": "test",
899 899 "date": [1577872860, 0],
900 900 "desc": "third",
901 901 "bookmarks": [],
902 902 "tags": ["tip"],
903 903 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"]
904 904 },
905 905 {
906 906 "rev": 7,
907 907 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
908 908 "branch": "default",
909 909 "phase": "draft",
910 910 "user": "User Name <user@hostname>",
911 911 "date": [1000000, 0],
912 912 "desc": "second",
913 913 "bookmarks": [],
914 914 "tags": [],
915 915 "parents": ["0000000000000000000000000000000000000000"]
916 916 },
917 917 {
918 918 "rev": 6,
919 919 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
920 920 "branch": "default",
921 921 "phase": "draft",
922 922 "user": "person",
923 923 "date": [1500001, 0],
924 924 "desc": "merge",
925 925 "bookmarks": [],
926 926 "tags": [],
927 927 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"]
928 928 },
929 929 {
930 930 "rev": 5,
931 931 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
932 932 "branch": "default",
933 933 "phase": "draft",
934 934 "user": "person",
935 935 "date": [1500000, 0],
936 936 "desc": "new head",
937 937 "bookmarks": [],
938 938 "tags": [],
939 939 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
940 940 },
941 941 {
942 942 "rev": 4,
943 943 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
944 944 "branch": "foo",
945 945 "phase": "draft",
946 946 "user": "person",
947 947 "date": [1400000, 0],
948 948 "desc": "new branch",
949 949 "bookmarks": [],
950 950 "tags": [],
951 951 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"]
952 952 },
953 953 {
954 954 "rev": 3,
955 955 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
956 956 "branch": "default",
957 957 "phase": "draft",
958 958 "user": "person",
959 959 "date": [1300000, 0],
960 960 "desc": "no user, no domain",
961 961 "bookmarks": [],
962 962 "tags": [],
963 963 "parents": ["97054abb4ab824450e9164180baf491ae0078465"]
964 964 },
965 965 {
966 966 "rev": 2,
967 967 "node": "97054abb4ab824450e9164180baf491ae0078465",
968 968 "branch": "default",
969 969 "phase": "draft",
970 970 "user": "other@place",
971 971 "date": [1200000, 0],
972 972 "desc": "no person",
973 973 "bookmarks": [],
974 974 "tags": [],
975 975 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"]
976 976 },
977 977 {
978 978 "rev": 1,
979 979 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
980 980 "branch": "default",
981 981 "phase": "draft",
982 982 "user": "A. N. Other <other@place>",
983 983 "date": [1100000, 0],
984 984 "desc": "other 1\nother 2\n\nother 3",
985 985 "bookmarks": [],
986 986 "tags": [],
987 987 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"]
988 988 },
989 989 {
990 990 "rev": 0,
991 991 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
992 992 "branch": "default",
993 993 "phase": "draft",
994 994 "user": "User Name <user@hostname>",
995 995 "date": [1000000, 0],
996 996 "desc": "line 1\nline 2",
997 997 "bookmarks": [],
998 998 "tags": [],
999 999 "parents": ["0000000000000000000000000000000000000000"]
1000 1000 }
1001 1001 ]
1002 1002
1003 1003 $ hg heads -v -Tjson
1004 1004 [
1005 1005 {
1006 1006 "rev": 8,
1007 1007 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
1008 1008 "branch": "default",
1009 1009 "phase": "draft",
1010 1010 "user": "test",
1011 1011 "date": [1577872860, 0],
1012 1012 "desc": "third",
1013 1013 "bookmarks": [],
1014 1014 "tags": ["tip"],
1015 1015 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
1016 1016 "files": ["fourth", "second", "third"]
1017 1017 },
1018 1018 {
1019 1019 "rev": 6,
1020 1020 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
1021 1021 "branch": "default",
1022 1022 "phase": "draft",
1023 1023 "user": "person",
1024 1024 "date": [1500001, 0],
1025 1025 "desc": "merge",
1026 1026 "bookmarks": [],
1027 1027 "tags": [],
1028 1028 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
1029 1029 "files": []
1030 1030 },
1031 1031 {
1032 1032 "rev": 4,
1033 1033 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
1034 1034 "branch": "foo",
1035 1035 "phase": "draft",
1036 1036 "user": "person",
1037 1037 "date": [1400000, 0],
1038 1038 "desc": "new branch",
1039 1039 "bookmarks": [],
1040 1040 "tags": [],
1041 1041 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1042 1042 "files": []
1043 1043 }
1044 1044 ]
1045 1045
1046 1046 $ hg log --debug -Tjson
1047 1047 [
1048 1048 {
1049 1049 "rev": 8,
1050 1050 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
1051 1051 "branch": "default",
1052 1052 "phase": "draft",
1053 1053 "user": "test",
1054 1054 "date": [1577872860, 0],
1055 1055 "desc": "third",
1056 1056 "bookmarks": [],
1057 1057 "tags": ["tip"],
1058 1058 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
1059 1059 "manifest": "94961b75a2da554b4df6fb599e5bfc7d48de0c64",
1060 1060 "extra": {"branch": "default"},
1061 1061 "modified": [],
1062 1062 "added": ["fourth", "third"],
1063 1063 "removed": ["second"]
1064 1064 },
1065 1065 {
1066 1066 "rev": 7,
1067 1067 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
1068 1068 "branch": "default",
1069 1069 "phase": "draft",
1070 1070 "user": "User Name <user@hostname>",
1071 1071 "date": [1000000, 0],
1072 1072 "desc": "second",
1073 1073 "bookmarks": [],
1074 1074 "tags": [],
1075 1075 "parents": ["0000000000000000000000000000000000000000"],
1076 1076 "manifest": "f2dbc354b94e5ec0b4f10680ee0cee816101d0bf",
1077 1077 "extra": {"branch": "default"},
1078 1078 "modified": [],
1079 1079 "added": ["second"],
1080 1080 "removed": []
1081 1081 },
1082 1082 {
1083 1083 "rev": 6,
1084 1084 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
1085 1085 "branch": "default",
1086 1086 "phase": "draft",
1087 1087 "user": "person",
1088 1088 "date": [1500001, 0],
1089 1089 "desc": "merge",
1090 1090 "bookmarks": [],
1091 1091 "tags": [],
1092 1092 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
1093 1093 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
1094 1094 "extra": {"branch": "default"},
1095 1095 "modified": [],
1096 1096 "added": [],
1097 1097 "removed": []
1098 1098 },
1099 1099 {
1100 1100 "rev": 5,
1101 1101 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
1102 1102 "branch": "default",
1103 1103 "phase": "draft",
1104 1104 "user": "person",
1105 1105 "date": [1500000, 0],
1106 1106 "desc": "new head",
1107 1107 "bookmarks": [],
1108 1108 "tags": [],
1109 1109 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1110 1110 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
1111 1111 "extra": {"branch": "default"},
1112 1112 "modified": [],
1113 1113 "added": ["d"],
1114 1114 "removed": []
1115 1115 },
1116 1116 {
1117 1117 "rev": 4,
1118 1118 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
1119 1119 "branch": "foo",
1120 1120 "phase": "draft",
1121 1121 "user": "person",
1122 1122 "date": [1400000, 0],
1123 1123 "desc": "new branch",
1124 1124 "bookmarks": [],
1125 1125 "tags": [],
1126 1126 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1127 1127 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
1128 1128 "extra": {"branch": "foo"},
1129 1129 "modified": [],
1130 1130 "added": [],
1131 1131 "removed": []
1132 1132 },
1133 1133 {
1134 1134 "rev": 3,
1135 1135 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
1136 1136 "branch": "default",
1137 1137 "phase": "draft",
1138 1138 "user": "person",
1139 1139 "date": [1300000, 0],
1140 1140 "desc": "no user, no domain",
1141 1141 "bookmarks": [],
1142 1142 "tags": [],
1143 1143 "parents": ["97054abb4ab824450e9164180baf491ae0078465"],
1144 1144 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
1145 1145 "extra": {"branch": "default"},
1146 1146 "modified": ["c"],
1147 1147 "added": [],
1148 1148 "removed": []
1149 1149 },
1150 1150 {
1151 1151 "rev": 2,
1152 1152 "node": "97054abb4ab824450e9164180baf491ae0078465",
1153 1153 "branch": "default",
1154 1154 "phase": "draft",
1155 1155 "user": "other@place",
1156 1156 "date": [1200000, 0],
1157 1157 "desc": "no person",
1158 1158 "bookmarks": [],
1159 1159 "tags": [],
1160 1160 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"],
1161 1161 "manifest": "6e0e82995c35d0d57a52aca8da4e56139e06b4b1",
1162 1162 "extra": {"branch": "default"},
1163 1163 "modified": [],
1164 1164 "added": ["c"],
1165 1165 "removed": []
1166 1166 },
1167 1167 {
1168 1168 "rev": 1,
1169 1169 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
1170 1170 "branch": "default",
1171 1171 "phase": "draft",
1172 1172 "user": "A. N. Other <other@place>",
1173 1173 "date": [1100000, 0],
1174 1174 "desc": "other 1\nother 2\n\nother 3",
1175 1175 "bookmarks": [],
1176 1176 "tags": [],
1177 1177 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"],
1178 1178 "manifest": "4e8d705b1e53e3f9375e0e60dc7b525d8211fe55",
1179 1179 "extra": {"branch": "default"},
1180 1180 "modified": [],
1181 1181 "added": ["b"],
1182 1182 "removed": []
1183 1183 },
1184 1184 {
1185 1185 "rev": 0,
1186 1186 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
1187 1187 "branch": "default",
1188 1188 "phase": "draft",
1189 1189 "user": "User Name <user@hostname>",
1190 1190 "date": [1000000, 0],
1191 1191 "desc": "line 1\nline 2",
1192 1192 "bookmarks": [],
1193 1193 "tags": [],
1194 1194 "parents": ["0000000000000000000000000000000000000000"],
1195 1195 "manifest": "a0c8bcbbb45c63b90b70ad007bf38961f64f2af0",
1196 1196 "extra": {"branch": "default"},
1197 1197 "modified": [],
1198 1198 "added": ["a"],
1199 1199 "removed": []
1200 1200 }
1201 1201 ]
1202 1202
1203 1203 Error if style not readable:
1204 1204
1205 1205 #if unix-permissions no-root
1206 1206 $ touch q
1207 1207 $ chmod 0 q
1208 1208 $ hg log --style ./q
1209 1209 abort: Permission denied: ./q
1210 1210 [255]
1211 1211 #endif
1212 1212
1213 1213 Error if no style:
1214 1214
1215 1215 $ hg log --style notexist
1216 1216 abort: style 'notexist' not found
1217 1217 (available styles: bisect, changelog, compact, default, phases, show, status, xml)
1218 1218 [255]
1219 1219
1220 1220 $ hg log -T list
1221 1221 available styles: bisect, changelog, compact, default, phases, show, status, xml
1222 1222 abort: specify a template
1223 1223 [255]
1224 1224
1225 1225 Error if style missing key:
1226 1226
1227 1227 $ echo 'q = q' > t
1228 1228 $ hg log --style ./t
1229 1229 abort: "changeset" not in template map
1230 1230 [255]
1231 1231
1232 1232 Error if style missing value:
1233 1233
1234 1234 $ echo 'changeset =' > t
1235 1235 $ hg log --style t
1236 1236 hg: parse error at t:1: missing value
1237 1237 [255]
1238 1238
1239 1239 Error if include fails:
1240 1240
1241 1241 $ echo 'changeset = q' >> t
1242 1242 #if unix-permissions no-root
1243 1243 $ hg log --style ./t
1244 1244 abort: template file ./q: Permission denied
1245 1245 [255]
1246 1246 $ rm -f q
1247 1247 #endif
1248 1248
1249 1249 Include works:
1250 1250
1251 1251 $ echo '{rev}' > q
1252 1252 $ hg log --style ./t
1253 1253 8
1254 1254 7
1255 1255 6
1256 1256 5
1257 1257 4
1258 1258 3
1259 1259 2
1260 1260 1
1261 1261 0
1262 1262
1263 1263 Check that recursive reference does not fall into RuntimeError (issue4758):
1264 1264
1265 1265 common mistake:
1266 1266
1267 1267 $ cat << EOF > issue4758
1268 1268 > changeset = '{changeset}\n'
1269 1269 > EOF
1270 1270 $ hg log --style ./issue4758
1271 1271 abort: recursive reference 'changeset' in template
1272 1272 [255]
1273 1273
1274 1274 circular reference:
1275 1275
1276 1276 $ cat << EOF > issue4758
1277 1277 > changeset = '{foo}'
1278 1278 > foo = '{changeset}'
1279 1279 > EOF
1280 1280 $ hg log --style ./issue4758
1281 1281 abort: recursive reference 'foo' in template
1282 1282 [255]
1283 1283
1284 1284 buildmap() -> gettemplate(), where no thunk was made:
1285 1285
1286 1286 $ cat << EOF > issue4758
1287 1287 > changeset = '{files % changeset}\n'
1288 1288 > EOF
1289 1289 $ hg log --style ./issue4758
1290 1290 abort: recursive reference 'changeset' in template
1291 1291 [255]
1292 1292
1293 1293 not a recursion if a keyword of the same name exists:
1294 1294
1295 1295 $ cat << EOF > issue4758
1296 1296 > changeset = '{tags % rev}'
1297 1297 > rev = '{rev} {tag}\n'
1298 1298 > EOF
1299 1299 $ hg log --style ./issue4758 -r tip
1300 1300 8 tip
1301 1301
1302 1302 Check that {phase} works correctly on parents:
1303 1303
1304 1304 $ cat << EOF > parentphase
1305 1305 > changeset_debug = '{rev} ({phase}):{parents}\n'
1306 1306 > parent = ' {rev} ({phase})'
1307 1307 > EOF
1308 1308 $ hg phase -r 5 --public
1309 1309 $ hg phase -r 7 --secret --force
1310 1310 $ hg log --debug -G --style ./parentphase
1311 1311 @ 8 (secret): 7 (secret) -1 (public)
1312 1312 |
1313 1313 o 7 (secret): -1 (public) -1 (public)
1314 1314
1315 1315 o 6 (draft): 5 (public) 4 (draft)
1316 1316 |\
1317 1317 | o 5 (public): 3 (public) -1 (public)
1318 1318 | |
1319 1319 o | 4 (draft): 3 (public) -1 (public)
1320 1320 |/
1321 1321 o 3 (public): 2 (public) -1 (public)
1322 1322 |
1323 1323 o 2 (public): 1 (public) -1 (public)
1324 1324 |
1325 1325 o 1 (public): 0 (public) -1 (public)
1326 1326 |
1327 1327 o 0 (public): -1 (public) -1 (public)
1328 1328
1329 1329
1330 1330 Missing non-standard names give no error (backward compatibility):
1331 1331
1332 1332 $ echo "changeset = '{c}'" > t
1333 1333 $ hg log --style ./t
1334 1334
1335 1335 Defining non-standard name works:
1336 1336
1337 1337 $ cat <<EOF > t
1338 1338 > changeset = '{c}'
1339 1339 > c = q
1340 1340 > EOF
1341 1341 $ hg log --style ./t
1342 1342 8
1343 1343 7
1344 1344 6
1345 1345 5
1346 1346 4
1347 1347 3
1348 1348 2
1349 1349 1
1350 1350 0
1351 1351
1352 1352 ui.style works:
1353 1353
1354 1354 $ echo '[ui]' > .hg/hgrc
1355 1355 $ echo 'style = t' >> .hg/hgrc
1356 1356 $ hg log
1357 1357 8
1358 1358 7
1359 1359 6
1360 1360 5
1361 1361 4
1362 1362 3
1363 1363 2
1364 1364 1
1365 1365 0
1366 1366
1367 1367
1368 1368 Issue338:
1369 1369
1370 1370 $ hg log --style=changelog > changelog
1371 1371
1372 1372 $ cat changelog
1373 1373 2020-01-01 test <test>
1374 1374
1375 1375 * fourth, second, third:
1376 1376 third
1377 1377 [95c24699272e] [tip]
1378 1378
1379 1379 1970-01-12 User Name <user@hostname>
1380 1380
1381 1381 * second:
1382 1382 second
1383 1383 [29114dbae42b]
1384 1384
1385 1385 1970-01-18 person <person>
1386 1386
1387 1387 * merge
1388 1388 [d41e714fe50d]
1389 1389
1390 1390 * d:
1391 1391 new head
1392 1392 [13207e5a10d9]
1393 1393
1394 1394 1970-01-17 person <person>
1395 1395
1396 1396 * new branch
1397 1397 [bbe44766e73d] <foo>
1398 1398
1399 1399 1970-01-16 person <person>
1400 1400
1401 1401 * c:
1402 1402 no user, no domain
1403 1403 [10e46f2dcbf4]
1404 1404
1405 1405 1970-01-14 other <other@place>
1406 1406
1407 1407 * c:
1408 1408 no person
1409 1409 [97054abb4ab8]
1410 1410
1411 1411 1970-01-13 A. N. Other <other@place>
1412 1412
1413 1413 * b:
1414 1414 other 1 other 2
1415 1415
1416 1416 other 3
1417 1417 [b608e9d1a3f0]
1418 1418
1419 1419 1970-01-12 User Name <user@hostname>
1420 1420
1421 1421 * a:
1422 1422 line 1 line 2
1423 1423 [1e4e1b8f71e0]
1424 1424
1425 1425
1426 1426 Issue2130: xml output for 'hg heads' is malformed
1427 1427
1428 1428 $ hg heads --style changelog
1429 1429 2020-01-01 test <test>
1430 1430
1431 1431 * fourth, second, third:
1432 1432 third
1433 1433 [95c24699272e] [tip]
1434 1434
1435 1435 1970-01-18 person <person>
1436 1436
1437 1437 * merge
1438 1438 [d41e714fe50d]
1439 1439
1440 1440 1970-01-17 person <person>
1441 1441
1442 1442 * new branch
1443 1443 [bbe44766e73d] <foo>
1444 1444
1445 1445
1446 1446 Keys work:
1447 1447
1448 1448 $ for key in author branch branches date desc file_adds file_dels file_mods \
1449 1449 > file_copies file_copies_switch files \
1450 1450 > manifest node parents rev tags diffstat extras \
1451 1451 > p1rev p2rev p1node p2node; do
1452 1452 > for mode in '' --verbose --debug; do
1453 1453 > hg log $mode --template "$key$mode: {$key}\n"
1454 1454 > done
1455 1455 > done
1456 1456 author: test
1457 1457 author: User Name <user@hostname>
1458 1458 author: person
1459 1459 author: person
1460 1460 author: person
1461 1461 author: person
1462 1462 author: other@place
1463 1463 author: A. N. Other <other@place>
1464 1464 author: User Name <user@hostname>
1465 1465 author--verbose: test
1466 1466 author--verbose: User Name <user@hostname>
1467 1467 author--verbose: person
1468 1468 author--verbose: person
1469 1469 author--verbose: person
1470 1470 author--verbose: person
1471 1471 author--verbose: other@place
1472 1472 author--verbose: A. N. Other <other@place>
1473 1473 author--verbose: User Name <user@hostname>
1474 1474 author--debug: test
1475 1475 author--debug: User Name <user@hostname>
1476 1476 author--debug: person
1477 1477 author--debug: person
1478 1478 author--debug: person
1479 1479 author--debug: person
1480 1480 author--debug: other@place
1481 1481 author--debug: A. N. Other <other@place>
1482 1482 author--debug: User Name <user@hostname>
1483 1483 branch: default
1484 1484 branch: default
1485 1485 branch: default
1486 1486 branch: default
1487 1487 branch: foo
1488 1488 branch: default
1489 1489 branch: default
1490 1490 branch: default
1491 1491 branch: default
1492 1492 branch--verbose: default
1493 1493 branch--verbose: default
1494 1494 branch--verbose: default
1495 1495 branch--verbose: default
1496 1496 branch--verbose: foo
1497 1497 branch--verbose: default
1498 1498 branch--verbose: default
1499 1499 branch--verbose: default
1500 1500 branch--verbose: default
1501 1501 branch--debug: default
1502 1502 branch--debug: default
1503 1503 branch--debug: default
1504 1504 branch--debug: default
1505 1505 branch--debug: foo
1506 1506 branch--debug: default
1507 1507 branch--debug: default
1508 1508 branch--debug: default
1509 1509 branch--debug: default
1510 1510 branches:
1511 1511 branches:
1512 1512 branches:
1513 1513 branches:
1514 1514 branches: foo
1515 1515 branches:
1516 1516 branches:
1517 1517 branches:
1518 1518 branches:
1519 1519 branches--verbose:
1520 1520 branches--verbose:
1521 1521 branches--verbose:
1522 1522 branches--verbose:
1523 1523 branches--verbose: foo
1524 1524 branches--verbose:
1525 1525 branches--verbose:
1526 1526 branches--verbose:
1527 1527 branches--verbose:
1528 1528 branches--debug:
1529 1529 branches--debug:
1530 1530 branches--debug:
1531 1531 branches--debug:
1532 1532 branches--debug: foo
1533 1533 branches--debug:
1534 1534 branches--debug:
1535 1535 branches--debug:
1536 1536 branches--debug:
1537 1537 date: 1577872860.00
1538 1538 date: 1000000.00
1539 1539 date: 1500001.00
1540 1540 date: 1500000.00
1541 1541 date: 1400000.00
1542 1542 date: 1300000.00
1543 1543 date: 1200000.00
1544 1544 date: 1100000.00
1545 1545 date: 1000000.00
1546 1546 date--verbose: 1577872860.00
1547 1547 date--verbose: 1000000.00
1548 1548 date--verbose: 1500001.00
1549 1549 date--verbose: 1500000.00
1550 1550 date--verbose: 1400000.00
1551 1551 date--verbose: 1300000.00
1552 1552 date--verbose: 1200000.00
1553 1553 date--verbose: 1100000.00
1554 1554 date--verbose: 1000000.00
1555 1555 date--debug: 1577872860.00
1556 1556 date--debug: 1000000.00
1557 1557 date--debug: 1500001.00
1558 1558 date--debug: 1500000.00
1559 1559 date--debug: 1400000.00
1560 1560 date--debug: 1300000.00
1561 1561 date--debug: 1200000.00
1562 1562 date--debug: 1100000.00
1563 1563 date--debug: 1000000.00
1564 1564 desc: third
1565 1565 desc: second
1566 1566 desc: merge
1567 1567 desc: new head
1568 1568 desc: new branch
1569 1569 desc: no user, no domain
1570 1570 desc: no person
1571 1571 desc: other 1
1572 1572 other 2
1573 1573
1574 1574 other 3
1575 1575 desc: line 1
1576 1576 line 2
1577 1577 desc--verbose: third
1578 1578 desc--verbose: second
1579 1579 desc--verbose: merge
1580 1580 desc--verbose: new head
1581 1581 desc--verbose: new branch
1582 1582 desc--verbose: no user, no domain
1583 1583 desc--verbose: no person
1584 1584 desc--verbose: other 1
1585 1585 other 2
1586 1586
1587 1587 other 3
1588 1588 desc--verbose: line 1
1589 1589 line 2
1590 1590 desc--debug: third
1591 1591 desc--debug: second
1592 1592 desc--debug: merge
1593 1593 desc--debug: new head
1594 1594 desc--debug: new branch
1595 1595 desc--debug: no user, no domain
1596 1596 desc--debug: no person
1597 1597 desc--debug: other 1
1598 1598 other 2
1599 1599
1600 1600 other 3
1601 1601 desc--debug: line 1
1602 1602 line 2
1603 1603 file_adds: fourth third
1604 1604 file_adds: second
1605 1605 file_adds:
1606 1606 file_adds: d
1607 1607 file_adds:
1608 1608 file_adds:
1609 1609 file_adds: c
1610 1610 file_adds: b
1611 1611 file_adds: a
1612 1612 file_adds--verbose: fourth third
1613 1613 file_adds--verbose: second
1614 1614 file_adds--verbose:
1615 1615 file_adds--verbose: d
1616 1616 file_adds--verbose:
1617 1617 file_adds--verbose:
1618 1618 file_adds--verbose: c
1619 1619 file_adds--verbose: b
1620 1620 file_adds--verbose: a
1621 1621 file_adds--debug: fourth third
1622 1622 file_adds--debug: second
1623 1623 file_adds--debug:
1624 1624 file_adds--debug: d
1625 1625 file_adds--debug:
1626 1626 file_adds--debug:
1627 1627 file_adds--debug: c
1628 1628 file_adds--debug: b
1629 1629 file_adds--debug: a
1630 1630 file_dels: second
1631 1631 file_dels:
1632 1632 file_dels:
1633 1633 file_dels:
1634 1634 file_dels:
1635 1635 file_dels:
1636 1636 file_dels:
1637 1637 file_dels:
1638 1638 file_dels:
1639 1639 file_dels--verbose: second
1640 1640 file_dels--verbose:
1641 1641 file_dels--verbose:
1642 1642 file_dels--verbose:
1643 1643 file_dels--verbose:
1644 1644 file_dels--verbose:
1645 1645 file_dels--verbose:
1646 1646 file_dels--verbose:
1647 1647 file_dels--verbose:
1648 1648 file_dels--debug: second
1649 1649 file_dels--debug:
1650 1650 file_dels--debug:
1651 1651 file_dels--debug:
1652 1652 file_dels--debug:
1653 1653 file_dels--debug:
1654 1654 file_dels--debug:
1655 1655 file_dels--debug:
1656 1656 file_dels--debug:
1657 1657 file_mods:
1658 1658 file_mods:
1659 1659 file_mods:
1660 1660 file_mods:
1661 1661 file_mods:
1662 1662 file_mods: c
1663 1663 file_mods:
1664 1664 file_mods:
1665 1665 file_mods:
1666 1666 file_mods--verbose:
1667 1667 file_mods--verbose:
1668 1668 file_mods--verbose:
1669 1669 file_mods--verbose:
1670 1670 file_mods--verbose:
1671 1671 file_mods--verbose: c
1672 1672 file_mods--verbose:
1673 1673 file_mods--verbose:
1674 1674 file_mods--verbose:
1675 1675 file_mods--debug:
1676 1676 file_mods--debug:
1677 1677 file_mods--debug:
1678 1678 file_mods--debug:
1679 1679 file_mods--debug:
1680 1680 file_mods--debug: c
1681 1681 file_mods--debug:
1682 1682 file_mods--debug:
1683 1683 file_mods--debug:
1684 1684 file_copies: fourth (second)
1685 1685 file_copies:
1686 1686 file_copies:
1687 1687 file_copies:
1688 1688 file_copies:
1689 1689 file_copies:
1690 1690 file_copies:
1691 1691 file_copies:
1692 1692 file_copies:
1693 1693 file_copies--verbose: fourth (second)
1694 1694 file_copies--verbose:
1695 1695 file_copies--verbose:
1696 1696 file_copies--verbose:
1697 1697 file_copies--verbose:
1698 1698 file_copies--verbose:
1699 1699 file_copies--verbose:
1700 1700 file_copies--verbose:
1701 1701 file_copies--verbose:
1702 1702 file_copies--debug: fourth (second)
1703 1703 file_copies--debug:
1704 1704 file_copies--debug:
1705 1705 file_copies--debug:
1706 1706 file_copies--debug:
1707 1707 file_copies--debug:
1708 1708 file_copies--debug:
1709 1709 file_copies--debug:
1710 1710 file_copies--debug:
1711 1711 file_copies_switch:
1712 1712 file_copies_switch:
1713 1713 file_copies_switch:
1714 1714 file_copies_switch:
1715 1715 file_copies_switch:
1716 1716 file_copies_switch:
1717 1717 file_copies_switch:
1718 1718 file_copies_switch:
1719 1719 file_copies_switch:
1720 1720 file_copies_switch--verbose:
1721 1721 file_copies_switch--verbose:
1722 1722 file_copies_switch--verbose:
1723 1723 file_copies_switch--verbose:
1724 1724 file_copies_switch--verbose:
1725 1725 file_copies_switch--verbose:
1726 1726 file_copies_switch--verbose:
1727 1727 file_copies_switch--verbose:
1728 1728 file_copies_switch--verbose:
1729 1729 file_copies_switch--debug:
1730 1730 file_copies_switch--debug:
1731 1731 file_copies_switch--debug:
1732 1732 file_copies_switch--debug:
1733 1733 file_copies_switch--debug:
1734 1734 file_copies_switch--debug:
1735 1735 file_copies_switch--debug:
1736 1736 file_copies_switch--debug:
1737 1737 file_copies_switch--debug:
1738 1738 files: fourth second third
1739 1739 files: second
1740 1740 files:
1741 1741 files: d
1742 1742 files:
1743 1743 files: c
1744 1744 files: c
1745 1745 files: b
1746 1746 files: a
1747 1747 files--verbose: fourth second third
1748 1748 files--verbose: second
1749 1749 files--verbose:
1750 1750 files--verbose: d
1751 1751 files--verbose:
1752 1752 files--verbose: c
1753 1753 files--verbose: c
1754 1754 files--verbose: b
1755 1755 files--verbose: a
1756 1756 files--debug: fourth second third
1757 1757 files--debug: second
1758 1758 files--debug:
1759 1759 files--debug: d
1760 1760 files--debug:
1761 1761 files--debug: c
1762 1762 files--debug: c
1763 1763 files--debug: b
1764 1764 files--debug: a
1765 1765 manifest: 6:94961b75a2da
1766 1766 manifest: 5:f2dbc354b94e
1767 1767 manifest: 4:4dc3def4f9b4
1768 1768 manifest: 4:4dc3def4f9b4
1769 1769 manifest: 3:cb5a1327723b
1770 1770 manifest: 3:cb5a1327723b
1771 1771 manifest: 2:6e0e82995c35
1772 1772 manifest: 1:4e8d705b1e53
1773 1773 manifest: 0:a0c8bcbbb45c
1774 1774 manifest--verbose: 6:94961b75a2da
1775 1775 manifest--verbose: 5:f2dbc354b94e
1776 1776 manifest--verbose: 4:4dc3def4f9b4
1777 1777 manifest--verbose: 4:4dc3def4f9b4
1778 1778 manifest--verbose: 3:cb5a1327723b
1779 1779 manifest--verbose: 3:cb5a1327723b
1780 1780 manifest--verbose: 2:6e0e82995c35
1781 1781 manifest--verbose: 1:4e8d705b1e53
1782 1782 manifest--verbose: 0:a0c8bcbbb45c
1783 1783 manifest--debug: 6:94961b75a2da554b4df6fb599e5bfc7d48de0c64
1784 1784 manifest--debug: 5:f2dbc354b94e5ec0b4f10680ee0cee816101d0bf
1785 1785 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1786 1786 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
1787 1787 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1788 1788 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1789 1789 manifest--debug: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
1790 1790 manifest--debug: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
1791 1791 manifest--debug: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
1792 1792 node: 95c24699272ef57d062b8bccc32c878bf841784a
1793 1793 node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1794 1794 node: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1795 1795 node: 13207e5a10d9fd28ec424934298e176197f2c67f
1796 1796 node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1797 1797 node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1798 1798 node: 97054abb4ab824450e9164180baf491ae0078465
1799 1799 node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1800 1800 node: 1e4e1b8f71e05681d422154f5421e385fec3454f
1801 1801 node--verbose: 95c24699272ef57d062b8bccc32c878bf841784a
1802 1802 node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1803 1803 node--verbose: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1804 1804 node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
1805 1805 node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1806 1806 node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1807 1807 node--verbose: 97054abb4ab824450e9164180baf491ae0078465
1808 1808 node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1809 1809 node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
1810 1810 node--debug: 95c24699272ef57d062b8bccc32c878bf841784a
1811 1811 node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
1812 1812 node--debug: d41e714fe50d9e4a5f11b4d595d543481b5f980b
1813 1813 node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
1814 1814 node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
1815 1815 node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
1816 1816 node--debug: 97054abb4ab824450e9164180baf491ae0078465
1817 1817 node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1818 1818 node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
1819 1819 parents:
1820 1820 parents: -1:000000000000
1821 1821 parents: 5:13207e5a10d9 4:bbe44766e73d
1822 1822 parents: 3:10e46f2dcbf4
1823 1823 parents:
1824 1824 parents:
1825 1825 parents:
1826 1826 parents:
1827 1827 parents:
1828 1828 parents--verbose:
1829 1829 parents--verbose: -1:000000000000
1830 1830 parents--verbose: 5:13207e5a10d9 4:bbe44766e73d
1831 1831 parents--verbose: 3:10e46f2dcbf4
1832 1832 parents--verbose:
1833 1833 parents--verbose:
1834 1834 parents--verbose:
1835 1835 parents--verbose:
1836 1836 parents--verbose:
1837 1837 parents--debug: 7:29114dbae42b9f078cf2714dbe3a86bba8ec7453 -1:0000000000000000000000000000000000000000
1838 1838 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1839 1839 parents--debug: 5:13207e5a10d9fd28ec424934298e176197f2c67f 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
1840 1840 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1841 1841 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
1842 1842 parents--debug: 2:97054abb4ab824450e9164180baf491ae0078465 -1:0000000000000000000000000000000000000000
1843 1843 parents--debug: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965 -1:0000000000000000000000000000000000000000
1844 1844 parents--debug: 0:1e4e1b8f71e05681d422154f5421e385fec3454f -1:0000000000000000000000000000000000000000
1845 1845 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
1846 1846 rev: 8
1847 1847 rev: 7
1848 1848 rev: 6
1849 1849 rev: 5
1850 1850 rev: 4
1851 1851 rev: 3
1852 1852 rev: 2
1853 1853 rev: 1
1854 1854 rev: 0
1855 1855 rev--verbose: 8
1856 1856 rev--verbose: 7
1857 1857 rev--verbose: 6
1858 1858 rev--verbose: 5
1859 1859 rev--verbose: 4
1860 1860 rev--verbose: 3
1861 1861 rev--verbose: 2
1862 1862 rev--verbose: 1
1863 1863 rev--verbose: 0
1864 1864 rev--debug: 8
1865 1865 rev--debug: 7
1866 1866 rev--debug: 6
1867 1867 rev--debug: 5
1868 1868 rev--debug: 4
1869 1869 rev--debug: 3
1870 1870 rev--debug: 2
1871 1871 rev--debug: 1
1872 1872 rev--debug: 0
1873 1873 tags: tip
1874 1874 tags:
1875 1875 tags:
1876 1876 tags:
1877 1877 tags:
1878 1878 tags:
1879 1879 tags:
1880 1880 tags:
1881 1881 tags:
1882 1882 tags--verbose: tip
1883 1883 tags--verbose:
1884 1884 tags--verbose:
1885 1885 tags--verbose:
1886 1886 tags--verbose:
1887 1887 tags--verbose:
1888 1888 tags--verbose:
1889 1889 tags--verbose:
1890 1890 tags--verbose:
1891 1891 tags--debug: tip
1892 1892 tags--debug:
1893 1893 tags--debug:
1894 1894 tags--debug:
1895 1895 tags--debug:
1896 1896 tags--debug:
1897 1897 tags--debug:
1898 1898 tags--debug:
1899 1899 tags--debug:
1900 1900 diffstat: 3: +2/-1
1901 1901 diffstat: 1: +1/-0
1902 1902 diffstat: 0: +0/-0
1903 1903 diffstat: 1: +1/-0
1904 1904 diffstat: 0: +0/-0
1905 1905 diffstat: 1: +1/-0
1906 1906 diffstat: 1: +4/-0
1907 1907 diffstat: 1: +2/-0
1908 1908 diffstat: 1: +1/-0
1909 1909 diffstat--verbose: 3: +2/-1
1910 1910 diffstat--verbose: 1: +1/-0
1911 1911 diffstat--verbose: 0: +0/-0
1912 1912 diffstat--verbose: 1: +1/-0
1913 1913 diffstat--verbose: 0: +0/-0
1914 1914 diffstat--verbose: 1: +1/-0
1915 1915 diffstat--verbose: 1: +4/-0
1916 1916 diffstat--verbose: 1: +2/-0
1917 1917 diffstat--verbose: 1: +1/-0
1918 1918 diffstat--debug: 3: +2/-1
1919 1919 diffstat--debug: 1: +1/-0
1920 1920 diffstat--debug: 0: +0/-0
1921 1921 diffstat--debug: 1: +1/-0
1922 1922 diffstat--debug: 0: +0/-0
1923 1923 diffstat--debug: 1: +1/-0
1924 1924 diffstat--debug: 1: +4/-0
1925 1925 diffstat--debug: 1: +2/-0
1926 1926 diffstat--debug: 1: +1/-0
1927 1927 extras: branch=default
1928 1928 extras: branch=default
1929 1929 extras: branch=default
1930 1930 extras: branch=default
1931 1931 extras: branch=foo
1932 1932 extras: branch=default
1933 1933 extras: branch=default
1934 1934 extras: branch=default
1935 1935 extras: branch=default
1936 1936 extras--verbose: branch=default
1937 1937 extras--verbose: branch=default
1938 1938 extras--verbose: branch=default
1939 1939 extras--verbose: branch=default
1940 1940 extras--verbose: branch=foo
1941 1941 extras--verbose: branch=default
1942 1942 extras--verbose: branch=default
1943 1943 extras--verbose: branch=default
1944 1944 extras--verbose: branch=default
1945 1945 extras--debug: branch=default
1946 1946 extras--debug: branch=default
1947 1947 extras--debug: branch=default
1948 1948 extras--debug: branch=default
1949 1949 extras--debug: branch=foo
1950 1950 extras--debug: branch=default
1951 1951 extras--debug: branch=default
1952 1952 extras--debug: branch=default
1953 1953 extras--debug: branch=default
1954 1954 p1rev: 7
1955 1955 p1rev: -1
1956 1956 p1rev: 5
1957 1957 p1rev: 3
1958 1958 p1rev: 3
1959 1959 p1rev: 2
1960 1960 p1rev: 1
1961 1961 p1rev: 0
1962 1962 p1rev: -1
1963 1963 p1rev--verbose: 7
1964 1964 p1rev--verbose: -1
1965 1965 p1rev--verbose: 5
1966 1966 p1rev--verbose: 3
1967 1967 p1rev--verbose: 3
1968 1968 p1rev--verbose: 2
1969 1969 p1rev--verbose: 1
1970 1970 p1rev--verbose: 0
1971 1971 p1rev--verbose: -1
1972 1972 p1rev--debug: 7
1973 1973 p1rev--debug: -1
1974 1974 p1rev--debug: 5
1975 1975 p1rev--debug: 3
1976 1976 p1rev--debug: 3
1977 1977 p1rev--debug: 2
1978 1978 p1rev--debug: 1
1979 1979 p1rev--debug: 0
1980 1980 p1rev--debug: -1
1981 1981 p2rev: -1
1982 1982 p2rev: -1
1983 1983 p2rev: 4
1984 1984 p2rev: -1
1985 1985 p2rev: -1
1986 1986 p2rev: -1
1987 1987 p2rev: -1
1988 1988 p2rev: -1
1989 1989 p2rev: -1
1990 1990 p2rev--verbose: -1
1991 1991 p2rev--verbose: -1
1992 1992 p2rev--verbose: 4
1993 1993 p2rev--verbose: -1
1994 1994 p2rev--verbose: -1
1995 1995 p2rev--verbose: -1
1996 1996 p2rev--verbose: -1
1997 1997 p2rev--verbose: -1
1998 1998 p2rev--verbose: -1
1999 1999 p2rev--debug: -1
2000 2000 p2rev--debug: -1
2001 2001 p2rev--debug: 4
2002 2002 p2rev--debug: -1
2003 2003 p2rev--debug: -1
2004 2004 p2rev--debug: -1
2005 2005 p2rev--debug: -1
2006 2006 p2rev--debug: -1
2007 2007 p2rev--debug: -1
2008 2008 p1node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
2009 2009 p1node: 0000000000000000000000000000000000000000
2010 2010 p1node: 13207e5a10d9fd28ec424934298e176197f2c67f
2011 2011 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
2012 2012 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
2013 2013 p1node: 97054abb4ab824450e9164180baf491ae0078465
2014 2014 p1node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2015 2015 p1node: 1e4e1b8f71e05681d422154f5421e385fec3454f
2016 2016 p1node: 0000000000000000000000000000000000000000
2017 2017 p1node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
2018 2018 p1node--verbose: 0000000000000000000000000000000000000000
2019 2019 p1node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
2020 2020 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
2021 2021 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
2022 2022 p1node--verbose: 97054abb4ab824450e9164180baf491ae0078465
2023 2023 p1node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2024 2024 p1node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
2025 2025 p1node--verbose: 0000000000000000000000000000000000000000
2026 2026 p1node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
2027 2027 p1node--debug: 0000000000000000000000000000000000000000
2028 2028 p1node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
2029 2029 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
2030 2030 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
2031 2031 p1node--debug: 97054abb4ab824450e9164180baf491ae0078465
2032 2032 p1node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2033 2033 p1node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
2034 2034 p1node--debug: 0000000000000000000000000000000000000000
2035 2035 p2node: 0000000000000000000000000000000000000000
2036 2036 p2node: 0000000000000000000000000000000000000000
2037 2037 p2node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
2038 2038 p2node: 0000000000000000000000000000000000000000
2039 2039 p2node: 0000000000000000000000000000000000000000
2040 2040 p2node: 0000000000000000000000000000000000000000
2041 2041 p2node: 0000000000000000000000000000000000000000
2042 2042 p2node: 0000000000000000000000000000000000000000
2043 2043 p2node: 0000000000000000000000000000000000000000
2044 2044 p2node--verbose: 0000000000000000000000000000000000000000
2045 2045 p2node--verbose: 0000000000000000000000000000000000000000
2046 2046 p2node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
2047 2047 p2node--verbose: 0000000000000000000000000000000000000000
2048 2048 p2node--verbose: 0000000000000000000000000000000000000000
2049 2049 p2node--verbose: 0000000000000000000000000000000000000000
2050 2050 p2node--verbose: 0000000000000000000000000000000000000000
2051 2051 p2node--verbose: 0000000000000000000000000000000000000000
2052 2052 p2node--verbose: 0000000000000000000000000000000000000000
2053 2053 p2node--debug: 0000000000000000000000000000000000000000
2054 2054 p2node--debug: 0000000000000000000000000000000000000000
2055 2055 p2node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
2056 2056 p2node--debug: 0000000000000000000000000000000000000000
2057 2057 p2node--debug: 0000000000000000000000000000000000000000
2058 2058 p2node--debug: 0000000000000000000000000000000000000000
2059 2059 p2node--debug: 0000000000000000000000000000000000000000
2060 2060 p2node--debug: 0000000000000000000000000000000000000000
2061 2061 p2node--debug: 0000000000000000000000000000000000000000
2062 2062
2063 2063 Filters work:
2064 2064
2065 2065 $ hg log --template '{author|domain}\n'
2066 2066
2067 2067 hostname
2068 2068
2069 2069
2070 2070
2071 2071
2072 2072 place
2073 2073 place
2074 2074 hostname
2075 2075
2076 2076 $ hg log --template '{author|person}\n'
2077 2077 test
2078 2078 User Name
2079 2079 person
2080 2080 person
2081 2081 person
2082 2082 person
2083 2083 other
2084 2084 A. N. Other
2085 2085 User Name
2086 2086
2087 2087 $ hg log --template '{author|user}\n'
2088 2088 test
2089 2089 user
2090 2090 person
2091 2091 person
2092 2092 person
2093 2093 person
2094 2094 other
2095 2095 other
2096 2096 user
2097 2097
2098 2098 $ hg log --template '{date|date}\n'
2099 2099 Wed Jan 01 10:01:00 2020 +0000
2100 2100 Mon Jan 12 13:46:40 1970 +0000
2101 2101 Sun Jan 18 08:40:01 1970 +0000
2102 2102 Sun Jan 18 08:40:00 1970 +0000
2103 2103 Sat Jan 17 04:53:20 1970 +0000
2104 2104 Fri Jan 16 01:06:40 1970 +0000
2105 2105 Wed Jan 14 21:20:00 1970 +0000
2106 2106 Tue Jan 13 17:33:20 1970 +0000
2107 2107 Mon Jan 12 13:46:40 1970 +0000
2108 2108
2109 2109 $ hg log --template '{date|isodate}\n'
2110 2110 2020-01-01 10:01 +0000
2111 2111 1970-01-12 13:46 +0000
2112 2112 1970-01-18 08:40 +0000
2113 2113 1970-01-18 08:40 +0000
2114 2114 1970-01-17 04:53 +0000
2115 2115 1970-01-16 01:06 +0000
2116 2116 1970-01-14 21:20 +0000
2117 2117 1970-01-13 17:33 +0000
2118 2118 1970-01-12 13:46 +0000
2119 2119
2120 2120 $ hg log --template '{date|isodatesec}\n'
2121 2121 2020-01-01 10:01:00 +0000
2122 2122 1970-01-12 13:46:40 +0000
2123 2123 1970-01-18 08:40:01 +0000
2124 2124 1970-01-18 08:40:00 +0000
2125 2125 1970-01-17 04:53:20 +0000
2126 2126 1970-01-16 01:06:40 +0000
2127 2127 1970-01-14 21:20:00 +0000
2128 2128 1970-01-13 17:33:20 +0000
2129 2129 1970-01-12 13:46:40 +0000
2130 2130
2131 2131 $ hg log --template '{date|rfc822date}\n'
2132 2132 Wed, 01 Jan 2020 10:01:00 +0000
2133 2133 Mon, 12 Jan 1970 13:46:40 +0000
2134 2134 Sun, 18 Jan 1970 08:40:01 +0000
2135 2135 Sun, 18 Jan 1970 08:40:00 +0000
2136 2136 Sat, 17 Jan 1970 04:53:20 +0000
2137 2137 Fri, 16 Jan 1970 01:06:40 +0000
2138 2138 Wed, 14 Jan 1970 21:20:00 +0000
2139 2139 Tue, 13 Jan 1970 17:33:20 +0000
2140 2140 Mon, 12 Jan 1970 13:46:40 +0000
2141 2141
2142 2142 $ hg log --template '{desc|firstline}\n'
2143 2143 third
2144 2144 second
2145 2145 merge
2146 2146 new head
2147 2147 new branch
2148 2148 no user, no domain
2149 2149 no person
2150 2150 other 1
2151 2151 line 1
2152 2152
2153 2153 $ hg log --template '{node|short}\n'
2154 2154 95c24699272e
2155 2155 29114dbae42b
2156 2156 d41e714fe50d
2157 2157 13207e5a10d9
2158 2158 bbe44766e73d
2159 2159 10e46f2dcbf4
2160 2160 97054abb4ab8
2161 2161 b608e9d1a3f0
2162 2162 1e4e1b8f71e0
2163 2163
2164 2164 $ hg log --template '<changeset author="{author|xmlescape}"/>\n'
2165 2165 <changeset author="test"/>
2166 2166 <changeset author="User Name &lt;user@hostname&gt;"/>
2167 2167 <changeset author="person"/>
2168 2168 <changeset author="person"/>
2169 2169 <changeset author="person"/>
2170 2170 <changeset author="person"/>
2171 2171 <changeset author="other@place"/>
2172 2172 <changeset author="A. N. Other &lt;other@place&gt;"/>
2173 2173 <changeset author="User Name &lt;user@hostname&gt;"/>
2174 2174
2175 2175 $ hg log --template '{rev}: {children}\n'
2176 2176 8:
2177 2177 7: 8:95c24699272e
2178 2178 6:
2179 2179 5: 6:d41e714fe50d
2180 2180 4: 6:d41e714fe50d
2181 2181 3: 4:bbe44766e73d 5:13207e5a10d9
2182 2182 2: 3:10e46f2dcbf4
2183 2183 1: 2:97054abb4ab8
2184 2184 0: 1:b608e9d1a3f0
2185 2185
2186 2186 Formatnode filter works:
2187 2187
2188 2188 $ hg -q log -r 0 --template '{node|formatnode}\n'
2189 2189 1e4e1b8f71e0
2190 2190
2191 2191 $ hg log -r 0 --template '{node|formatnode}\n'
2192 2192 1e4e1b8f71e0
2193 2193
2194 2194 $ hg -v log -r 0 --template '{node|formatnode}\n'
2195 2195 1e4e1b8f71e0
2196 2196
2197 2197 $ hg --debug log -r 0 --template '{node|formatnode}\n'
2198 2198 1e4e1b8f71e05681d422154f5421e385fec3454f
2199 2199
2200 2200 Age filter:
2201 2201
2202 2202 $ hg init unstable-hash
2203 2203 $ cd unstable-hash
2204 2204 $ hg log --template '{date|age}\n' > /dev/null || exit 1
2205 2205
2206 2206 >>> from __future__ import absolute_import
2207 2207 >>> import datetime
2208 2208 >>> fp = open('a', 'w')
2209 2209 >>> n = datetime.datetime.now() + datetime.timedelta(366 * 7)
2210 2210 >>> fp.write('%d-%d-%d 00:00' % (n.year, n.month, n.day))
2211 2211 >>> fp.close()
2212 2212 $ hg add a
2213 2213 $ hg commit -m future -d "`cat a`"
2214 2214
2215 2215 $ hg log -l1 --template '{date|age}\n'
2216 2216 7 years from now
2217 2217
2218 2218 $ cd ..
2219 2219 $ rm -rf unstable-hash
2220 2220
2221 2221 Add a dummy commit to make up for the instability of the above:
2222 2222
2223 2223 $ echo a > a
2224 2224 $ hg add a
2225 2225 $ hg ci -m future
2226 2226
2227 2227 Count filter:
2228 2228
2229 2229 $ hg log -l1 --template '{node|count} {node|short|count}\n'
2230 2230 40 12
2231 2231
2232 2232 $ hg log -l1 --template '{revset("null^")|count} {revset(".")|count} {revset("0::3")|count}\n'
2233 2233 0 1 4
2234 2234
2235 2235 $ hg log -G --template '{rev}: children: {children|count}, \
2236 2236 > tags: {tags|count}, file_adds: {file_adds|count}, \
2237 2237 > ancestors: {revset("ancestors(%s)", rev)|count}'
2238 2238 @ 9: children: 0, tags: 1, file_adds: 1, ancestors: 3
2239 2239 |
2240 2240 o 8: children: 1, tags: 0, file_adds: 2, ancestors: 2
2241 2241 |
2242 2242 o 7: children: 1, tags: 0, file_adds: 1, ancestors: 1
2243 2243
2244 2244 o 6: children: 0, tags: 0, file_adds: 0, ancestors: 7
2245 2245 |\
2246 2246 | o 5: children: 1, tags: 0, file_adds: 1, ancestors: 5
2247 2247 | |
2248 2248 o | 4: children: 1, tags: 0, file_adds: 0, ancestors: 5
2249 2249 |/
2250 2250 o 3: children: 2, tags: 0, file_adds: 0, ancestors: 4
2251 2251 |
2252 2252 o 2: children: 1, tags: 0, file_adds: 1, ancestors: 3
2253 2253 |
2254 2254 o 1: children: 1, tags: 0, file_adds: 1, ancestors: 2
2255 2255 |
2256 2256 o 0: children: 1, tags: 0, file_adds: 1, ancestors: 1
2257 2257
2258 2258
2259 2259 Upper/lower filters:
2260 2260
2261 2261 $ hg log -r0 --template '{branch|upper}\n'
2262 2262 DEFAULT
2263 2263 $ hg log -r0 --template '{author|lower}\n'
2264 2264 user name <user@hostname>
2265 2265 $ hg log -r0 --template '{date|upper}\n'
2266 2266 abort: template filter 'upper' is not compatible with keyword 'date'
2267 2267 [255]
2268 2268
2269 2269 Add a commit that does all possible modifications at once
2270 2270
2271 2271 $ echo modify >> third
2272 2272 $ touch b
2273 2273 $ hg add b
2274 2274 $ hg mv fourth fifth
2275 2275 $ hg rm a
2276 2276 $ hg ci -m "Modify, add, remove, rename"
2277 2277
2278 2278 Check the status template
2279 2279
2280 2280 $ cat <<EOF >> $HGRCPATH
2281 2281 > [extensions]
2282 2282 > color=
2283 2283 > EOF
2284 2284
2285 2285 $ hg log -T status -r 10
2286 2286 changeset: 10:0f9759ec227a
2287 2287 tag: tip
2288 2288 user: test
2289 2289 date: Thu Jan 01 00:00:00 1970 +0000
2290 2290 summary: Modify, add, remove, rename
2291 2291 files:
2292 2292 M third
2293 2293 A b
2294 2294 A fifth
2295 2295 R a
2296 2296 R fourth
2297 2297
2298 2298 $ hg log -T status -C -r 10
2299 2299 changeset: 10:0f9759ec227a
2300 2300 tag: tip
2301 2301 user: test
2302 2302 date: Thu Jan 01 00:00:00 1970 +0000
2303 2303 summary: Modify, add, remove, rename
2304 2304 files:
2305 2305 M third
2306 2306 A b
2307 2307 A fifth
2308 2308 fourth
2309 2309 R a
2310 2310 R fourth
2311 2311
2312 2312 $ hg log -T status -C -r 10 -v
2313 2313 changeset: 10:0f9759ec227a
2314 2314 tag: tip
2315 2315 user: test
2316 2316 date: Thu Jan 01 00:00:00 1970 +0000
2317 2317 description:
2318 2318 Modify, add, remove, rename
2319 2319
2320 2320 files:
2321 2321 M third
2322 2322 A b
2323 2323 A fifth
2324 2324 fourth
2325 2325 R a
2326 2326 R fourth
2327 2327
2328 2328 $ hg log -T status -C -r 10 --debug
2329 2329 changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c
2330 2330 tag: tip
2331 2331 phase: secret
2332 2332 parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066
2333 2333 parent: -1:0000000000000000000000000000000000000000
2334 2334 manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567
2335 2335 user: test
2336 2336 date: Thu Jan 01 00:00:00 1970 +0000
2337 2337 extra: branch=default
2338 2338 description:
2339 2339 Modify, add, remove, rename
2340 2340
2341 2341 files:
2342 2342 M third
2343 2343 A b
2344 2344 A fifth
2345 2345 fourth
2346 2346 R a
2347 2347 R fourth
2348 2348
2349 2349 $ hg log -T status -C -r 10 --quiet
2350 2350 10:0f9759ec227a
2351 2351 $ hg --color=debug log -T status -r 10
2352 2352 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2353 2353 [log.tag|tag: tip]
2354 2354 [log.user|user: test]
2355 2355 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2356 2356 [log.summary|summary: Modify, add, remove, rename]
2357 2357 [ui.note log.files|files:]
2358 2358 [status.modified|M third]
2359 2359 [status.added|A b]
2360 2360 [status.added|A fifth]
2361 2361 [status.removed|R a]
2362 2362 [status.removed|R fourth]
2363 2363
2364 2364 $ hg --color=debug log -T status -C -r 10
2365 2365 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2366 2366 [log.tag|tag: tip]
2367 2367 [log.user|user: test]
2368 2368 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2369 2369 [log.summary|summary: Modify, add, remove, rename]
2370 2370 [ui.note log.files|files:]
2371 2371 [status.modified|M third]
2372 2372 [status.added|A b]
2373 2373 [status.added|A fifth]
2374 2374 [status.copied| fourth]
2375 2375 [status.removed|R a]
2376 2376 [status.removed|R fourth]
2377 2377
2378 2378 $ hg --color=debug log -T status -C -r 10 -v
2379 2379 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
2380 2380 [log.tag|tag: tip]
2381 2381 [log.user|user: test]
2382 2382 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2383 2383 [ui.note log.description|description:]
2384 2384 [ui.note log.description|Modify, add, remove, rename]
2385 2385
2386 2386 [ui.note log.files|files:]
2387 2387 [status.modified|M third]
2388 2388 [status.added|A b]
2389 2389 [status.added|A fifth]
2390 2390 [status.copied| fourth]
2391 2391 [status.removed|R a]
2392 2392 [status.removed|R fourth]
2393 2393
2394 2394 $ hg --color=debug log -T status -C -r 10 --debug
2395 2395 [log.changeset changeset.secret|changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c]
2396 2396 [log.tag|tag: tip]
2397 2397 [log.phase|phase: secret]
2398 2398 [log.parent changeset.secret|parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066]
2399 2399 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2400 2400 [ui.debug log.manifest|manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567]
2401 2401 [log.user|user: test]
2402 2402 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
2403 2403 [ui.debug log.extra|extra: branch=default]
2404 2404 [ui.note log.description|description:]
2405 2405 [ui.note log.description|Modify, add, remove, rename]
2406 2406
2407 2407 [ui.note log.files|files:]
2408 2408 [status.modified|M third]
2409 2409 [status.added|A b]
2410 2410 [status.added|A fifth]
2411 2411 [status.copied| fourth]
2412 2412 [status.removed|R a]
2413 2413 [status.removed|R fourth]
2414 2414
2415 2415 $ hg --color=debug log -T status -C -r 10 --quiet
2416 2416 [log.node|10:0f9759ec227a]
2417 2417
2418 2418 Check the bisect template
2419 2419
2420 2420 $ hg bisect -g 1
2421 2421 $ hg bisect -b 3 --noupdate
2422 2422 Testing changeset 2:97054abb4ab8 (2 changesets remaining, ~1 tests)
2423 2423 $ hg log -T bisect -r 0:4
2424 2424 changeset: 0:1e4e1b8f71e0
2425 2425 bisect: good (implicit)
2426 2426 user: User Name <user@hostname>
2427 2427 date: Mon Jan 12 13:46:40 1970 +0000
2428 2428 summary: line 1
2429 2429
2430 2430 changeset: 1:b608e9d1a3f0
2431 2431 bisect: good
2432 2432 user: A. N. Other <other@place>
2433 2433 date: Tue Jan 13 17:33:20 1970 +0000
2434 2434 summary: other 1
2435 2435
2436 2436 changeset: 2:97054abb4ab8
2437 2437 bisect: untested
2438 2438 user: other@place
2439 2439 date: Wed Jan 14 21:20:00 1970 +0000
2440 2440 summary: no person
2441 2441
2442 2442 changeset: 3:10e46f2dcbf4
2443 2443 bisect: bad
2444 2444 user: person
2445 2445 date: Fri Jan 16 01:06:40 1970 +0000
2446 2446 summary: no user, no domain
2447 2447
2448 2448 changeset: 4:bbe44766e73d
2449 2449 bisect: bad (implicit)
2450 2450 branch: foo
2451 2451 user: person
2452 2452 date: Sat Jan 17 04:53:20 1970 +0000
2453 2453 summary: new branch
2454 2454
2455 2455 $ hg log --debug -T bisect -r 0:4
2456 2456 changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
2457 2457 bisect: good (implicit)
2458 2458 phase: public
2459 2459 parent: -1:0000000000000000000000000000000000000000
2460 2460 parent: -1:0000000000000000000000000000000000000000
2461 2461 manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
2462 2462 user: User Name <user@hostname>
2463 2463 date: Mon Jan 12 13:46:40 1970 +0000
2464 2464 files+: a
2465 2465 extra: branch=default
2466 2466 description:
2467 2467 line 1
2468 2468 line 2
2469 2469
2470 2470
2471 2471 changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2472 2472 bisect: good
2473 2473 phase: public
2474 2474 parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
2475 2475 parent: -1:0000000000000000000000000000000000000000
2476 2476 manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
2477 2477 user: A. N. Other <other@place>
2478 2478 date: Tue Jan 13 17:33:20 1970 +0000
2479 2479 files+: b
2480 2480 extra: branch=default
2481 2481 description:
2482 2482 other 1
2483 2483 other 2
2484 2484
2485 2485 other 3
2486 2486
2487 2487
2488 2488 changeset: 2:97054abb4ab824450e9164180baf491ae0078465
2489 2489 bisect: untested
2490 2490 phase: public
2491 2491 parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
2492 2492 parent: -1:0000000000000000000000000000000000000000
2493 2493 manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
2494 2494 user: other@place
2495 2495 date: Wed Jan 14 21:20:00 1970 +0000
2496 2496 files+: c
2497 2497 extra: branch=default
2498 2498 description:
2499 2499 no person
2500 2500
2501 2501
2502 2502 changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
2503 2503 bisect: bad
2504 2504 phase: public
2505 2505 parent: 2:97054abb4ab824450e9164180baf491ae0078465
2506 2506 parent: -1:0000000000000000000000000000000000000000
2507 2507 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
2508 2508 user: person
2509 2509 date: Fri Jan 16 01:06:40 1970 +0000
2510 2510 files: c
2511 2511 extra: branch=default
2512 2512 description:
2513 2513 no user, no domain
2514 2514
2515 2515
2516 2516 changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
2517 2517 bisect: bad (implicit)
2518 2518 branch: foo
2519 2519 phase: draft
2520 2520 parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
2521 2521 parent: -1:0000000000000000000000000000000000000000
2522 2522 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
2523 2523 user: person
2524 2524 date: Sat Jan 17 04:53:20 1970 +0000
2525 2525 extra: branch=foo
2526 2526 description:
2527 2527 new branch
2528 2528
2529 2529
2530 2530 $ hg log -v -T bisect -r 0:4
2531 2531 changeset: 0:1e4e1b8f71e0
2532 2532 bisect: good (implicit)
2533 2533 user: User Name <user@hostname>
2534 2534 date: Mon Jan 12 13:46:40 1970 +0000
2535 2535 files: a
2536 2536 description:
2537 2537 line 1
2538 2538 line 2
2539 2539
2540 2540
2541 2541 changeset: 1:b608e9d1a3f0
2542 2542 bisect: good
2543 2543 user: A. N. Other <other@place>
2544 2544 date: Tue Jan 13 17:33:20 1970 +0000
2545 2545 files: b
2546 2546 description:
2547 2547 other 1
2548 2548 other 2
2549 2549
2550 2550 other 3
2551 2551
2552 2552
2553 2553 changeset: 2:97054abb4ab8
2554 2554 bisect: untested
2555 2555 user: other@place
2556 2556 date: Wed Jan 14 21:20:00 1970 +0000
2557 2557 files: c
2558 2558 description:
2559 2559 no person
2560 2560
2561 2561
2562 2562 changeset: 3:10e46f2dcbf4
2563 2563 bisect: bad
2564 2564 user: person
2565 2565 date: Fri Jan 16 01:06:40 1970 +0000
2566 2566 files: c
2567 2567 description:
2568 2568 no user, no domain
2569 2569
2570 2570
2571 2571 changeset: 4:bbe44766e73d
2572 2572 bisect: bad (implicit)
2573 2573 branch: foo
2574 2574 user: person
2575 2575 date: Sat Jan 17 04:53:20 1970 +0000
2576 2576 description:
2577 2577 new branch
2578 2578
2579 2579
2580 2580 $ hg --color=debug log -T bisect -r 0:4
2581 2581 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
2582 2582 [log.bisect bisect.good|bisect: good (implicit)]
2583 2583 [log.user|user: User Name <user@hostname>]
2584 2584 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2585 2585 [log.summary|summary: line 1]
2586 2586
2587 2587 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
2588 2588 [log.bisect bisect.good|bisect: good]
2589 2589 [log.user|user: A. N. Other <other@place>]
2590 2590 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2591 2591 [log.summary|summary: other 1]
2592 2592
2593 2593 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
2594 2594 [log.bisect bisect.untested|bisect: untested]
2595 2595 [log.user|user: other@place]
2596 2596 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2597 2597 [log.summary|summary: no person]
2598 2598
2599 2599 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
2600 2600 [log.bisect bisect.bad|bisect: bad]
2601 2601 [log.user|user: person]
2602 2602 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2603 2603 [log.summary|summary: no user, no domain]
2604 2604
2605 2605 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
2606 2606 [log.bisect bisect.bad|bisect: bad (implicit)]
2607 2607 [log.branch|branch: foo]
2608 2608 [log.user|user: person]
2609 2609 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2610 2610 [log.summary|summary: new branch]
2611 2611
2612 2612 $ hg --color=debug log --debug -T bisect -r 0:4
2613 2613 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
2614 2614 [log.bisect bisect.good|bisect: good (implicit)]
2615 2615 [log.phase|phase: public]
2616 2616 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2617 2617 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2618 2618 [ui.debug log.manifest|manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0]
2619 2619 [log.user|user: User Name <user@hostname>]
2620 2620 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2621 2621 [ui.debug log.files|files+: a]
2622 2622 [ui.debug log.extra|extra: branch=default]
2623 2623 [ui.note log.description|description:]
2624 2624 [ui.note log.description|line 1
2625 2625 line 2]
2626 2626
2627 2627
2628 2628 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
2629 2629 [log.bisect bisect.good|bisect: good]
2630 2630 [log.phase|phase: public]
2631 2631 [log.parent changeset.public|parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
2632 2632 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2633 2633 [ui.debug log.manifest|manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55]
2634 2634 [log.user|user: A. N. Other <other@place>]
2635 2635 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2636 2636 [ui.debug log.files|files+: b]
2637 2637 [ui.debug log.extra|extra: branch=default]
2638 2638 [ui.note log.description|description:]
2639 2639 [ui.note log.description|other 1
2640 2640 other 2
2641 2641
2642 2642 other 3]
2643 2643
2644 2644
2645 2645 [log.changeset changeset.public|changeset: 2:97054abb4ab824450e9164180baf491ae0078465]
2646 2646 [log.bisect bisect.untested|bisect: untested]
2647 2647 [log.phase|phase: public]
2648 2648 [log.parent changeset.public|parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
2649 2649 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2650 2650 [ui.debug log.manifest|manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1]
2651 2651 [log.user|user: other@place]
2652 2652 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2653 2653 [ui.debug log.files|files+: c]
2654 2654 [ui.debug log.extra|extra: branch=default]
2655 2655 [ui.note log.description|description:]
2656 2656 [ui.note log.description|no person]
2657 2657
2658 2658
2659 2659 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
2660 2660 [log.bisect bisect.bad|bisect: bad]
2661 2661 [log.phase|phase: public]
2662 2662 [log.parent changeset.public|parent: 2:97054abb4ab824450e9164180baf491ae0078465]
2663 2663 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2664 2664 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
2665 2665 [log.user|user: person]
2666 2666 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2667 2667 [ui.debug log.files|files: c]
2668 2668 [ui.debug log.extra|extra: branch=default]
2669 2669 [ui.note log.description|description:]
2670 2670 [ui.note log.description|no user, no domain]
2671 2671
2672 2672
2673 2673 [log.changeset changeset.draft|changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74]
2674 2674 [log.bisect bisect.bad|bisect: bad (implicit)]
2675 2675 [log.branch|branch: foo]
2676 2676 [log.phase|phase: draft]
2677 2677 [log.parent changeset.public|parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
2678 2678 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
2679 2679 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
2680 2680 [log.user|user: person]
2681 2681 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2682 2682 [ui.debug log.extra|extra: branch=foo]
2683 2683 [ui.note log.description|description:]
2684 2684 [ui.note log.description|new branch]
2685 2685
2686 2686
2687 2687 $ hg --color=debug log -v -T bisect -r 0:4
2688 2688 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
2689 2689 [log.bisect bisect.good|bisect: good (implicit)]
2690 2690 [log.user|user: User Name <user@hostname>]
2691 2691 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
2692 2692 [ui.note log.files|files: a]
2693 2693 [ui.note log.description|description:]
2694 2694 [ui.note log.description|line 1
2695 2695 line 2]
2696 2696
2697 2697
2698 2698 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
2699 2699 [log.bisect bisect.good|bisect: good]
2700 2700 [log.user|user: A. N. Other <other@place>]
2701 2701 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
2702 2702 [ui.note log.files|files: b]
2703 2703 [ui.note log.description|description:]
2704 2704 [ui.note log.description|other 1
2705 2705 other 2
2706 2706
2707 2707 other 3]
2708 2708
2709 2709
2710 2710 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
2711 2711 [log.bisect bisect.untested|bisect: untested]
2712 2712 [log.user|user: other@place]
2713 2713 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
2714 2714 [ui.note log.files|files: c]
2715 2715 [ui.note log.description|description:]
2716 2716 [ui.note log.description|no person]
2717 2717
2718 2718
2719 2719 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
2720 2720 [log.bisect bisect.bad|bisect: bad]
2721 2721 [log.user|user: person]
2722 2722 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
2723 2723 [ui.note log.files|files: c]
2724 2724 [ui.note log.description|description:]
2725 2725 [ui.note log.description|no user, no domain]
2726 2726
2727 2727
2728 2728 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
2729 2729 [log.bisect bisect.bad|bisect: bad (implicit)]
2730 2730 [log.branch|branch: foo]
2731 2731 [log.user|user: person]
2732 2732 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
2733 2733 [ui.note log.description|description:]
2734 2734 [ui.note log.description|new branch]
2735 2735
2736 2736
2737 2737 $ hg bisect --reset
2738 2738
2739 2739 Error on syntax:
2740 2740
2741 2741 $ echo 'x = "f' >> t
2742 2742 $ hg log
2743 2743 hg: parse error at t:3: unmatched quotes
2744 2744 [255]
2745 2745
2746 2746 $ hg log -T '{date'
2747 2747 hg: parse error at 1: unterminated template expansion
2748 2748 [255]
2749 2749
2750 2750 Behind the scenes, this will throw TypeError
2751 2751
2752 2752 $ hg log -l 3 --template '{date|obfuscate}\n'
2753 2753 abort: template filter 'obfuscate' is not compatible with keyword 'date'
2754 2754 [255]
2755 2755
2756 2756 Behind the scenes, this will throw a ValueError
2757 2757
2758 2758 $ hg log -l 3 --template 'line: {desc|shortdate}\n'
2759 2759 abort: template filter 'shortdate' is not compatible with keyword 'desc'
2760 2760 [255]
2761 2761
2762 2762 Behind the scenes, this will throw AttributeError
2763 2763
2764 2764 $ hg log -l 3 --template 'line: {date|escape}\n'
2765 2765 abort: template filter 'escape' is not compatible with keyword 'date'
2766 2766 [255]
2767 2767
2768 2768 $ hg log -l 3 --template 'line: {extras|localdate}\n'
2769 2769 hg: parse error: localdate expects a date information
2770 2770 [255]
2771 2771
2772 2772 Behind the scenes, this will throw ValueError
2773 2773
2774 2774 $ hg tip --template '{author|email|date}\n'
2775 2775 hg: parse error: date expects a date information
2776 2776 [255]
2777 2777
2778 2778 $ hg tip -T '{author|email|shortdate}\n'
2779 2779 abort: template filter 'shortdate' is not compatible with keyword 'author'
2780 2780 [255]
2781 2781
2782 2782 $ hg tip -T '{get(extras, "branch")|shortdate}\n'
2783 2783 abort: incompatible use of template filter 'shortdate'
2784 2784 [255]
2785 2785
2786 2786 Error in nested template:
2787 2787
2788 2788 $ hg log -T '{"date'
2789 2789 hg: parse error at 2: unterminated string
2790 2790 [255]
2791 2791
2792 2792 $ hg log -T '{"foo{date|?}"}'
2793 2793 hg: parse error at 11: syntax error
2794 2794 [255]
2795 2795
2796 2796 Thrown an error if a template function doesn't exist
2797 2797
2798 2798 $ hg tip --template '{foo()}\n'
2799 2799 hg: parse error: unknown function 'foo'
2800 2800 [255]
2801 2801
2802 2802 Pass generator object created by template function to filter
2803 2803
2804 2804 $ hg log -l 1 --template '{if(author, author)|user}\n'
2805 2805 test
2806 2806
2807 2807 Test index keyword:
2808 2808
2809 2809 $ hg log -l 2 -T '{index + 10}{files % " {index}:{file}"}\n'
2810 2810 10 0:a 1:b 2:fifth 3:fourth 4:third
2811 2811 11 0:a
2812 2812
2813 2813 $ hg branches -T '{index} {branch}\n'
2814 2814 0 default
2815 2815 1 foo
2816 2816
2817 2817 Test diff function:
2818 2818
2819 2819 $ hg diff -c 8
2820 2820 diff -r 29114dbae42b -r 95c24699272e fourth
2821 2821 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2822 2822 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2823 2823 @@ -0,0 +1,1 @@
2824 2824 +second
2825 2825 diff -r 29114dbae42b -r 95c24699272e second
2826 2826 --- a/second Mon Jan 12 13:46:40 1970 +0000
2827 2827 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2828 2828 @@ -1,1 +0,0 @@
2829 2829 -second
2830 2830 diff -r 29114dbae42b -r 95c24699272e third
2831 2831 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2832 2832 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2833 2833 @@ -0,0 +1,1 @@
2834 2834 +third
2835 2835
2836 2836 $ hg log -r 8 -T "{diff()}"
2837 2837 diff -r 29114dbae42b -r 95c24699272e fourth
2838 2838 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2839 2839 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2840 2840 @@ -0,0 +1,1 @@
2841 2841 +second
2842 2842 diff -r 29114dbae42b -r 95c24699272e second
2843 2843 --- a/second Mon Jan 12 13:46:40 1970 +0000
2844 2844 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2845 2845 @@ -1,1 +0,0 @@
2846 2846 -second
2847 2847 diff -r 29114dbae42b -r 95c24699272e third
2848 2848 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2849 2849 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2850 2850 @@ -0,0 +1,1 @@
2851 2851 +third
2852 2852
2853 2853 $ hg log -r 8 -T "{diff('glob:f*')}"
2854 2854 diff -r 29114dbae42b -r 95c24699272e fourth
2855 2855 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2856 2856 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2857 2857 @@ -0,0 +1,1 @@
2858 2858 +second
2859 2859
2860 2860 $ hg log -r 8 -T "{diff('', 'glob:f*')}"
2861 2861 diff -r 29114dbae42b -r 95c24699272e second
2862 2862 --- a/second Mon Jan 12 13:46:40 1970 +0000
2863 2863 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2864 2864 @@ -1,1 +0,0 @@
2865 2865 -second
2866 2866 diff -r 29114dbae42b -r 95c24699272e third
2867 2867 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2868 2868 +++ b/third Wed Jan 01 10:01:00 2020 +0000
2869 2869 @@ -0,0 +1,1 @@
2870 2870 +third
2871 2871
2872 2872 $ hg log -r 8 -T "{diff('FOURTH'|lower)}"
2873 2873 diff -r 29114dbae42b -r 95c24699272e fourth
2874 2874 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2875 2875 +++ b/fourth Wed Jan 01 10:01:00 2020 +0000
2876 2876 @@ -0,0 +1,1 @@
2877 2877 +second
2878 2878
2879 ui verbosity:
2880
2881 $ hg log -l1 -T '{verbosity}\n'
2882
2883 $ hg log -l1 -T '{verbosity}\n' --debug
2884 debug
2885 $ hg log -l1 -T '{verbosity}\n' --quiet
2886 quiet
2887 $ hg log -l1 -T '{verbosity}\n' --verbose
2888 verbose
2889
2879 2890 $ cd ..
2880 2891
2881 2892
2882 2893 latesttag:
2883 2894
2884 2895 $ hg init latesttag
2885 2896 $ cd latesttag
2886 2897
2887 2898 $ echo a > file
2888 2899 $ hg ci -Am a -d '0 0'
2889 2900 adding file
2890 2901
2891 2902 $ echo b >> file
2892 2903 $ hg ci -m b -d '1 0'
2893 2904
2894 2905 $ echo c >> head1
2895 2906 $ hg ci -Am h1c -d '2 0'
2896 2907 adding head1
2897 2908
2898 2909 $ hg update -q 1
2899 2910 $ echo d >> head2
2900 2911 $ hg ci -Am h2d -d '3 0'
2901 2912 adding head2
2902 2913 created new head
2903 2914
2904 2915 $ echo e >> head2
2905 2916 $ hg ci -m h2e -d '4 0'
2906 2917
2907 2918 $ hg merge -q
2908 2919 $ hg ci -m merge -d '5 -3600'
2909 2920
2910 2921 No tag set:
2911 2922
2912 2923 $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
2913 2924 @ 5: null+5
2914 2925 |\
2915 2926 | o 4: null+4
2916 2927 | |
2917 2928 | o 3: null+3
2918 2929 | |
2919 2930 o | 2: null+3
2920 2931 |/
2921 2932 o 1: null+2
2922 2933 |
2923 2934 o 0: null+1
2924 2935
2925 2936
2926 2937 One common tag: longest path wins for {latesttagdistance}:
2927 2938
2928 2939 $ hg tag -r 1 -m t1 -d '6 0' t1
2929 2940 $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
2930 2941 @ 6: t1+4
2931 2942 |
2932 2943 o 5: t1+3
2933 2944 |\
2934 2945 | o 4: t1+2
2935 2946 | |
2936 2947 | o 3: t1+1
2937 2948 | |
2938 2949 o | 2: t1+1
2939 2950 |/
2940 2951 o 1: t1+0
2941 2952 |
2942 2953 o 0: null+1
2943 2954
2944 2955
2945 2956 One ancestor tag: closest wins:
2946 2957
2947 2958 $ hg tag -r 2 -m t2 -d '7 0' t2
2948 2959 $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
2949 2960 @ 7: t2+3
2950 2961 |
2951 2962 o 6: t2+2
2952 2963 |
2953 2964 o 5: t2+1
2954 2965 |\
2955 2966 | o 4: t1+2
2956 2967 | |
2957 2968 | o 3: t1+1
2958 2969 | |
2959 2970 o | 2: t2+0
2960 2971 |/
2961 2972 o 1: t1+0
2962 2973 |
2963 2974 o 0: null+1
2964 2975
2965 2976
2966 2977 Two branch tags: more recent wins if same number of changes:
2967 2978
2968 2979 $ hg tag -r 3 -m t3 -d '8 0' t3
2969 2980 $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
2970 2981 @ 8: t3+5
2971 2982 |
2972 2983 o 7: t3+4
2973 2984 |
2974 2985 o 6: t3+3
2975 2986 |
2976 2987 o 5: t3+2
2977 2988 |\
2978 2989 | o 4: t3+1
2979 2990 | |
2980 2991 | o 3: t3+0
2981 2992 | |
2982 2993 o | 2: t2+0
2983 2994 |/
2984 2995 o 1: t1+0
2985 2996 |
2986 2997 o 0: null+1
2987 2998
2988 2999
2989 3000 Two branch tags: fewest changes wins:
2990 3001
2991 3002 $ hg tag -r 4 -m t4 -d '4 0' t4 # older than t2, but should not matter
2992 3003 $ hg log -G --template "{rev}: {latesttag % '{tag}+{distance},{changes} '}\n"
2993 3004 @ 9: t4+5,6
2994 3005 |
2995 3006 o 8: t4+4,5
2996 3007 |
2997 3008 o 7: t4+3,4
2998 3009 |
2999 3010 o 6: t4+2,3
3000 3011 |
3001 3012 o 5: t4+1,2
3002 3013 |\
3003 3014 | o 4: t4+0,0
3004 3015 | |
3005 3016 | o 3: t3+0,0
3006 3017 | |
3007 3018 o | 2: t2+0,0
3008 3019 |/
3009 3020 o 1: t1+0,0
3010 3021 |
3011 3022 o 0: null+1,1
3012 3023
3013 3024
3014 3025 Merged tag overrides:
3015 3026
3016 3027 $ hg tag -r 5 -m t5 -d '9 0' t5
3017 3028 $ hg tag -r 3 -m at3 -d '10 0' at3
3018 3029 $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
3019 3030 @ 11: t5+6
3020 3031 |
3021 3032 o 10: t5+5
3022 3033 |
3023 3034 o 9: t5+4
3024 3035 |
3025 3036 o 8: t5+3
3026 3037 |
3027 3038 o 7: t5+2
3028 3039 |
3029 3040 o 6: t5+1
3030 3041 |
3031 3042 o 5: t5+0
3032 3043 |\
3033 3044 | o 4: t4+0
3034 3045 | |
3035 3046 | o 3: at3:t3+0
3036 3047 | |
3037 3048 o | 2: t2+0
3038 3049 |/
3039 3050 o 1: t1+0
3040 3051 |
3041 3052 o 0: null+1
3042 3053
3043 3054
3044 3055 $ hg log -G --template "{rev}: {latesttag % '{tag}+{distance},{changes} '}\n"
3045 3056 @ 11: t5+6,6
3046 3057 |
3047 3058 o 10: t5+5,5
3048 3059 |
3049 3060 o 9: t5+4,4
3050 3061 |
3051 3062 o 8: t5+3,3
3052 3063 |
3053 3064 o 7: t5+2,2
3054 3065 |
3055 3066 o 6: t5+1,1
3056 3067 |
3057 3068 o 5: t5+0,0
3058 3069 |\
3059 3070 | o 4: t4+0,0
3060 3071 | |
3061 3072 | o 3: at3+0,0 t3+0,0
3062 3073 | |
3063 3074 o | 2: t2+0,0
3064 3075 |/
3065 3076 o 1: t1+0,0
3066 3077 |
3067 3078 o 0: null+1,1
3068 3079
3069 3080
3070 3081 $ hg log -G --template "{rev}: {latesttag('re:^t[13]$') % '{tag}, C: {changes}, D: {distance}'}\n"
3071 3082 @ 11: t3, C: 9, D: 8
3072 3083 |
3073 3084 o 10: t3, C: 8, D: 7
3074 3085 |
3075 3086 o 9: t3, C: 7, D: 6
3076 3087 |
3077 3088 o 8: t3, C: 6, D: 5
3078 3089 |
3079 3090 o 7: t3, C: 5, D: 4
3080 3091 |
3081 3092 o 6: t3, C: 4, D: 3
3082 3093 |
3083 3094 o 5: t3, C: 3, D: 2
3084 3095 |\
3085 3096 | o 4: t3, C: 1, D: 1
3086 3097 | |
3087 3098 | o 3: t3, C: 0, D: 0
3088 3099 | |
3089 3100 o | 2: t1, C: 1, D: 1
3090 3101 |/
3091 3102 o 1: t1, C: 0, D: 0
3092 3103 |
3093 3104 o 0: null, C: 1, D: 1
3094 3105
3095 3106
3096 3107 $ cd ..
3097 3108
3098 3109
3099 3110 Style path expansion: issue1948 - ui.style option doesn't work on OSX
3100 3111 if it is a relative path
3101 3112
3102 3113 $ mkdir -p home/styles
3103 3114
3104 3115 $ cat > home/styles/teststyle <<EOF
3105 3116 > changeset = 'test {rev}:{node|short}\n'
3106 3117 > EOF
3107 3118
3108 3119 $ HOME=`pwd`/home; export HOME
3109 3120
3110 3121 $ cat > latesttag/.hg/hgrc <<EOF
3111 3122 > [ui]
3112 3123 > style = ~/styles/teststyle
3113 3124 > EOF
3114 3125
3115 3126 $ hg -R latesttag tip
3116 3127 test 11:97e5943b523a
3117 3128
3118 3129 Test recursive showlist template (issue1989):
3119 3130
3120 3131 $ cat > style1989 <<EOF
3121 3132 > changeset = '{file_mods}{manifest}{extras}'
3122 3133 > file_mod = 'M|{author|person}\n'
3123 3134 > manifest = '{rev},{author}\n'
3124 3135 > extra = '{key}: {author}\n'
3125 3136 > EOF
3126 3137
3127 3138 $ hg -R latesttag log -r tip --style=style1989
3128 3139 M|test
3129 3140 11,test
3130 3141 branch: test
3131 3142
3132 3143 Test new-style inline templating:
3133 3144
3134 3145 $ hg log -R latesttag -r tip --template 'modified files: {file_mods % " {file}\n"}\n'
3135 3146 modified files: .hgtags
3136 3147
3137 3148
3138 3149 $ hg log -R latesttag -r tip -T '{rev % "a"}\n'
3139 3150 hg: parse error: keyword 'rev' is not iterable
3140 3151 [255]
3141 3152 $ hg log -R latesttag -r tip -T '{get(extras, "unknown") % "a"}\n'
3142 3153 hg: parse error: None is not iterable
3143 3154 [255]
3144 3155
3145 3156 Test new-style inline templating of non-list/dict type:
3146 3157
3147 3158 $ hg log -R latesttag -r tip -T '{manifest}\n'
3148 3159 11:2bc6e9006ce2
3149 3160 $ hg log -R latesttag -r tip -T 'string length: {manifest|count}\n'
3150 3161 string length: 15
3151 3162 $ hg log -R latesttag -r tip -T '{manifest % "{rev}:{node}"}\n'
3152 3163 11:2bc6e9006ce29882383a22d39fd1f4e66dd3e2fc
3153 3164
3154 3165 $ hg log -R latesttag -r tip -T '{get(extras, "branch") % "{key}: {value}\n"}'
3155 3166 branch: default
3156 3167 $ hg log -R latesttag -r tip -T '{get(extras, "unknown") % "{key}\n"}'
3157 3168 hg: parse error: None is not iterable
3158 3169 [255]
3159 3170 $ hg log -R latesttag -r tip -T '{min(extras) % "{key}: {value}\n"}'
3160 3171 branch: default
3161 3172 $ hg log -R latesttag -l1 -T '{min(revset("0:9")) % "{rev}:{node|short}\n"}'
3162 3173 0:ce3cec86e6c2
3163 3174 $ hg log -R latesttag -l1 -T '{max(revset("0:9")) % "{rev}:{node|short}\n"}'
3164 3175 9:fbc7cd862e9c
3165 3176
3166 3177 Test manifest/get() can be join()-ed as before, though it's silly:
3167 3178
3168 3179 $ hg log -R latesttag -r tip -T '{join(manifest, "")}\n'
3169 3180 11:2bc6e9006ce2
3170 3181 $ hg log -R latesttag -r tip -T '{join(get(extras, "branch"), "")}\n'
3171 3182 default
3172 3183
3173 3184 Test min/max of integers
3174 3185
3175 3186 $ hg log -R latesttag -l1 -T '{min(revset("9:10"))}\n'
3176 3187 9
3177 3188 $ hg log -R latesttag -l1 -T '{max(revset("9:10"))}\n'
3178 3189 10
3179 3190
3180 3191 Test dot operator precedence:
3181 3192
3182 3193 $ hg debugtemplate -R latesttag -r0 -v '{manifest.node|short}\n'
3183 3194 (template
3184 3195 (|
3185 3196 (.
3186 3197 (symbol 'manifest')
3187 3198 (symbol 'node'))
3188 3199 (symbol 'short'))
3189 3200 (string '\n'))
3190 3201 89f4071fec70
3191 3202
3192 3203 (the following examples are invalid, but seem natural in parsing POV)
3193 3204
3194 3205 $ hg debugtemplate -R latesttag -r0 -v '{foo|bar.baz}\n' 2> /dev/null
3195 3206 (template
3196 3207 (|
3197 3208 (symbol 'foo')
3198 3209 (.
3199 3210 (symbol 'bar')
3200 3211 (symbol 'baz')))
3201 3212 (string '\n'))
3202 3213 [255]
3203 3214 $ hg debugtemplate -R latesttag -r0 -v '{foo.bar()}\n' 2> /dev/null
3204 3215 (template
3205 3216 (.
3206 3217 (symbol 'foo')
3207 3218 (func
3208 3219 (symbol 'bar')
3209 3220 None))
3210 3221 (string '\n'))
3211 3222 [255]
3212 3223
3213 3224 Test evaluation of dot operator:
3214 3225
3215 3226 $ hg log -R latesttag -l1 -T '{min(revset("0:9")).node}\n'
3216 3227 ce3cec86e6c26bd9bdfc590a6b92abc9680f1796
3217 3228 $ hg log -R latesttag -r0 -T '{extras.branch}\n'
3218 3229 default
3219 3230
3220 3231 $ hg log -R latesttag -l1 -T '{author.invalid}\n'
3221 3232 hg: parse error: keyword 'author' has no member
3222 3233 [255]
3223 3234 $ hg log -R latesttag -l1 -T '{min("abc").invalid}\n'
3224 3235 hg: parse error: 'a' has no member
3225 3236 [255]
3226 3237
3227 3238 Test the sub function of templating for expansion:
3228 3239
3229 3240 $ hg log -R latesttag -r 10 --template '{sub("[0-9]", "x", "{rev}")}\n'
3230 3241 xx
3231 3242
3232 3243 $ hg log -R latesttag -r 10 -T '{sub("[", "x", rev)}\n'
3233 3244 hg: parse error: sub got an invalid pattern: [
3234 3245 [255]
3235 3246 $ hg log -R latesttag -r 10 -T '{sub("[0-9]", r"\1", rev)}\n'
3236 3247 hg: parse error: sub got an invalid replacement: \1
3237 3248 [255]
3238 3249
3239 3250 Test the strip function with chars specified:
3240 3251
3241 3252 $ hg log -R latesttag --template '{desc}\n'
3242 3253 at3
3243 3254 t5
3244 3255 t4
3245 3256 t3
3246 3257 t2
3247 3258 t1
3248 3259 merge
3249 3260 h2e
3250 3261 h2d
3251 3262 h1c
3252 3263 b
3253 3264 a
3254 3265
3255 3266 $ hg log -R latesttag --template '{strip(desc, "te")}\n'
3256 3267 at3
3257 3268 5
3258 3269 4
3259 3270 3
3260 3271 2
3261 3272 1
3262 3273 merg
3263 3274 h2
3264 3275 h2d
3265 3276 h1c
3266 3277 b
3267 3278 a
3268 3279
3269 3280 Test date format:
3270 3281
3271 3282 $ hg log -R latesttag --template 'date: {date(date, "%y %m %d %S %z")}\n'
3272 3283 date: 70 01 01 10 +0000
3273 3284 date: 70 01 01 09 +0000
3274 3285 date: 70 01 01 04 +0000
3275 3286 date: 70 01 01 08 +0000
3276 3287 date: 70 01 01 07 +0000
3277 3288 date: 70 01 01 06 +0000
3278 3289 date: 70 01 01 05 +0100
3279 3290 date: 70 01 01 04 +0000
3280 3291 date: 70 01 01 03 +0000
3281 3292 date: 70 01 01 02 +0000
3282 3293 date: 70 01 01 01 +0000
3283 3294 date: 70 01 01 00 +0000
3284 3295
3285 3296 Test invalid date:
3286 3297
3287 3298 $ hg log -R latesttag -T '{date(rev)}\n'
3288 3299 hg: parse error: date expects a date information
3289 3300 [255]
3290 3301
3291 3302 Test integer literal:
3292 3303
3293 3304 $ hg debugtemplate -v '{(0)}\n'
3294 3305 (template
3295 3306 (group
3296 3307 (integer '0'))
3297 3308 (string '\n'))
3298 3309 0
3299 3310 $ hg debugtemplate -v '{(123)}\n'
3300 3311 (template
3301 3312 (group
3302 3313 (integer '123'))
3303 3314 (string '\n'))
3304 3315 123
3305 3316 $ hg debugtemplate -v '{(-4)}\n'
3306 3317 (template
3307 3318 (group
3308 3319 (negate
3309 3320 (integer '4')))
3310 3321 (string '\n'))
3311 3322 -4
3312 3323 $ hg debugtemplate '{(-)}\n'
3313 3324 hg: parse error at 3: not a prefix: )
3314 3325 [255]
3315 3326 $ hg debugtemplate '{(-a)}\n'
3316 3327 hg: parse error: negation needs an integer argument
3317 3328 [255]
3318 3329
3319 3330 top-level integer literal is interpreted as symbol (i.e. variable name):
3320 3331
3321 3332 $ hg debugtemplate -D 1=one -v '{1}\n'
3322 3333 (template
3323 3334 (integer '1')
3324 3335 (string '\n'))
3325 3336 one
3326 3337 $ hg debugtemplate -D 1=one -v '{if("t", "{1}")}\n'
3327 3338 (template
3328 3339 (func
3329 3340 (symbol 'if')
3330 3341 (list
3331 3342 (string 't')
3332 3343 (template
3333 3344 (integer '1'))))
3334 3345 (string '\n'))
3335 3346 one
3336 3347 $ hg debugtemplate -D 1=one -v '{1|stringify}\n'
3337 3348 (template
3338 3349 (|
3339 3350 (integer '1')
3340 3351 (symbol 'stringify'))
3341 3352 (string '\n'))
3342 3353 one
3343 3354
3344 3355 unless explicit symbol is expected:
3345 3356
3346 3357 $ hg log -Ra -r0 -T '{desc|1}\n'
3347 3358 hg: parse error: expected a symbol, got 'integer'
3348 3359 [255]
3349 3360 $ hg log -Ra -r0 -T '{1()}\n'
3350 3361 hg: parse error: expected a symbol, got 'integer'
3351 3362 [255]
3352 3363
3353 3364 Test string literal:
3354 3365
3355 3366 $ hg debugtemplate -Ra -r0 -v '{"string with no template fragment"}\n'
3356 3367 (template
3357 3368 (string 'string with no template fragment')
3358 3369 (string '\n'))
3359 3370 string with no template fragment
3360 3371 $ hg debugtemplate -Ra -r0 -v '{"template: {rev}"}\n'
3361 3372 (template
3362 3373 (template
3363 3374 (string 'template: ')
3364 3375 (symbol 'rev'))
3365 3376 (string '\n'))
3366 3377 template: 0
3367 3378 $ hg debugtemplate -Ra -r0 -v '{r"rawstring: {rev}"}\n'
3368 3379 (template
3369 3380 (string 'rawstring: {rev}')
3370 3381 (string '\n'))
3371 3382 rawstring: {rev}
3372 3383 $ hg debugtemplate -Ra -r0 -v '{files % r"rawstring: {file}"}\n'
3373 3384 (template
3374 3385 (%
3375 3386 (symbol 'files')
3376 3387 (string 'rawstring: {file}'))
3377 3388 (string '\n'))
3378 3389 rawstring: {file}
3379 3390
3380 3391 Test string escaping:
3381 3392
3382 3393 $ hg log -R latesttag -r 0 --template '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
3383 3394 >
3384 3395 <>\n<[>
3385 3396 <>\n<]>
3386 3397 <>\n<
3387 3398
3388 3399 $ hg log -R latesttag -r 0 \
3389 3400 > --config ui.logtemplate='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
3390 3401 >
3391 3402 <>\n<[>
3392 3403 <>\n<]>
3393 3404 <>\n<
3394 3405
3395 3406 $ hg log -R latesttag -r 0 -T esc \
3396 3407 > --config templates.esc='>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
3397 3408 >
3398 3409 <>\n<[>
3399 3410 <>\n<]>
3400 3411 <>\n<
3401 3412
3402 3413 $ cat <<'EOF' > esctmpl
3403 3414 > changeset = '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
3404 3415 > EOF
3405 3416 $ hg log -R latesttag -r 0 --style ./esctmpl
3406 3417 >
3407 3418 <>\n<[>
3408 3419 <>\n<]>
3409 3420 <>\n<
3410 3421
3411 3422 Test string escaping of quotes:
3412 3423
3413 3424 $ hg log -Ra -r0 -T '{"\""}\n'
3414 3425 "
3415 3426 $ hg log -Ra -r0 -T '{"\\\""}\n'
3416 3427 \"
3417 3428 $ hg log -Ra -r0 -T '{r"\""}\n'
3418 3429 \"
3419 3430 $ hg log -Ra -r0 -T '{r"\\\""}\n'
3420 3431 \\\"
3421 3432
3422 3433
3423 3434 $ hg log -Ra -r0 -T '{"\""}\n'
3424 3435 "
3425 3436 $ hg log -Ra -r0 -T '{"\\\""}\n'
3426 3437 \"
3427 3438 $ hg log -Ra -r0 -T '{r"\""}\n'
3428 3439 \"
3429 3440 $ hg log -Ra -r0 -T '{r"\\\""}\n'
3430 3441 \\\"
3431 3442
3432 3443 Test exception in quoted template. single backslash before quotation mark is
3433 3444 stripped before parsing:
3434 3445
3435 3446 $ cat <<'EOF' > escquotetmpl
3436 3447 > changeset = "\" \\" \\\" \\\\" {files % \"{file}\"}\n"
3437 3448 > EOF
3438 3449 $ cd latesttag
3439 3450 $ hg log -r 2 --style ../escquotetmpl
3440 3451 " \" \" \\" head1
3441 3452
3442 3453 $ hg log -r 2 -T esc --config templates.esc='"{\"valid\"}\n"'
3443 3454 valid
3444 3455 $ hg log -r 2 -T esc --config templates.esc="'"'{\'"'"'valid\'"'"'}\n'"'"
3445 3456 valid
3446 3457
3447 3458 Test compatibility with 2.9.2-3.4 of escaped quoted strings in nested
3448 3459 _evalifliteral() templates (issue4733):
3449 3460
3450 3461 $ hg log -r 2 -T '{if(rev, "\"{rev}")}\n'
3451 3462 "2
3452 3463 $ hg log -r 2 -T '{if(rev, "{if(rev, \"\\\"{rev}\")}")}\n'
3453 3464 "2
3454 3465 $ hg log -r 2 -T '{if(rev, "{if(rev, \"{if(rev, \\\"\\\\\\\"{rev}\\\")}\")}")}\n'
3455 3466 "2
3456 3467
3457 3468 $ hg log -r 2 -T '{if(rev, "\\\"")}\n'
3458 3469 \"
3459 3470 $ hg log -r 2 -T '{if(rev, "{if(rev, \"\\\\\\\"\")}")}\n'
3460 3471 \"
3461 3472 $ hg log -r 2 -T '{if(rev, "{if(rev, \"{if(rev, \\\"\\\\\\\\\\\\\\\"\\\")}\")}")}\n'
3462 3473 \"
3463 3474
3464 3475 $ hg log -r 2 -T '{if(rev, r"\\\"")}\n'
3465 3476 \\\"
3466 3477 $ hg log -r 2 -T '{if(rev, "{if(rev, r\"\\\\\\\"\")}")}\n'
3467 3478 \\\"
3468 3479 $ hg log -r 2 -T '{if(rev, "{if(rev, \"{if(rev, r\\\"\\\\\\\\\\\\\\\"\\\")}\")}")}\n'
3469 3480 \\\"
3470 3481
3471 3482 escaped single quotes and errors:
3472 3483
3473 3484 $ hg log -r 2 -T "{if(rev, '{if(rev, \'foo\')}')}"'\n'
3474 3485 foo
3475 3486 $ hg log -r 2 -T "{if(rev, '{if(rev, r\'foo\')}')}"'\n'
3476 3487 foo
3477 3488 $ hg log -r 2 -T '{if(rev, "{if(rev, \")}")}\n'
3478 3489 hg: parse error at 21: unterminated string
3479 3490 [255]
3480 3491 $ hg log -r 2 -T '{if(rev, \"\\"")}\n'
3481 3492 hg: parse error: trailing \ in string
3482 3493 [255]
3483 3494 $ hg log -r 2 -T '{if(rev, r\"\\"")}\n'
3484 3495 hg: parse error: trailing \ in string
3485 3496 [255]
3486 3497
3487 3498 $ cd ..
3488 3499
3489 3500 Test leading backslashes:
3490 3501
3491 3502 $ cd latesttag
3492 3503 $ hg log -r 2 -T '\{rev} {files % "\{file}"}\n'
3493 3504 {rev} {file}
3494 3505 $ hg log -r 2 -T '\\{rev} {files % "\\{file}"}\n'
3495 3506 \2 \head1
3496 3507 $ hg log -r 2 -T '\\\{rev} {files % "\\\{file}"}\n'
3497 3508 \{rev} \{file}
3498 3509 $ cd ..
3499 3510
3500 3511 Test leading backslashes in "if" expression (issue4714):
3501 3512
3502 3513 $ cd latesttag
3503 3514 $ hg log -r 2 -T '{if("1", "\{rev}")} {if("1", r"\{rev}")}\n'
3504 3515 {rev} \{rev}
3505 3516 $ hg log -r 2 -T '{if("1", "\\{rev}")} {if("1", r"\\{rev}")}\n'
3506 3517 \2 \\{rev}
3507 3518 $ hg log -r 2 -T '{if("1", "\\\{rev}")} {if("1", r"\\\{rev}")}\n'
3508 3519 \{rev} \\\{rev}
3509 3520 $ cd ..
3510 3521
3511 3522 "string-escape"-ed "\x5c\x786e" becomes r"\x6e" (once) or r"n" (twice)
3512 3523
3513 3524 $ hg log -R a -r 0 --template '{if("1", "\x5c\x786e", "NG")}\n'
3514 3525 \x6e
3515 3526 $ hg log -R a -r 0 --template '{if("1", r"\x5c\x786e", "NG")}\n'
3516 3527 \x5c\x786e
3517 3528 $ hg log -R a -r 0 --template '{if("", "NG", "\x5c\x786e")}\n'
3518 3529 \x6e
3519 3530 $ hg log -R a -r 0 --template '{if("", "NG", r"\x5c\x786e")}\n'
3520 3531 \x5c\x786e
3521 3532
3522 3533 $ hg log -R a -r 2 --template '{ifeq("no perso\x6e", desc, "\x5c\x786e", "NG")}\n'
3523 3534 \x6e
3524 3535 $ hg log -R a -r 2 --template '{ifeq(r"no perso\x6e", desc, "NG", r"\x5c\x786e")}\n'
3525 3536 \x5c\x786e
3526 3537 $ hg log -R a -r 2 --template '{ifeq(desc, "no perso\x6e", "\x5c\x786e", "NG")}\n'
3527 3538 \x6e
3528 3539 $ hg log -R a -r 2 --template '{ifeq(desc, r"no perso\x6e", "NG", r"\x5c\x786e")}\n'
3529 3540 \x5c\x786e
3530 3541
3531 3542 $ hg log -R a -r 8 --template '{join(files, "\n")}\n'
3532 3543 fourth
3533 3544 second
3534 3545 third
3535 3546 $ hg log -R a -r 8 --template '{join(files, r"\n")}\n'
3536 3547 fourth\nsecond\nthird
3537 3548
3538 3549 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", "htm\x6c")}'
3539 3550 <p>
3540 3551 1st
3541 3552 </p>
3542 3553 <p>
3543 3554 2nd
3544 3555 </p>
3545 3556 $ hg log -R a -r 2 --template '{rstdoc(r"1st\n\n2nd", "html")}'
3546 3557 <p>
3547 3558 1st\n\n2nd
3548 3559 </p>
3549 3560 $ hg log -R a -r 2 --template '{rstdoc("1st\n\n2nd", r"htm\x6c")}'
3550 3561 1st
3551 3562
3552 3563 2nd
3553 3564
3554 3565 $ hg log -R a -r 2 --template '{strip(desc, "\x6e")}\n'
3555 3566 o perso
3556 3567 $ hg log -R a -r 2 --template '{strip(desc, r"\x6e")}\n'
3557 3568 no person
3558 3569 $ hg log -R a -r 2 --template '{strip("no perso\x6e", "\x6e")}\n'
3559 3570 o perso
3560 3571 $ hg log -R a -r 2 --template '{strip(r"no perso\x6e", r"\x6e")}\n'
3561 3572 no perso
3562 3573
3563 3574 $ hg log -R a -r 2 --template '{sub("\\x6e", "\x2d", desc)}\n'
3564 3575 -o perso-
3565 3576 $ hg log -R a -r 2 --template '{sub(r"\\x6e", "-", desc)}\n'
3566 3577 no person
3567 3578 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", desc)}\n'
3568 3579 \x2do perso\x2d
3569 3580 $ hg log -R a -r 2 --template '{sub("n", "\x2d", "no perso\x6e")}\n'
3570 3581 -o perso-
3571 3582 $ hg log -R a -r 2 --template '{sub("n", r"\x2d", r"no perso\x6e")}\n'
3572 3583 \x2do perso\x6e
3573 3584
3574 3585 $ hg log -R a -r 8 --template '{files % "{file}\n"}'
3575 3586 fourth
3576 3587 second
3577 3588 third
3578 3589
3579 3590 Test string escaping in nested expression:
3580 3591
3581 3592 $ hg log -R a -r 8 --template '{ifeq(r"\x6e", if("1", "\x5c\x786e"), join(files, "\x5c\x786e"))}\n'
3582 3593 fourth\x6esecond\x6ethird
3583 3594 $ hg log -R a -r 8 --template '{ifeq(if("1", r"\x6e"), "\x5c\x786e", join(files, "\x5c\x786e"))}\n'
3584 3595 fourth\x6esecond\x6ethird
3585 3596
3586 3597 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", "\x5c\x786e"))}\n'
3587 3598 fourth\x6esecond\x6ethird
3588 3599 $ hg log -R a -r 8 --template '{join(files, ifeq(branch, "default", r"\x5c\x786e"))}\n'
3589 3600 fourth\x5c\x786esecond\x5c\x786ethird
3590 3601
3591 3602 $ hg log -R a -r 3:4 --template '{rev}:{sub(if("1", "\x6e"), ifeq(branch, "foo", r"\x5c\x786e", "\x5c\x786e"), desc)}\n'
3592 3603 3:\x6eo user, \x6eo domai\x6e
3593 3604 4:\x5c\x786eew bra\x5c\x786ech
3594 3605
3595 3606 Test quotes in nested expression are evaluated just like a $(command)
3596 3607 substitution in POSIX shells:
3597 3608
3598 3609 $ hg log -R a -r 8 -T '{"{"{rev}:{node|short}"}"}\n'
3599 3610 8:95c24699272e
3600 3611 $ hg log -R a -r 8 -T '{"{"\{{rev}} \"{node|short}\""}"}\n'
3601 3612 {8} "95c24699272e"
3602 3613
3603 3614 Test recursive evaluation:
3604 3615
3605 3616 $ hg init r
3606 3617 $ cd r
3607 3618 $ echo a > a
3608 3619 $ hg ci -Am '{rev}'
3609 3620 adding a
3610 3621 $ hg log -r 0 --template '{if(rev, desc)}\n'
3611 3622 {rev}
3612 3623 $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n'
3613 3624 test 0
3614 3625
3615 3626 $ hg branch -q 'text.{rev}'
3616 3627 $ echo aa >> aa
3617 3628 $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
3618 3629
3619 3630 $ hg log -l1 --template '{fill(desc, "20", author, branch)}'
3620 3631 {node|short}desc to
3621 3632 text.{rev}be wrapped
3622 3633 text.{rev}desc to be
3623 3634 text.{rev}wrapped (no-eol)
3624 3635 $ hg log -l1 --template '{fill(desc, "20", "{node|short}:", "text.{rev}:")}'
3625 3636 bcc7ff960b8e:desc to
3626 3637 text.1:be wrapped
3627 3638 text.1:desc to be
3628 3639 text.1:wrapped (no-eol)
3629 3640 $ hg log -l1 -T '{fill(desc, date, "", "")}\n'
3630 3641 hg: parse error: fill expects an integer width
3631 3642 [255]
3632 3643
3633 3644 $ COLUMNS=25 hg log -l1 --template '{fill(desc, termwidth, "{node|short}:", "termwidth.{rev}:")}'
3634 3645 bcc7ff960b8e:desc to be
3635 3646 termwidth.1:wrapped desc
3636 3647 termwidth.1:to be wrapped (no-eol)
3637 3648
3638 3649 $ hg log -l 1 --template '{sub(r"[0-9]", "-", author)}'
3639 3650 {node|short} (no-eol)
3640 3651 $ hg log -l 1 --template '{sub(r"[0-9]", "-", "{node|short}")}'
3641 3652 bcc-ff---b-e (no-eol)
3642 3653
3643 3654 $ cat >> .hg/hgrc <<EOF
3644 3655 > [extensions]
3645 3656 > color=
3646 3657 > [color]
3647 3658 > mode=ansi
3648 3659 > text.{rev} = red
3649 3660 > text.1 = green
3650 3661 > EOF
3651 3662 $ hg log --color=always -l 1 --template '{label(branch, "text\n")}'
3652 3663 \x1b[0;31mtext\x1b[0m (esc)
3653 3664 $ hg log --color=always -l 1 --template '{label("text.{rev}", "text\n")}'
3654 3665 \x1b[0;32mtext\x1b[0m (esc)
3655 3666
3656 3667 color effect can be specified without quoting:
3657 3668
3658 3669 $ hg log --color=always -l 1 --template '{label(red, "text\n")}'
3659 3670 \x1b[0;31mtext\x1b[0m (esc)
3660 3671
3661 3672 color effects can be nested (issue5413)
3662 3673
3663 3674 $ hg debugtemplate --color=always \
3664 3675 > '{label(red, "red{label(magenta, "ma{label(cyan, "cyan")}{label(yellow, "yellow")}genta")}")}\n'
3665 3676 \x1b[0;31mred\x1b[0;35mma\x1b[0;36mcyan\x1b[0m\x1b[0;31m\x1b[0;35m\x1b[0;33myellow\x1b[0m\x1b[0;31m\x1b[0;35mgenta\x1b[0m (esc)
3666 3677
3667 3678 pad() should interact well with color codes (issue5416)
3668 3679
3669 3680 $ hg debugtemplate --color=always \
3670 3681 > '{pad(label(red, "red"), 5, label(cyan, "-"))}\n'
3671 3682 \x1b[0;31mred\x1b[0m\x1b[0;36m-\x1b[0m\x1b[0;36m-\x1b[0m (esc)
3672 3683
3673 3684 label should be no-op if color is disabled:
3674 3685
3675 3686 $ hg log --color=never -l 1 --template '{label(red, "text\n")}'
3676 3687 text
3677 3688 $ hg log --config extensions.color=! -l 1 --template '{label(red, "text\n")}'
3678 3689 text
3679 3690
3680 3691 Test branches inside if statement:
3681 3692
3682 3693 $ hg log -r 0 --template '{if(branches, "yes", "no")}\n'
3683 3694 no
3684 3695
3685 3696 Test dict constructor:
3686 3697
3687 3698 $ hg log -r 0 -T '{dict(y=node|short, x=rev)}\n'
3688 3699 y=f7769ec2ab97 x=0
3689 3700 $ hg log -r 0 -T '{dict(x=rev, y=node|short) % "{key}={value}\n"}'
3690 3701 x=0
3691 3702 y=f7769ec2ab97
3692 3703 $ hg log -r 0 -T '{dict(x=rev, y=node|short)|json}\n'
3693 3704 {"x": 0, "y": "f7769ec2ab97"}
3694 3705 $ hg log -r 0 -T '{dict()|json}\n'
3695 3706 {}
3696 3707
3697 3708 $ hg log -r 0 -T '{dict(rev, node=node|short)}\n'
3698 3709 rev=0 node=f7769ec2ab97
3699 3710 $ hg log -r 0 -T '{dict(rev, node|short)}\n'
3700 3711 rev=0 node=f7769ec2ab97
3701 3712
3702 3713 $ hg log -r 0 -T '{dict(rev, rev=rev)}\n'
3703 3714 hg: parse error: duplicated dict key 'rev' inferred
3704 3715 [255]
3705 3716 $ hg log -r 0 -T '{dict(node, node|short)}\n'
3706 3717 hg: parse error: duplicated dict key 'node' inferred
3707 3718 [255]
3708 3719 $ hg log -r 0 -T '{dict(1 + 2)}'
3709 3720 hg: parse error: dict key cannot be inferred
3710 3721 [255]
3711 3722
3712 3723 $ hg log -r 0 -T '{dict(x=rev, x=node)}'
3713 3724 hg: parse error: dict got multiple values for keyword argument 'x'
3714 3725 [255]
3715 3726
3716 3727 Test get function:
3717 3728
3718 3729 $ hg log -r 0 --template '{get(extras, "branch")}\n'
3719 3730 default
3720 3731 $ hg log -r 0 --template '{get(extras, "br{"anch"}")}\n'
3721 3732 default
3722 3733 $ hg log -r 0 --template '{get(files, "should_fail")}\n'
3723 3734 hg: parse error: get() expects a dict as first argument
3724 3735 [255]
3725 3736
3726 3737 Test json filter applied to hybrid object:
3727 3738
3728 3739 $ hg log -r0 -T '{files|json}\n'
3729 3740 ["a"]
3730 3741 $ hg log -r0 -T '{extras|json}\n'
3731 3742 {"branch": "default"}
3732 3743
3733 3744 Test localdate(date, tz) function:
3734 3745
3735 3746 $ TZ=JST-09 hg log -r0 -T '{date|localdate|isodate}\n'
3736 3747 1970-01-01 09:00 +0900
3737 3748 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "UTC")|isodate}\n'
3738 3749 1970-01-01 00:00 +0000
3739 3750 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "blahUTC")|isodate}\n'
3740 3751 hg: parse error: localdate expects a timezone
3741 3752 [255]
3742 3753 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "+0200")|isodate}\n'
3743 3754 1970-01-01 02:00 +0200
3744 3755 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "0")|isodate}\n'
3745 3756 1970-01-01 00:00 +0000
3746 3757 $ TZ=JST-09 hg log -r0 -T '{localdate(date, 0)|isodate}\n'
3747 3758 1970-01-01 00:00 +0000
3748 3759 $ hg log -r0 -T '{localdate(date, "invalid")|isodate}\n'
3749 3760 hg: parse error: localdate expects a timezone
3750 3761 [255]
3751 3762 $ hg log -r0 -T '{localdate(date, date)|isodate}\n'
3752 3763 hg: parse error: localdate expects a timezone
3753 3764 [255]
3754 3765
3755 3766 Test shortest(node) function:
3756 3767
3757 3768 $ echo b > b
3758 3769 $ hg ci -qAm b
3759 3770 $ hg log --template '{shortest(node)}\n'
3760 3771 e777
3761 3772 bcc7
3762 3773 f776
3763 3774 $ hg log --template '{shortest(node, 10)}\n'
3764 3775 e777603221
3765 3776 bcc7ff960b
3766 3777 f7769ec2ab
3767 3778 $ hg log --template '{node|shortest}\n' -l1
3768 3779 e777
3769 3780
3770 3781 $ hg log -r 0 -T '{shortest(node, "1{"0"}")}\n'
3771 3782 f7769ec2ab
3772 3783 $ hg log -r 0 -T '{shortest(node, "not an int")}\n'
3773 3784 hg: parse error: shortest() expects an integer minlength
3774 3785 [255]
3775 3786
3776 3787 $ hg log -r 'wdir()' -T '{node|shortest}\n'
3777 3788 ffff
3778 3789
3779 3790 $ cd ..
3780 3791
3781 3792 Test shortest(node) with the repo having short hash collision:
3782 3793
3783 3794 $ hg init hashcollision
3784 3795 $ cd hashcollision
3785 3796 $ cat <<EOF >> .hg/hgrc
3786 3797 > [experimental]
3787 3798 > evolution.createmarkers=True
3788 3799 > EOF
3789 3800 $ echo 0 > a
3790 3801 $ hg ci -qAm 0
3791 3802 $ for i in 17 129 248 242 480 580 617 1057 2857 4025; do
3792 3803 > hg up -q 0
3793 3804 > echo $i > a
3794 3805 > hg ci -qm $i
3795 3806 > done
3796 3807 $ hg up -q null
3797 3808 $ hg log -r0: -T '{rev}:{node}\n'
3798 3809 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a
3799 3810 1:11424df6dc1dd4ea255eae2b58eaca7831973bbc
3800 3811 2:11407b3f1b9c3e76a79c1ec5373924df096f0499
3801 3812 3:11dd92fe0f39dfdaacdaa5f3997edc533875cfc4
3802 3813 4:10776689e627b465361ad5c296a20a487e153ca4
3803 3814 5:a00be79088084cb3aff086ab799f8790e01a976b
3804 3815 6:a0b0acd79b4498d0052993d35a6a748dd51d13e6
3805 3816 7:a0457b3450b8e1b778f1163b31a435802987fe5d
3806 3817 8:c56256a09cd28e5764f32e8e2810d0f01e2e357a
3807 3818 9:c5623987d205cd6d9d8389bfc40fff9dbb670b48
3808 3819 10:c562ddd9c94164376c20b86b0b4991636a3bf84f
3809 3820 $ hg debugobsolete a00be79088084cb3aff086ab799f8790e01a976b
3810 3821 obsoleted 1 changesets
3811 3822 $ hg debugobsolete c5623987d205cd6d9d8389bfc40fff9dbb670b48
3812 3823 obsoleted 1 changesets
3813 3824 $ hg debugobsolete c562ddd9c94164376c20b86b0b4991636a3bf84f
3814 3825 obsoleted 1 changesets
3815 3826
3816 3827 nodes starting with '11' (we don't have the revision number '11' though)
3817 3828
3818 3829 $ hg log -r 1:3 -T '{rev}:{shortest(node, 0)}\n'
3819 3830 1:1142
3820 3831 2:1140
3821 3832 3:11d
3822 3833
3823 3834 '5:a00' is hidden, but still we have two nodes starting with 'a0'
3824 3835
3825 3836 $ hg log -r 6:7 -T '{rev}:{shortest(node, 0)}\n'
3826 3837 6:a0b
3827 3838 7:a04
3828 3839
3829 3840 node '10' conflicts with the revision number '10' even if it is hidden
3830 3841 (we could exclude hidden revision numbers, but currently we don't)
3831 3842
3832 3843 $ hg log -r 4 -T '{rev}:{shortest(node, 0)}\n'
3833 3844 4:107
3834 3845 $ hg log -r 4 -T '{rev}:{shortest(node, 0)}\n' --hidden
3835 3846 4:107
3836 3847
3837 3848 node 'c562' should be unique if the other 'c562' nodes are hidden
3838 3849 (but we don't try the slow path to filter out hidden nodes for now)
3839 3850
3840 3851 $ hg log -r 8 -T '{rev}:{node|shortest}\n'
3841 3852 8:c5625
3842 3853 $ hg log -r 8:10 -T '{rev}:{node|shortest}\n' --hidden
3843 3854 8:c5625
3844 3855 9:c5623
3845 3856 10:c562d
3846 3857
3847 3858 $ cd ..
3848 3859
3849 3860 Test pad function
3850 3861
3851 3862 $ cd r
3852 3863
3853 3864 $ hg log --template '{pad(rev, 20)} {author|user}\n'
3854 3865 2 test
3855 3866 1 {node|short}
3856 3867 0 test
3857 3868
3858 3869 $ hg log --template '{pad(rev, 20, " ", True)} {author|user}\n'
3859 3870 2 test
3860 3871 1 {node|short}
3861 3872 0 test
3862 3873
3863 3874 $ hg log --template '{pad(rev, 20, "-", False)} {author|user}\n'
3864 3875 2------------------- test
3865 3876 1------------------- {node|short}
3866 3877 0------------------- test
3867 3878
3868 3879 Test template string in pad function
3869 3880
3870 3881 $ hg log -r 0 -T '{pad("\{{rev}}", 10)} {author|user}\n'
3871 3882 {0} test
3872 3883
3873 3884 $ hg log -r 0 -T '{pad(r"\{rev}", 10)} {author|user}\n'
3874 3885 \{rev} test
3875 3886
3876 3887 Test width argument passed to pad function
3877 3888
3878 3889 $ hg log -r 0 -T '{pad(rev, "1{"0"}")} {author|user}\n'
3879 3890 0 test
3880 3891 $ hg log -r 0 -T '{pad(rev, "not an int")}\n'
3881 3892 hg: parse error: pad() expects an integer width
3882 3893 [255]
3883 3894
3884 3895 Test invalid fillchar passed to pad function
3885 3896
3886 3897 $ hg log -r 0 -T '{pad(rev, 10, "")}\n'
3887 3898 hg: parse error: pad() expects a single fill character
3888 3899 [255]
3889 3900 $ hg log -r 0 -T '{pad(rev, 10, "--")}\n'
3890 3901 hg: parse error: pad() expects a single fill character
3891 3902 [255]
3892 3903
3893 3904 Test boolean argument passed to pad function
3894 3905
3895 3906 no crash
3896 3907
3897 3908 $ hg log -r 0 -T '{pad(rev, 10, "-", "f{"oo"}")}\n'
3898 3909 ---------0
3899 3910
3900 3911 string/literal
3901 3912
3902 3913 $ hg log -r 0 -T '{pad(rev, 10, "-", "false")}\n'
3903 3914 ---------0
3904 3915 $ hg log -r 0 -T '{pad(rev, 10, "-", false)}\n'
3905 3916 0---------
3906 3917 $ hg log -r 0 -T '{pad(rev, 10, "-", "")}\n'
3907 3918 0---------
3908 3919
3909 3920 unknown keyword is evaluated to ''
3910 3921
3911 3922 $ hg log -r 0 -T '{pad(rev, 10, "-", unknownkeyword)}\n'
3912 3923 0---------
3913 3924
3914 3925 Test separate function
3915 3926
3916 3927 $ hg log -r 0 -T '{separate("-", "", "a", "b", "", "", "c", "")}\n'
3917 3928 a-b-c
3918 3929 $ hg log -r 0 -T '{separate(" ", "{rev}:{node|short}", author|user, branch)}\n'
3919 3930 0:f7769ec2ab97 test default
3920 3931 $ hg log -r 0 --color=always -T '{separate(" ", "a", label(red, "b"), "c", label(red, ""), "d")}\n'
3921 3932 a \x1b[0;31mb\x1b[0m c d (esc)
3922 3933
3923 3934 Test boolean expression/literal passed to if function
3924 3935
3925 3936 $ hg log -r 0 -T '{if(rev, "rev 0 is True")}\n'
3926 3937 rev 0 is True
3927 3938 $ hg log -r 0 -T '{if(0, "literal 0 is True as well")}\n'
3928 3939 literal 0 is True as well
3929 3940 $ hg log -r 0 -T '{if("", "", "empty string is False")}\n'
3930 3941 empty string is False
3931 3942 $ hg log -r 0 -T '{if(revset(r"0 - 0"), "", "empty list is False")}\n'
3932 3943 empty list is False
3933 3944 $ hg log -r 0 -T '{if(true, "true is True")}\n'
3934 3945 true is True
3935 3946 $ hg log -r 0 -T '{if(false, "", "false is False")}\n'
3936 3947 false is False
3937 3948 $ hg log -r 0 -T '{if("false", "non-empty string is True")}\n'
3938 3949 non-empty string is True
3939 3950
3940 3951 Test ifcontains function
3941 3952
3942 3953 $ hg log --template '{rev} {ifcontains(rev, "2 two 0", "is in the string", "is not")}\n'
3943 3954 2 is in the string
3944 3955 1 is not
3945 3956 0 is in the string
3946 3957
3947 3958 $ hg log -T '{rev} {ifcontains(rev, "2 two{" 0"}", "is in the string", "is not")}\n'
3948 3959 2 is in the string
3949 3960 1 is not
3950 3961 0 is in the string
3951 3962
3952 3963 $ hg log --template '{rev} {ifcontains("a", file_adds, "added a", "did not add a")}\n'
3953 3964 2 did not add a
3954 3965 1 did not add a
3955 3966 0 added a
3956 3967
3957 3968 $ hg log --debug -T '{rev}{ifcontains(1, parents, " is parent of 1")}\n'
3958 3969 2 is parent of 1
3959 3970 1
3960 3971 0
3961 3972
3962 3973 Test revset function
3963 3974
3964 3975 $ hg log --template '{rev} {ifcontains(rev, revset("."), "current rev", "not current rev")}\n'
3965 3976 2 current rev
3966 3977 1 not current rev
3967 3978 0 not current rev
3968 3979
3969 3980 $ hg log --template '{rev} {ifcontains(rev, revset(". + .^"), "match rev", "not match rev")}\n'
3970 3981 2 match rev
3971 3982 1 match rev
3972 3983 0 not match rev
3973 3984
3974 3985 $ hg log -T '{ifcontains(desc, revset(":"), "", "type not match")}\n' -l1
3975 3986 type not match
3976 3987
3977 3988 $ hg log --template '{rev} Parents: {revset("parents(%s)", rev)}\n'
3978 3989 2 Parents: 1
3979 3990 1 Parents: 0
3980 3991 0 Parents:
3981 3992
3982 3993 $ cat >> .hg/hgrc <<EOF
3983 3994 > [revsetalias]
3984 3995 > myparents(\$1) = parents(\$1)
3985 3996 > EOF
3986 3997 $ hg log --template '{rev} Parents: {revset("myparents(%s)", rev)}\n'
3987 3998 2 Parents: 1
3988 3999 1 Parents: 0
3989 4000 0 Parents:
3990 4001
3991 4002 $ hg log --template 'Rev: {rev}\n{revset("::%s", rev) % "Ancestor: {revision}\n"}\n'
3992 4003 Rev: 2
3993 4004 Ancestor: 0
3994 4005 Ancestor: 1
3995 4006 Ancestor: 2
3996 4007
3997 4008 Rev: 1
3998 4009 Ancestor: 0
3999 4010 Ancestor: 1
4000 4011
4001 4012 Rev: 0
4002 4013 Ancestor: 0
4003 4014
4004 4015 $ hg log --template '{revset("TIP"|lower)}\n' -l1
4005 4016 2
4006 4017
4007 4018 $ hg log -T '{revset("%s", "t{"ip"}")}\n' -l1
4008 4019 2
4009 4020
4010 4021 a list template is evaluated for each item of revset/parents
4011 4022
4012 4023 $ hg log -T '{rev} p: {revset("p1(%s)", rev) % "{rev}:{node|short}"}\n'
4013 4024 2 p: 1:bcc7ff960b8e
4014 4025 1 p: 0:f7769ec2ab97
4015 4026 0 p:
4016 4027
4017 4028 $ hg log --debug -T '{rev} p:{parents % " {rev}:{node|short}"}\n'
4018 4029 2 p: 1:bcc7ff960b8e -1:000000000000
4019 4030 1 p: 0:f7769ec2ab97 -1:000000000000
4020 4031 0 p: -1:000000000000 -1:000000000000
4021 4032
4022 4033 therefore, 'revcache' should be recreated for each rev
4023 4034
4024 4035 $ hg log -T '{rev} {file_adds}\np {revset("p1(%s)", rev) % "{file_adds}"}\n'
4025 4036 2 aa b
4026 4037 p
4027 4038 1
4028 4039 p a
4029 4040 0 a
4030 4041 p
4031 4042
4032 4043 $ hg log --debug -T '{rev} {file_adds}\np {parents % "{file_adds}"}\n'
4033 4044 2 aa b
4034 4045 p
4035 4046 1
4036 4047 p a
4037 4048 0 a
4038 4049 p
4039 4050
4040 4051 a revset item must be evaluated as an integer revision, not an offset from tip
4041 4052
4042 4053 $ hg log -l 1 -T '{revset("null") % "{rev}:{node|short}"}\n'
4043 4054 -1:000000000000
4044 4055 $ hg log -l 1 -T '{revset("%s", "null") % "{rev}:{node|short}"}\n'
4045 4056 -1:000000000000
4046 4057
4047 4058 join() should pick '{rev}' from revset items:
4048 4059
4049 4060 $ hg log -R ../a -T '{join(revset("parents(%d)", rev), ", ")}\n' -r6
4050 4061 4, 5
4051 4062
4052 4063 on the other hand, parents are formatted as '{rev}:{node|formatnode}' by
4053 4064 default. join() should agree with the default formatting:
4054 4065
4055 4066 $ hg log -R ../a -T '{join(parents, ", ")}\n' -r6
4056 4067 5:13207e5a10d9, 4:bbe44766e73d
4057 4068
4058 4069 $ hg log -R ../a -T '{join(parents, ",\n")}\n' -r6 --debug
4059 4070 5:13207e5a10d9fd28ec424934298e176197f2c67f,
4060 4071 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
4061 4072
4062 4073 Test files function
4063 4074
4064 4075 $ hg log -T "{rev}\n{join(files('*'), '\n')}\n"
4065 4076 2
4066 4077 a
4067 4078 aa
4068 4079 b
4069 4080 1
4070 4081 a
4071 4082 0
4072 4083 a
4073 4084
4074 4085 $ hg log -T "{rev}\n{join(files('aa'), '\n')}\n"
4075 4086 2
4076 4087 aa
4077 4088 1
4078 4089
4079 4090 0
4080 4091
4081 4092
4082 4093 Test relpath function
4083 4094
4084 4095 $ hg log -r0 -T '{files % "{file|relpath}\n"}'
4085 4096 a
4086 4097 $ cd ..
4087 4098 $ hg log -R r -r0 -T '{files % "{file|relpath}\n"}'
4088 4099 r/a
4089 4100 $ cd r
4090 4101
4091 4102 Test active bookmark templating
4092 4103
4093 4104 $ hg book foo
4094 4105 $ hg book bar
4095 4106 $ hg log --template "{rev} {bookmarks % '{bookmark}{ifeq(bookmark, active, \"*\")} '}\n"
4096 4107 2 bar* foo
4097 4108 1
4098 4109 0
4099 4110 $ hg log --template "{rev} {activebookmark}\n"
4100 4111 2 bar
4101 4112 1
4102 4113 0
4103 4114 $ hg bookmarks --inactive bar
4104 4115 $ hg log --template "{rev} {activebookmark}\n"
4105 4116 2
4106 4117 1
4107 4118 0
4108 4119 $ hg book -r1 baz
4109 4120 $ hg log --template "{rev} {join(bookmarks, ' ')}\n"
4110 4121 2 bar foo
4111 4122 1 baz
4112 4123 0
4113 4124 $ hg log --template "{rev} {ifcontains('foo', bookmarks, 't', 'f')}\n"
4114 4125 2 t
4115 4126 1 f
4116 4127 0 f
4117 4128
4118 4129 Test namespaces dict
4119 4130
4120 4131 $ hg --config extensions.revnamesext=$TESTDIR/revnamesext.py log -T '{rev}\n{namespaces % " {namespace} color={colorname} builtin={builtin}\n {join(names, ",")}\n"}\n'
4121 4132 2
4122 4133 bookmarks color=bookmark builtin=True
4123 4134 bar,foo
4124 4135 tags color=tag builtin=True
4125 4136 tip
4126 4137 branches color=branch builtin=True
4127 4138 text.{rev}
4128 4139 revnames color=revname builtin=False
4129 4140 r2
4130 4141
4131 4142 1
4132 4143 bookmarks color=bookmark builtin=True
4133 4144 baz
4134 4145 tags color=tag builtin=True
4135 4146
4136 4147 branches color=branch builtin=True
4137 4148 text.{rev}
4138 4149 revnames color=revname builtin=False
4139 4150 r1
4140 4151
4141 4152 0
4142 4153 bookmarks color=bookmark builtin=True
4143 4154
4144 4155 tags color=tag builtin=True
4145 4156
4146 4157 branches color=branch builtin=True
4147 4158 default
4148 4159 revnames color=revname builtin=False
4149 4160 r0
4150 4161
4151 4162 $ hg log -r2 -T '{namespaces % "{namespace}: {names}\n"}'
4152 4163 bookmarks: bar foo
4153 4164 tags: tip
4154 4165 branches: text.{rev}
4155 4166 $ hg log -r2 -T '{namespaces % "{namespace}:\n{names % " {name}\n"}"}'
4156 4167 bookmarks:
4157 4168 bar
4158 4169 foo
4159 4170 tags:
4160 4171 tip
4161 4172 branches:
4162 4173 text.{rev}
4163 4174 $ hg log -r2 -T '{get(namespaces, "bookmarks") % "{name}\n"}'
4164 4175 bar
4165 4176 foo
4166 4177 $ hg log -r2 -T '{namespaces.bookmarks % "{bookmark}\n"}'
4167 4178 bar
4168 4179 foo
4169 4180
4170 4181 Test stringify on sub expressions
4171 4182
4172 4183 $ cd ..
4173 4184 $ hg log -R a -r 8 --template '{join(files, if("1", if("1", ", ")))}\n'
4174 4185 fourth, second, third
4175 4186 $ hg log -R a -r 8 --template '{strip(if("1", if("1", "-abc-")), if("1", if("1", "-")))}\n'
4176 4187 abc
4177 4188
4178 4189 Test splitlines
4179 4190
4180 4191 $ hg log -Gv -R a --template "{splitlines(desc) % 'foo {line}\n'}"
4181 4192 @ foo Modify, add, remove, rename
4182 4193 |
4183 4194 o foo future
4184 4195 |
4185 4196 o foo third
4186 4197 |
4187 4198 o foo second
4188 4199
4189 4200 o foo merge
4190 4201 |\
4191 4202 | o foo new head
4192 4203 | |
4193 4204 o | foo new branch
4194 4205 |/
4195 4206 o foo no user, no domain
4196 4207 |
4197 4208 o foo no person
4198 4209 |
4199 4210 o foo other 1
4200 4211 | foo other 2
4201 4212 | foo
4202 4213 | foo other 3
4203 4214 o foo line 1
4204 4215 foo line 2
4205 4216
4206 4217 $ hg log -R a -r0 -T '{desc|splitlines}\n'
4207 4218 line 1 line 2
4208 4219 $ hg log -R a -r0 -T '{join(desc|splitlines, "|")}\n'
4209 4220 line 1|line 2
4210 4221
4211 4222 Test startswith
4212 4223 $ hg log -Gv -R a --template "{startswith(desc)}"
4213 4224 hg: parse error: startswith expects two arguments
4214 4225 [255]
4215 4226
4216 4227 $ hg log -Gv -R a --template "{startswith('line', desc)}"
4217 4228 @
4218 4229 |
4219 4230 o
4220 4231 |
4221 4232 o
4222 4233 |
4223 4234 o
4224 4235
4225 4236 o
4226 4237 |\
4227 4238 | o
4228 4239 | |
4229 4240 o |
4230 4241 |/
4231 4242 o
4232 4243 |
4233 4244 o
4234 4245 |
4235 4246 o
4236 4247 |
4237 4248 o line 1
4238 4249 line 2
4239 4250
4240 4251 Test bad template with better error message
4241 4252
4242 4253 $ hg log -Gv -R a --template '{desc|user()}'
4243 4254 hg: parse error: expected a symbol, got 'func'
4244 4255 [255]
4245 4256
4246 4257 Test word function (including index out of bounds graceful failure)
4247 4258
4248 4259 $ hg log -Gv -R a --template "{word('1', desc)}"
4249 4260 @ add,
4250 4261 |
4251 4262 o
4252 4263 |
4253 4264 o
4254 4265 |
4255 4266 o
4256 4267
4257 4268 o
4258 4269 |\
4259 4270 | o head
4260 4271 | |
4261 4272 o | branch
4262 4273 |/
4263 4274 o user,
4264 4275 |
4265 4276 o person
4266 4277 |
4267 4278 o 1
4268 4279 |
4269 4280 o 1
4270 4281
4271 4282
4272 4283 Test word third parameter used as splitter
4273 4284
4274 4285 $ hg log -Gv -R a --template "{word('0', desc, 'o')}"
4275 4286 @ M
4276 4287 |
4277 4288 o future
4278 4289 |
4279 4290 o third
4280 4291 |
4281 4292 o sec
4282 4293
4283 4294 o merge
4284 4295 |\
4285 4296 | o new head
4286 4297 | |
4287 4298 o | new branch
4288 4299 |/
4289 4300 o n
4290 4301 |
4291 4302 o n
4292 4303 |
4293 4304 o
4294 4305 |
4295 4306 o line 1
4296 4307 line 2
4297 4308
4298 4309 Test word error messages for not enough and too many arguments
4299 4310
4300 4311 $ hg log -Gv -R a --template "{word('0')}"
4301 4312 hg: parse error: word expects two or three arguments, got 1
4302 4313 [255]
4303 4314
4304 4315 $ hg log -Gv -R a --template "{word('0', desc, 'o', 'h', 'b', 'o', 'y')}"
4305 4316 hg: parse error: word expects two or three arguments, got 7
4306 4317 [255]
4307 4318
4308 4319 Test word for integer literal
4309 4320
4310 4321 $ hg log -R a --template "{word(2, desc)}\n" -r0
4311 4322 line
4312 4323
4313 4324 Test word for invalid numbers
4314 4325
4315 4326 $ hg log -Gv -R a --template "{word('a', desc)}"
4316 4327 hg: parse error: word expects an integer index
4317 4328 [255]
4318 4329
4319 4330 Test word for out of range
4320 4331
4321 4332 $ hg log -R a --template "{word(10000, desc)}"
4322 4333 $ hg log -R a --template "{word(-10000, desc)}"
4323 4334
4324 4335 Test indent and not adding to empty lines
4325 4336
4326 4337 $ hg log -T "-----\n{indent(desc, '>> ', ' > ')}\n" -r 0:1 -R a
4327 4338 -----
4328 4339 > line 1
4329 4340 >> line 2
4330 4341 -----
4331 4342 > other 1
4332 4343 >> other 2
4333 4344
4334 4345 >> other 3
4335 4346
4336 4347 Test with non-strings like dates
4337 4348
4338 4349 $ hg log -T "{indent(date, ' ')}\n" -r 2:3 -R a
4339 4350 1200000.00
4340 4351 1300000.00
4341 4352
4342 4353 Test broken string escapes:
4343 4354
4344 4355 $ hg log -T "bogus\\" -R a
4345 4356 hg: parse error: trailing \ in string
4346 4357 [255]
4347 4358 $ hg log -T "\\xy" -R a
4348 4359 hg: parse error: invalid \x escape
4349 4360 [255]
4350 4361
4351 4362 json filter should escape HTML tags so that the output can be embedded in hgweb:
4352 4363
4353 4364 $ hg log -T "{'<foo@example.org>'|json}\n" -R a -l1
4354 4365 "\u003cfoo@example.org\u003e"
4355 4366
4356 4367 Templater supports aliases of symbol and func() styles:
4357 4368
4358 4369 $ hg clone -q a aliases
4359 4370 $ cd aliases
4360 4371 $ cat <<EOF >> .hg/hgrc
4361 4372 > [templatealias]
4362 4373 > r = rev
4363 4374 > rn = "{r}:{node|short}"
4364 4375 > status(c, files) = files % "{c} {file}\n"
4365 4376 > utcdate(d) = localdate(d, "UTC")
4366 4377 > EOF
4367 4378
4368 4379 $ hg debugtemplate -vr0 '{rn} {utcdate(date)|isodate}\n'
4369 4380 (template
4370 4381 (symbol 'rn')
4371 4382 (string ' ')
4372 4383 (|
4373 4384 (func
4374 4385 (symbol 'utcdate')
4375 4386 (symbol 'date'))
4376 4387 (symbol 'isodate'))
4377 4388 (string '\n'))
4378 4389 * expanded:
4379 4390 (template
4380 4391 (template
4381 4392 (symbol 'rev')
4382 4393 (string ':')
4383 4394 (|
4384 4395 (symbol 'node')
4385 4396 (symbol 'short')))
4386 4397 (string ' ')
4387 4398 (|
4388 4399 (func
4389 4400 (symbol 'localdate')
4390 4401 (list
4391 4402 (symbol 'date')
4392 4403 (string 'UTC')))
4393 4404 (symbol 'isodate'))
4394 4405 (string '\n'))
4395 4406 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
4396 4407
4397 4408 $ hg debugtemplate -vr0 '{status("A", file_adds)}'
4398 4409 (template
4399 4410 (func
4400 4411 (symbol 'status')
4401 4412 (list
4402 4413 (string 'A')
4403 4414 (symbol 'file_adds'))))
4404 4415 * expanded:
4405 4416 (template
4406 4417 (%
4407 4418 (symbol 'file_adds')
4408 4419 (template
4409 4420 (string 'A')
4410 4421 (string ' ')
4411 4422 (symbol 'file')
4412 4423 (string '\n'))))
4413 4424 A a
4414 4425
4415 4426 A unary function alias can be called as a filter:
4416 4427
4417 4428 $ hg debugtemplate -vr0 '{date|utcdate|isodate}\n'
4418 4429 (template
4419 4430 (|
4420 4431 (|
4421 4432 (symbol 'date')
4422 4433 (symbol 'utcdate'))
4423 4434 (symbol 'isodate'))
4424 4435 (string '\n'))
4425 4436 * expanded:
4426 4437 (template
4427 4438 (|
4428 4439 (func
4429 4440 (symbol 'localdate')
4430 4441 (list
4431 4442 (symbol 'date')
4432 4443 (string 'UTC')))
4433 4444 (symbol 'isodate'))
4434 4445 (string '\n'))
4435 4446 1970-01-12 13:46 +0000
4436 4447
4437 4448 Aliases should be applied only to command arguments and templates in hgrc.
4438 4449 Otherwise, our stock styles and web templates could be corrupted:
4439 4450
4440 4451 $ hg log -r0 -T '{rn} {utcdate(date)|isodate}\n'
4441 4452 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
4442 4453
4443 4454 $ hg log -r0 --config ui.logtemplate='"{rn} {utcdate(date)|isodate}\n"'
4444 4455 0:1e4e1b8f71e0 1970-01-12 13:46 +0000
4445 4456
4446 4457 $ cat <<EOF > tmpl
4447 4458 > changeset = 'nothing expanded:{rn}\n'
4448 4459 > EOF
4449 4460 $ hg log -r0 --style ./tmpl
4450 4461 nothing expanded:
4451 4462
4452 4463 Aliases in formatter:
4453 4464
4454 4465 $ hg branches -T '{pad(branch, 7)} {rn}\n'
4455 4466 default 6:d41e714fe50d
4456 4467 foo 4:bbe44766e73d
4457 4468
4458 4469 Aliases should honor HGPLAIN:
4459 4470
4460 4471 $ HGPLAIN= hg log -r0 -T 'nothing expanded:{rn}\n'
4461 4472 nothing expanded:
4462 4473 $ HGPLAINEXCEPT=templatealias hg log -r0 -T '{rn}\n'
4463 4474 0:1e4e1b8f71e0
4464 4475
4465 4476 Unparsable alias:
4466 4477
4467 4478 $ hg debugtemplate --config templatealias.bad='x(' -v '{bad}'
4468 4479 (template
4469 4480 (symbol 'bad'))
4470 4481 abort: bad definition of template alias "bad": at 2: not a prefix: end
4471 4482 [255]
4472 4483 $ hg log --config templatealias.bad='x(' -T '{bad}'
4473 4484 abort: bad definition of template alias "bad": at 2: not a prefix: end
4474 4485 [255]
4475 4486
4476 4487 $ cd ..
4477 4488
4478 4489 Set up repository for non-ascii encoding tests:
4479 4490
4480 4491 $ hg init nonascii
4481 4492 $ cd nonascii
4482 4493 $ $PYTHON <<EOF
4483 4494 > open('latin1', 'w').write('\xe9')
4484 4495 > open('utf-8', 'w').write('\xc3\xa9')
4485 4496 > EOF
4486 4497 $ HGENCODING=utf-8 hg branch -q `cat utf-8`
4487 4498 $ HGENCODING=utf-8 hg ci -qAm "non-ascii branch: `cat utf-8`" utf-8
4488 4499
4489 4500 json filter should try round-trip conversion to utf-8:
4490 4501
4491 4502 $ HGENCODING=ascii hg log -T "{branch|json}\n" -r0
4492 4503 "\u00e9"
4493 4504 $ HGENCODING=ascii hg log -T "{desc|json}\n" -r0
4494 4505 "non-ascii branch: \u00e9"
4495 4506
4496 4507 json filter takes input as utf-8b:
4497 4508
4498 4509 $ HGENCODING=ascii hg log -T "{'`cat utf-8`'|json}\n" -l1
4499 4510 "\u00e9"
4500 4511 $ HGENCODING=ascii hg log -T "{'`cat latin1`'|json}\n" -l1
4501 4512 "\udce9"
4502 4513
4503 4514 utf8 filter:
4504 4515
4505 4516 $ HGENCODING=ascii hg log -T "round-trip: {branch|utf8|hex}\n" -r0
4506 4517 round-trip: c3a9
4507 4518 $ HGENCODING=latin1 hg log -T "decoded: {'`cat latin1`'|utf8|hex}\n" -l1
4508 4519 decoded: c3a9
4509 4520 $ HGENCODING=ascii hg log -T "replaced: {'`cat latin1`'|utf8|hex}\n" -l1
4510 4521 abort: decoding near * (glob)
4511 4522 [255]
4512 4523 $ hg log -T "invalid type: {rev|utf8}\n" -r0
4513 4524 abort: template filter 'utf8' is not compatible with keyword 'rev'
4514 4525 [255]
4515 4526
4516 4527 pad width:
4517 4528
4518 4529 $ HGENCODING=utf-8 hg debugtemplate "{pad('`cat utf-8`', 2, '-')}\n"
4519 4530 \xc3\xa9- (esc)
4520 4531
4521 4532 $ cd ..
4522 4533
4523 4534 Test that template function in extension is registered as expected
4524 4535
4525 4536 $ cd a
4526 4537
4527 4538 $ cat <<EOF > $TESTTMP/customfunc.py
4528 4539 > from mercurial import registrar
4529 4540 >
4530 4541 > templatefunc = registrar.templatefunc()
4531 4542 >
4532 4543 > @templatefunc('custom()')
4533 4544 > def custom(context, mapping, args):
4534 4545 > return 'custom'
4535 4546 > EOF
4536 4547 $ cat <<EOF > .hg/hgrc
4537 4548 > [extensions]
4538 4549 > customfunc = $TESTTMP/customfunc.py
4539 4550 > EOF
4540 4551
4541 4552 $ hg log -r . -T "{custom()}\n" --config customfunc.enabled=true
4542 4553 custom
4543 4554
4544 4555 $ cd ..
4545 4556
4546 4557 Test 'graphwidth' in 'hg log' on various topologies. The key here is that the
4547 4558 printed graphwidths 3, 5, 7, etc. should all line up in their respective
4548 4559 columns. We don't care about other aspects of the graph rendering here.
4549 4560
4550 4561 $ hg init graphwidth
4551 4562 $ cd graphwidth
4552 4563
4553 4564 $ wrappabletext="a a a a a a a a a a a a"
4554 4565
4555 4566 $ printf "first\n" > file
4556 4567 $ hg add file
4557 4568 $ hg commit -m "$wrappabletext"
4558 4569
4559 4570 $ printf "first\nsecond\n" > file
4560 4571 $ hg commit -m "$wrappabletext"
4561 4572
4562 4573 $ hg checkout 0
4563 4574 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
4564 4575 $ printf "third\nfirst\n" > file
4565 4576 $ hg commit -m "$wrappabletext"
4566 4577 created new head
4567 4578
4568 4579 $ hg merge
4569 4580 merging file
4570 4581 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
4571 4582 (branch merge, don't forget to commit)
4572 4583
4573 4584 $ hg log --graph -T "{graphwidth}"
4574 4585 @ 3
4575 4586 |
4576 4587 | @ 5
4577 4588 |/
4578 4589 o 3
4579 4590
4580 4591 $ hg commit -m "$wrappabletext"
4581 4592
4582 4593 $ hg log --graph -T "{graphwidth}"
4583 4594 @ 5
4584 4595 |\
4585 4596 | o 5
4586 4597 | |
4587 4598 o | 5
4588 4599 |/
4589 4600 o 3
4590 4601
4591 4602
4592 4603 $ hg checkout 0
4593 4604 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
4594 4605 $ printf "third\nfirst\nsecond\n" > file
4595 4606 $ hg commit -m "$wrappabletext"
4596 4607 created new head
4597 4608
4598 4609 $ hg log --graph -T "{graphwidth}"
4599 4610 @ 3
4600 4611 |
4601 4612 | o 7
4602 4613 | |\
4603 4614 +---o 7
4604 4615 | |
4605 4616 | o 5
4606 4617 |/
4607 4618 o 3
4608 4619
4609 4620
4610 4621 $ hg log --graph -T "{graphwidth}" -r 3
4611 4622 o 5
4612 4623 |\
4613 4624 ~ ~
4614 4625
4615 4626 $ hg log --graph -T "{graphwidth}" -r 1
4616 4627 o 3
4617 4628 |
4618 4629 ~
4619 4630
4620 4631 $ hg merge
4621 4632 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
4622 4633 (branch merge, don't forget to commit)
4623 4634 $ hg commit -m "$wrappabletext"
4624 4635
4625 4636 $ printf "seventh\n" >> file
4626 4637 $ hg commit -m "$wrappabletext"
4627 4638
4628 4639 $ hg log --graph -T "{graphwidth}"
4629 4640 @ 3
4630 4641 |
4631 4642 o 5
4632 4643 |\
4633 4644 | o 5
4634 4645 | |
4635 4646 o | 7
4636 4647 |\ \
4637 4648 | o | 7
4638 4649 | |/
4639 4650 o / 5
4640 4651 |/
4641 4652 o 3
4642 4653
4643 4654
4644 4655 The point of graphwidth is to allow wrapping that accounts for the space taken
4645 4656 by the graph.
4646 4657
4647 4658 $ COLUMNS=10 hg log --graph -T "{fill(desc, termwidth - graphwidth)}"
4648 4659 @ a a a a
4649 4660 | a a a a
4650 4661 | a a a a
4651 4662 o a a a
4652 4663 |\ a a a
4653 4664 | | a a a
4654 4665 | | a a a
4655 4666 | o a a a
4656 4667 | | a a a
4657 4668 | | a a a
4658 4669 | | a a a
4659 4670 o | a a
4660 4671 |\ \ a a
4661 4672 | | | a a
4662 4673 | | | a a
4663 4674 | | | a a
4664 4675 | | | a a
4665 4676 | o | a a
4666 4677 | |/ a a
4667 4678 | | a a
4668 4679 | | a a
4669 4680 | | a a
4670 4681 | | a a
4671 4682 o | a a a
4672 4683 |/ a a a
4673 4684 | a a a
4674 4685 | a a a
4675 4686 o a a a a
4676 4687 a a a a
4677 4688 a a a a
4678 4689
4679 4690 Something tricky happens when there are elided nodes; the next drawn row of
4680 4691 edges can be more than one column wider, but the graph width only increases by
4681 4692 one column. The remaining columns are added in between the nodes.
4682 4693
4683 4694 $ hg log --graph -T "{graphwidth}" -r "0|2|4|5"
4684 4695 o 5
4685 4696 |\
4686 4697 | \
4687 4698 | :\
4688 4699 o : : 7
4689 4700 :/ /
4690 4701 : o 5
4691 4702 :/
4692 4703 o 3
4693 4704
4694 4705
4695 4706 $ cd ..
4696 4707
General Comments 0
You need to be logged in to leave comments. Login now