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