##// END OF EJS Templates
templates: define a {onelinesummary} keyword...
Martin von Zweigbergk -
r46472:dbc57472 default draft
parent child Browse files
Show More
@@ -1,991 +1,1004 b''
1 1 # templatekw.py - common changeset template keywords
2 2 #
3 3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 from .i18n import _
11 11 from .node import (
12 12 hex,
13 13 nullid,
14 14 wdirid,
15 15 wdirrev,
16 16 )
17 17
18 18 from . import (
19 19 diffutil,
20 20 encoding,
21 21 error,
22 22 hbisect,
23 23 i18n,
24 24 obsutil,
25 25 patch,
26 26 pycompat,
27 27 registrar,
28 28 scmutil,
29 29 templateutil,
30 30 util,
31 31 )
32 32 from .utils import stringutil
33 33
34 34 _hybrid = templateutil.hybrid
35 35 hybriddict = templateutil.hybriddict
36 36 hybridlist = templateutil.hybridlist
37 37 compatdict = templateutil.compatdict
38 38 compatlist = templateutil.compatlist
39 39 _showcompatlist = templateutil._showcompatlist
40 40
41 41
42 42 def getlatesttags(context, mapping, pattern=None):
43 43 '''return date, distance and name for the latest tag of rev'''
44 44 repo = context.resource(mapping, b'repo')
45 45 ctx = context.resource(mapping, b'ctx')
46 46 cache = context.resource(mapping, b'cache')
47 47
48 48 cachename = b'latesttags'
49 49 if pattern is not None:
50 50 cachename += b'-' + pattern
51 51 match = stringutil.stringmatcher(pattern)[2]
52 52 else:
53 53 match = util.always
54 54
55 55 if cachename not in cache:
56 56 # Cache mapping from rev to a tuple with tag date, tag
57 57 # distance and tag name
58 58 cache[cachename] = {-1: (0, 0, [b'null'])}
59 59 latesttags = cache[cachename]
60 60
61 61 rev = ctx.rev()
62 62 todo = [rev]
63 63 while todo:
64 64 rev = todo.pop()
65 65 if rev in latesttags:
66 66 continue
67 67 ctx = repo[rev]
68 68 tags = [
69 69 t
70 70 for t in ctx.tags()
71 71 if (repo.tagtype(t) and repo.tagtype(t) != b'local' and match(t))
72 72 ]
73 73 if tags:
74 74 latesttags[rev] = ctx.date()[0], 0, [t for t in sorted(tags)]
75 75 continue
76 76 try:
77 77 ptags = [latesttags[p.rev()] for p in ctx.parents()]
78 78 if len(ptags) > 1:
79 79 if ptags[0][2] == ptags[1][2]:
80 80 # The tuples are laid out so the right one can be found by
81 81 # comparison in this case.
82 82 pdate, pdist, ptag = max(ptags)
83 83 else:
84 84
85 85 def key(x):
86 86 tag = x[2][0]
87 87 if ctx.rev() is None:
88 88 # only() doesn't support wdir
89 89 prevs = [c.rev() for c in ctx.parents()]
90 90 changes = repo.revs(b'only(%ld, %s)', prevs, tag)
91 91 changessincetag = len(changes) + 1
92 92 else:
93 93 changes = repo.revs(b'only(%d, %s)', ctx.rev(), tag)
94 94 changessincetag = len(changes)
95 95 # Smallest number of changes since tag wins. Date is
96 96 # used as tiebreaker.
97 97 return [-changessincetag, x[0]]
98 98
99 99 pdate, pdist, ptag = max(ptags, key=key)
100 100 else:
101 101 pdate, pdist, ptag = ptags[0]
102 102 except KeyError:
103 103 # Cache miss - recurse
104 104 todo.append(rev)
105 105 todo.extend(p.rev() for p in ctx.parents())
106 106 continue
107 107 latesttags[rev] = pdate, pdist + 1, ptag
108 108 return latesttags[rev]
109 109
110 110
111 111 def getlogcolumns():
112 112 """Return a dict of log column labels"""
113 113 _ = pycompat.identity # temporarily disable gettext
114 114 # i18n: column positioning for "hg log"
115 115 columns = _(
116 116 b'bookmark: %s\n'
117 117 b'branch: %s\n'
118 118 b'changeset: %s\n'
119 119 b'copies: %s\n'
120 120 b'date: %s\n'
121 121 b'extra: %s=%s\n'
122 122 b'files+: %s\n'
123 123 b'files-: %s\n'
124 124 b'files: %s\n'
125 125 b'instability: %s\n'
126 126 b'manifest: %s\n'
127 127 b'obsolete: %s\n'
128 128 b'parent: %s\n'
129 129 b'phase: %s\n'
130 130 b'summary: %s\n'
131 131 b'tag: %s\n'
132 132 b'user: %s\n'
133 133 )
134 134 return dict(
135 135 zip(
136 136 [s.split(b':', 1)[0] for s in columns.splitlines()],
137 137 i18n._(columns).splitlines(True),
138 138 )
139 139 )
140 140
141 141
142 142 # basic internal templates
143 143 _changeidtmpl = b'{rev}:{node|formatnode}'
144 144
145 145 # default templates internally used for rendering of lists
146 146 defaulttempl = {
147 147 b'parent': _changeidtmpl + b' ',
148 148 b'manifest': _changeidtmpl,
149 149 b'file_copy': b'{name} ({source})',
150 150 b'envvar': b'{key}={value}',
151 151 b'extra': b'{key}={value|stringescape}',
152 152 }
153 153 # filecopy is preserved for compatibility reasons
154 154 defaulttempl[b'filecopy'] = defaulttempl[b'file_copy']
155 155
156 156 # keywords are callables (see registrar.templatekeyword for details)
157 157 keywords = {}
158 158 templatekeyword = registrar.templatekeyword(keywords)
159 159
160 160
161 161 @templatekeyword(b'author', requires={b'ctx'})
162 162 def showauthor(context, mapping):
163 163 """Alias for ``{user}``"""
164 164 return showuser(context, mapping)
165 165
166 166
167 167 @templatekeyword(b'bisect', requires={b'repo', b'ctx'})
168 168 def showbisect(context, mapping):
169 169 """String. The changeset bisection status."""
170 170 repo = context.resource(mapping, b'repo')
171 171 ctx = context.resource(mapping, b'ctx')
172 172 return hbisect.label(repo, ctx.node())
173 173
174 174
175 175 @templatekeyword(b'branch', requires={b'ctx'})
176 176 def showbranch(context, mapping):
177 177 """String. The name of the branch on which the changeset was
178 178 committed.
179 179 """
180 180 ctx = context.resource(mapping, b'ctx')
181 181 return ctx.branch()
182 182
183 183
184 184 @templatekeyword(b'branches', requires={b'ctx'})
185 185 def showbranches(context, mapping):
186 186 """List of strings. The name of the branch on which the
187 187 changeset was committed. Will be empty if the branch name was
188 188 default. (DEPRECATED)
189 189 """
190 190 ctx = context.resource(mapping, b'ctx')
191 191 branch = ctx.branch()
192 192 if branch != b'default':
193 193 return compatlist(
194 194 context, mapping, b'branch', [branch], plural=b'branches'
195 195 )
196 196 return compatlist(context, mapping, b'branch', [], plural=b'branches')
197 197
198 198
199 199 @templatekeyword(b'bookmarks', requires={b'repo', b'ctx'})
200 200 def showbookmarks(context, mapping):
201 201 """List of strings. Any bookmarks associated with the
202 202 changeset. Also sets 'active', the name of the active bookmark.
203 203 """
204 204 repo = context.resource(mapping, b'repo')
205 205 ctx = context.resource(mapping, b'ctx')
206 206 bookmarks = ctx.bookmarks()
207 207 active = repo._activebookmark
208 208 makemap = lambda v: {b'bookmark': v, b'active': active, b'current': active}
209 209 f = _showcompatlist(context, mapping, b'bookmark', bookmarks)
210 210 return _hybrid(f, bookmarks, makemap, pycompat.identity)
211 211
212 212
213 213 @templatekeyword(b'children', requires={b'ctx'})
214 214 def showchildren(context, mapping):
215 215 """List of strings. The children of the changeset."""
216 216 ctx = context.resource(mapping, b'ctx')
217 217 childrevs = [b'%d:%s' % (cctx.rev(), cctx) for cctx in ctx.children()]
218 218 return compatlist(
219 219 context, mapping, b'children', childrevs, element=b'child'
220 220 )
221 221
222 222
223 223 # Deprecated, but kept alive for help generation a purpose.
224 224 @templatekeyword(b'currentbookmark', requires={b'repo', b'ctx'})
225 225 def showcurrentbookmark(context, mapping):
226 226 """String. The active bookmark, if it is associated with the changeset.
227 227 (DEPRECATED)"""
228 228 return showactivebookmark(context, mapping)
229 229
230 230
231 231 @templatekeyword(b'activebookmark', requires={b'repo', b'ctx'})
232 232 def showactivebookmark(context, mapping):
233 233 """String. The active bookmark, if it is associated with the changeset."""
234 234 repo = context.resource(mapping, b'repo')
235 235 ctx = context.resource(mapping, b'ctx')
236 236 active = repo._activebookmark
237 237 if active and active in ctx.bookmarks():
238 238 return active
239 239 return b''
240 240
241 241
242 242 @templatekeyword(b'date', requires={b'ctx'})
243 243 def showdate(context, mapping):
244 244 """Date information. The date when the changeset was committed."""
245 245 ctx = context.resource(mapping, b'ctx')
246 246 # the default string format is '<float(unixtime)><tzoffset>' because
247 247 # python-hglib splits date at decimal separator.
248 248 return templateutil.date(ctx.date(), showfmt=b'%d.0%d')
249 249
250 250
251 251 @templatekeyword(b'desc', requires={b'ctx'})
252 252 def showdescription(context, mapping):
253 253 """String. The text of the changeset description."""
254 254 ctx = context.resource(mapping, b'ctx')
255 255 s = ctx.description()
256 256 if isinstance(s, encoding.localstr):
257 257 # try hard to preserve utf-8 bytes
258 258 return encoding.tolocal(encoding.fromlocal(s).strip())
259 259 elif isinstance(s, encoding.safelocalstr):
260 260 return encoding.safelocalstr(s.strip())
261 261 else:
262 262 return s.strip()
263 263
264 264
265 265 @templatekeyword(b'diffstat', requires={b'ui', b'ctx'})
266 266 def showdiffstat(context, mapping):
267 267 """String. Statistics of changes with the following format:
268 268 "modified files: +added/-removed lines"
269 269 """
270 270 ui = context.resource(mapping, b'ui')
271 271 ctx = context.resource(mapping, b'ctx')
272 272 diffopts = diffutil.diffallopts(ui, {b'noprefix': False})
273 273 diff = ctx.diff(opts=diffopts)
274 274 stats = patch.diffstatdata(util.iterlines(diff))
275 275 maxname, maxtotal, adds, removes, binary = patch.diffstatsum(stats)
276 276 return b'%d: +%d/-%d' % (len(stats), adds, removes)
277 277
278 278
279 279 @templatekeyword(b'envvars', requires={b'ui'})
280 280 def showenvvars(context, mapping):
281 281 """A dictionary of environment variables. (EXPERIMENTAL)"""
282 282 ui = context.resource(mapping, b'ui')
283 283 env = ui.exportableenviron()
284 284 env = util.sortdict((k, env[k]) for k in sorted(env))
285 285 return compatdict(context, mapping, b'envvar', env, plural=b'envvars')
286 286
287 287
288 288 @templatekeyword(b'extras', requires={b'ctx'})
289 289 def showextras(context, mapping):
290 290 """List of dicts with key, value entries of the 'extras'
291 291 field of this changeset."""
292 292 ctx = context.resource(mapping, b'ctx')
293 293 extras = ctx.extra()
294 294 extras = util.sortdict((k, extras[k]) for k in sorted(extras))
295 295 makemap = lambda k: {b'key': k, b'value': extras[k]}
296 296 c = [makemap(k) for k in extras]
297 297 f = _showcompatlist(context, mapping, b'extra', c, plural=b'extras')
298 298 return _hybrid(
299 299 f,
300 300 extras,
301 301 makemap,
302 302 lambda k: b'%s=%s' % (k, stringutil.escapestr(extras[k])),
303 303 )
304 304
305 305
306 306 def _getfilestatus(context, mapping, listall=False):
307 307 ctx = context.resource(mapping, b'ctx')
308 308 revcache = context.resource(mapping, b'revcache')
309 309 if b'filestatus' not in revcache or revcache[b'filestatusall'] < listall:
310 310 stat = ctx.p1().status(
311 311 ctx, listignored=listall, listclean=listall, listunknown=listall
312 312 )
313 313 revcache[b'filestatus'] = stat
314 314 revcache[b'filestatusall'] = listall
315 315 return revcache[b'filestatus']
316 316
317 317
318 318 def _getfilestatusmap(context, mapping, listall=False):
319 319 revcache = context.resource(mapping, b'revcache')
320 320 if b'filestatusmap' not in revcache or revcache[b'filestatusall'] < listall:
321 321 stat = _getfilestatus(context, mapping, listall=listall)
322 322 revcache[b'filestatusmap'] = statmap = {}
323 323 for char, files in zip(pycompat.iterbytestr(b'MAR!?IC'), stat):
324 324 statmap.update((f, char) for f in files)
325 325 return revcache[b'filestatusmap'] # {path: statchar}
326 326
327 327
328 328 @templatekeyword(
329 329 b'file_copies', requires={b'repo', b'ctx', b'cache', b'revcache'}
330 330 )
331 331 def showfilecopies(context, mapping):
332 332 """List of strings. Files copied in this changeset with
333 333 their sources.
334 334 """
335 335 repo = context.resource(mapping, b'repo')
336 336 ctx = context.resource(mapping, b'ctx')
337 337 cache = context.resource(mapping, b'cache')
338 338 copies = context.resource(mapping, b'revcache').get(b'copies')
339 339 if copies is None:
340 340 if b'getcopies' not in cache:
341 341 cache[b'getcopies'] = scmutil.getcopiesfn(repo)
342 342 getcopies = cache[b'getcopies']
343 343 copies = getcopies(ctx)
344 344 return templateutil.compatfilecopiesdict(
345 345 context, mapping, b'file_copy', copies
346 346 )
347 347
348 348
349 349 # showfilecopiesswitch() displays file copies only if copy records are
350 350 # provided before calling the templater, usually with a --copies
351 351 # command line switch.
352 352 @templatekeyword(b'file_copies_switch', requires={b'revcache'})
353 353 def showfilecopiesswitch(context, mapping):
354 354 """List of strings. Like "file_copies" but displayed
355 355 only if the --copied switch is set.
356 356 """
357 357 copies = context.resource(mapping, b'revcache').get(b'copies') or []
358 358 return templateutil.compatfilecopiesdict(
359 359 context, mapping, b'file_copy', copies
360 360 )
361 361
362 362
363 363 @templatekeyword(b'file_adds', requires={b'ctx', b'revcache'})
364 364 def showfileadds(context, mapping):
365 365 """List of strings. Files added by this changeset."""
366 366 ctx = context.resource(mapping, b'ctx')
367 367 return templateutil.compatfileslist(
368 368 context, mapping, b'file_add', ctx.filesadded()
369 369 )
370 370
371 371
372 372 @templatekeyword(b'file_dels', requires={b'ctx', b'revcache'})
373 373 def showfiledels(context, mapping):
374 374 """List of strings. Files removed by this changeset."""
375 375 ctx = context.resource(mapping, b'ctx')
376 376 return templateutil.compatfileslist(
377 377 context, mapping, b'file_del', ctx.filesremoved()
378 378 )
379 379
380 380
381 381 @templatekeyword(b'file_mods', requires={b'ctx', b'revcache'})
382 382 def showfilemods(context, mapping):
383 383 """List of strings. Files modified by this changeset."""
384 384 ctx = context.resource(mapping, b'ctx')
385 385 return templateutil.compatfileslist(
386 386 context, mapping, b'file_mod', ctx.filesmodified()
387 387 )
388 388
389 389
390 390 @templatekeyword(b'files', requires={b'ctx'})
391 391 def showfiles(context, mapping):
392 392 """List of strings. All files modified, added, or removed by this
393 393 changeset.
394 394 """
395 395 ctx = context.resource(mapping, b'ctx')
396 396 return templateutil.compatfileslist(context, mapping, b'file', ctx.files())
397 397
398 398
399 399 @templatekeyword(b'graphnode', requires={b'repo', b'ctx', b'cache'})
400 400 def showgraphnode(context, mapping):
401 401 """String. The character representing the changeset node in an ASCII
402 402 revision graph."""
403 403 repo = context.resource(mapping, b'repo')
404 404 ctx = context.resource(mapping, b'ctx')
405 405 cache = context.resource(mapping, b'cache')
406 406 return getgraphnode(repo, ctx, cache)
407 407
408 408
409 409 def getgraphnode(repo, ctx, cache):
410 410 return getgraphnodecurrent(repo, ctx, cache) or getgraphnodesymbol(ctx)
411 411
412 412
413 413 def getgraphnodecurrent(repo, ctx, cache):
414 414 wpnodes = repo.dirstate.parents()
415 415 if wpnodes[1] == nullid:
416 416 wpnodes = wpnodes[:1]
417 417 if ctx.node() in wpnodes:
418 418 return b'@'
419 419 else:
420 420 merge_nodes = cache.get(b'merge_nodes')
421 421 if merge_nodes is None:
422 422 from . import mergestate as mergestatemod
423 423
424 424 mergestate = mergestatemod.mergestate.read(repo)
425 425 if mergestate.unresolvedcount():
426 426 merge_nodes = (mergestate.local, mergestate.other)
427 427 else:
428 428 merge_nodes = ()
429 429 cache[b'merge_nodes'] = merge_nodes
430 430
431 431 if ctx.node() in merge_nodes:
432 432 return b'%'
433 433 return b''
434 434
435 435
436 436 def getgraphnodesymbol(ctx):
437 437 if ctx.obsolete():
438 438 return b'x'
439 439 elif ctx.isunstable():
440 440 return b'*'
441 441 elif ctx.closesbranch():
442 442 return b'_'
443 443 else:
444 444 return b'o'
445 445
446 446
447 447 @templatekeyword(b'graphwidth', requires=())
448 448 def showgraphwidth(context, mapping):
449 449 """Integer. The width of the graph drawn by 'log --graph' or zero."""
450 450 # just hosts documentation; should be overridden by template mapping
451 451 return 0
452 452
453 453
454 454 @templatekeyword(b'index', requires=())
455 455 def showindex(context, mapping):
456 456 """Integer. The current iteration of the loop. (0 indexed)"""
457 457 # just hosts documentation; should be overridden by template mapping
458 458 raise error.Abort(_(b"can't use index in this context"))
459 459
460 460
461 461 @templatekeyword(b'latesttag', requires={b'repo', b'ctx', b'cache'})
462 462 def showlatesttag(context, mapping):
463 463 """List of strings. The global tags on the most recent globally
464 464 tagged ancestor of this changeset. If no such tags exist, the list
465 465 consists of the single string "null".
466 466 """
467 467 return showlatesttags(context, mapping, None)
468 468
469 469
470 470 def showlatesttags(context, mapping, pattern):
471 471 """helper method for the latesttag keyword and function"""
472 472 latesttags = getlatesttags(context, mapping, pattern)
473 473
474 474 # latesttag[0] is an implementation detail for sorting csets on different
475 475 # branches in a stable manner- it is the date the tagged cset was created,
476 476 # not the date the tag was created. Therefore it isn't made visible here.
477 477 makemap = lambda v: {
478 478 b'changes': _showchangessincetag,
479 479 b'distance': latesttags[1],
480 480 b'latesttag': v, # BC with {latesttag % '{latesttag}'}
481 481 b'tag': v,
482 482 }
483 483
484 484 tags = latesttags[2]
485 485 f = _showcompatlist(context, mapping, b'latesttag', tags, separator=b':')
486 486 return _hybrid(f, tags, makemap, pycompat.identity)
487 487
488 488
489 489 @templatekeyword(b'latesttagdistance', requires={b'repo', b'ctx', b'cache'})
490 490 def showlatesttagdistance(context, mapping):
491 491 """Integer. Longest path to the latest tag."""
492 492 return getlatesttags(context, mapping)[1]
493 493
494 494
495 495 @templatekeyword(b'changessincelatesttag', requires={b'repo', b'ctx', b'cache'})
496 496 def showchangessincelatesttag(context, mapping):
497 497 """Integer. All ancestors not in the latest tag."""
498 498 tag = getlatesttags(context, mapping)[2][0]
499 499 mapping = context.overlaymap(mapping, {b'tag': tag})
500 500 return _showchangessincetag(context, mapping)
501 501
502 502
503 503 def _showchangessincetag(context, mapping):
504 504 repo = context.resource(mapping, b'repo')
505 505 ctx = context.resource(mapping, b'ctx')
506 506 offset = 0
507 507 revs = [ctx.rev()]
508 508 tag = context.symbol(mapping, b'tag')
509 509
510 510 # The only() revset doesn't currently support wdir()
511 511 if ctx.rev() is None:
512 512 offset = 1
513 513 revs = [p.rev() for p in ctx.parents()]
514 514
515 515 return len(repo.revs(b'only(%ld, %s)', revs, tag)) + offset
516 516
517 517
518 518 # teach templater latesttags.changes is switched to (context, mapping) API
519 519 _showchangessincetag._requires = {b'repo', b'ctx'}
520 520
521 521
522 522 @templatekeyword(b'manifest', requires={b'repo', b'ctx'})
523 523 def showmanifest(context, mapping):
524 524 repo = context.resource(mapping, b'repo')
525 525 ctx = context.resource(mapping, b'ctx')
526 526 mnode = ctx.manifestnode()
527 527 if mnode is None:
528 528 mnode = wdirid
529 529 mrev = wdirrev
530 530 else:
531 531 mrev = repo.manifestlog.rev(mnode)
532 532 mhex = hex(mnode)
533 533 mapping = context.overlaymap(mapping, {b'rev': mrev, b'node': mhex})
534 534 f = context.process(b'manifest', mapping)
535 535 return templateutil.hybriditem(
536 536 f, None, f, lambda x: {b'rev': mrev, b'node': mhex}
537 537 )
538 538
539 539
540 540 @templatekeyword(b'obsfate', requires={b'ui', b'repo', b'ctx'})
541 541 def showobsfate(context, mapping):
542 542 # this function returns a list containing pre-formatted obsfate strings.
543 543 #
544 544 # This function will be replaced by templates fragments when we will have
545 545 # the verbosity templatekw available.
546 546 succsandmarkers = showsuccsandmarkers(context, mapping)
547 547
548 548 ui = context.resource(mapping, b'ui')
549 549 repo = context.resource(mapping, b'repo')
550 550 values = []
551 551
552 552 for x in succsandmarkers.tovalue(context, mapping):
553 553 v = obsutil.obsfateprinter(
554 554 ui, repo, x[b'successors'], x[b'markers'], scmutil.formatchangeid
555 555 )
556 556 values.append(v)
557 557
558 558 return compatlist(context, mapping, b"fate", values)
559 559
560 560
561 561 def shownames(context, mapping, namespace):
562 562 """helper method to generate a template keyword for a namespace"""
563 563 repo = context.resource(mapping, b'repo')
564 564 ctx = context.resource(mapping, b'ctx')
565 565 ns = repo.names.get(namespace)
566 566 if ns is None:
567 567 # namespaces.addnamespace() registers new template keyword, but
568 568 # the registered namespace might not exist in the current repo.
569 569 return
570 570 names = ns.names(repo, ctx.node())
571 571 return compatlist(
572 572 context, mapping, ns.templatename, names, plural=namespace
573 573 )
574 574
575 575
576 576 @templatekeyword(b'namespaces', requires={b'repo', b'ctx'})
577 577 def shownamespaces(context, mapping):
578 578 """Dict of lists. Names attached to this changeset per
579 579 namespace."""
580 580 repo = context.resource(mapping, b'repo')
581 581 ctx = context.resource(mapping, b'ctx')
582 582
583 583 namespaces = util.sortdict()
584 584
585 585 def makensmapfn(ns):
586 586 # 'name' for iterating over namespaces, templatename for local reference
587 587 return lambda v: {b'name': v, ns.templatename: v}
588 588
589 589 for k, ns in pycompat.iteritems(repo.names):
590 590 names = ns.names(repo, ctx.node())
591 591 f = _showcompatlist(context, mapping, b'name', names)
592 592 namespaces[k] = _hybrid(f, names, makensmapfn(ns), pycompat.identity)
593 593
594 594 f = _showcompatlist(context, mapping, b'namespace', list(namespaces))
595 595
596 596 def makemap(ns):
597 597 return {
598 598 b'namespace': ns,
599 599 b'names': namespaces[ns],
600 600 b'builtin': repo.names[ns].builtin,
601 601 b'colorname': repo.names[ns].colorname,
602 602 }
603 603
604 604 return _hybrid(f, namespaces, makemap, pycompat.identity)
605 605
606 606
607 607 @templatekeyword(b'negrev', requires={b'repo', b'ctx'})
608 608 def shownegrev(context, mapping):
609 609 """Integer. The repository-local changeset negative revision number,
610 610 which counts in the opposite direction."""
611 611 ctx = context.resource(mapping, b'ctx')
612 612 rev = ctx.rev()
613 613 if rev is None or rev < 0: # wdir() or nullrev?
614 614 return None
615 615 repo = context.resource(mapping, b'repo')
616 616 return rev - len(repo)
617 617
618 618
619 619 @templatekeyword(b'node', requires={b'ctx'})
620 620 def shownode(context, mapping):
621 621 """String. The changeset identification hash, as a 40 hexadecimal
622 622 digit string.
623 623 """
624 624 ctx = context.resource(mapping, b'ctx')
625 625 return ctx.hex()
626 626
627 627
628 628 @templatekeyword(b'obsolete', requires={b'ctx'})
629 629 def showobsolete(context, mapping):
630 630 """String. Whether the changeset is obsolete. (EXPERIMENTAL)"""
631 631 ctx = context.resource(mapping, b'ctx')
632 632 if ctx.obsolete():
633 633 return b'obsolete'
634 634 return b''
635 635
636 636
637 @templatekeyword(b'onelinesummary', requires={b'ui', b'ctx'})
638 def showonelinesummary(context, mapping):
639 """String. A one-line summary for the ctx (not including trailing newline).
640 The default template be overridden in command-templates.oneline-summary."""
641 # Avoid cycle:
642 # mercurial.cmdutil -> mercurial.templatekw -> mercurial.cmdutil
643 from . import cmdutil
644
645 ui = context.resource(mapping, b'ui')
646 ctx = context.resource(mapping, b'ctx')
647 return cmdutil.format_changeset_summary(ui, ctx)
648
649
637 650 @templatekeyword(b'path', requires={b'fctx'})
638 651 def showpath(context, mapping):
639 652 """String. Repository-absolute path of the current file. (EXPERIMENTAL)"""
640 653 fctx = context.resource(mapping, b'fctx')
641 654 return fctx.path()
642 655
643 656
644 657 @templatekeyword(b'peerurls', requires={b'repo'})
645 658 def showpeerurls(context, mapping):
646 659 """A dictionary of repository locations defined in the [paths] section
647 660 of your configuration file."""
648 661 repo = context.resource(mapping, b'repo')
649 662 # see commands.paths() for naming of dictionary keys
650 663 paths = repo.ui.paths
651 664 urls = util.sortdict(
652 665 (k, p.rawloc) for k, p in sorted(pycompat.iteritems(paths))
653 666 )
654 667
655 668 def makemap(k):
656 669 p = paths[k]
657 670 d = {b'name': k, b'url': p.rawloc}
658 671 d.update((o, v) for o, v in sorted(pycompat.iteritems(p.suboptions)))
659 672 return d
660 673
661 674 return _hybrid(None, urls, makemap, lambda k: b'%s=%s' % (k, urls[k]))
662 675
663 676
664 677 @templatekeyword(b"predecessors", requires={b'repo', b'ctx'})
665 678 def showpredecessors(context, mapping):
666 679 """Returns the list of the closest visible predecessors. (EXPERIMENTAL)"""
667 680 repo = context.resource(mapping, b'repo')
668 681 ctx = context.resource(mapping, b'ctx')
669 682 predecessors = sorted(obsutil.closestpredecessors(repo, ctx.node()))
670 683 predecessors = pycompat.maplist(hex, predecessors)
671 684
672 685 return _hybrid(
673 686 None,
674 687 predecessors,
675 688 lambda x: {b'ctx': repo[x]},
676 689 lambda x: scmutil.formatchangeid(repo[x]),
677 690 )
678 691
679 692
680 693 @templatekeyword(b'reporoot', requires={b'repo'})
681 694 def showreporoot(context, mapping):
682 695 """String. The root directory of the current repository."""
683 696 repo = context.resource(mapping, b'repo')
684 697 return repo.root
685 698
686 699
687 700 @templatekeyword(b'size', requires={b'fctx'})
688 701 def showsize(context, mapping):
689 702 """Integer. Size of the current file in bytes. (EXPERIMENTAL)"""
690 703 fctx = context.resource(mapping, b'fctx')
691 704 return fctx.size()
692 705
693 706
694 707 # requires 'fctx' to denote {status} depends on (ctx, path) pair
695 708 @templatekeyword(b'status', requires={b'ctx', b'fctx', b'revcache'})
696 709 def showstatus(context, mapping):
697 710 """String. Status code of the current file. (EXPERIMENTAL)"""
698 711 path = templateutil.runsymbol(context, mapping, b'path')
699 712 path = templateutil.stringify(context, mapping, path)
700 713 if not path:
701 714 return
702 715 statmap = _getfilestatusmap(context, mapping)
703 716 if path not in statmap:
704 717 statmap = _getfilestatusmap(context, mapping, listall=True)
705 718 return statmap.get(path)
706 719
707 720
708 721 @templatekeyword(b"successorssets", requires={b'repo', b'ctx'})
709 722 def showsuccessorssets(context, mapping):
710 723 """Returns a string of sets of successors for a changectx. Format used
711 724 is: [ctx1, ctx2], [ctx3] if ctx has been split into ctx1 and ctx2
712 725 while also diverged into ctx3. (EXPERIMENTAL)"""
713 726 repo = context.resource(mapping, b'repo')
714 727 ctx = context.resource(mapping, b'ctx')
715 728 data = []
716 729
717 730 if ctx.obsolete():
718 731 ssets = obsutil.successorssets(repo, ctx.node(), closest=True)
719 732 ssets = [[hex(n) for n in ss] for ss in ssets]
720 733
721 734 for ss in ssets:
722 735 h = _hybrid(
723 736 None,
724 737 ss,
725 738 lambda x: {b'ctx': repo[x]},
726 739 lambda x: scmutil.formatchangeid(repo[x]),
727 740 )
728 741 data.append(h)
729 742
730 743 # Format the successorssets
731 744 def render(d):
732 745 return templateutil.stringify(context, mapping, d)
733 746
734 747 def gen(data):
735 748 yield b"; ".join(render(d) for d in data)
736 749
737 750 return _hybrid(
738 751 gen(data), data, lambda x: {b'successorset': x}, pycompat.identity
739 752 )
740 753
741 754
742 755 @templatekeyword(b"succsandmarkers", requires={b'repo', b'ctx'})
743 756 def showsuccsandmarkers(context, mapping):
744 757 """Returns a list of dict for each final successor of ctx. The dict
745 758 contains successors node id in "successors" keys and the list of
746 759 obs-markers from ctx to the set of successors in "markers".
747 760 (EXPERIMENTAL)
748 761 """
749 762 repo = context.resource(mapping, b'repo')
750 763 ctx = context.resource(mapping, b'ctx')
751 764
752 765 values = obsutil.successorsandmarkers(repo, ctx)
753 766
754 767 if values is None:
755 768 values = []
756 769
757 770 # Format successors and markers to avoid exposing binary to templates
758 771 data = []
759 772 for i in values:
760 773 # Format successors
761 774 successors = i[b'successors']
762 775
763 776 successors = [hex(n) for n in successors]
764 777 successors = _hybrid(
765 778 None,
766 779 successors,
767 780 lambda x: {b'ctx': repo[x]},
768 781 lambda x: scmutil.formatchangeid(repo[x]),
769 782 )
770 783
771 784 # Format markers
772 785 finalmarkers = []
773 786 for m in i[b'markers']:
774 787 hexprec = hex(m[0])
775 788 hexsucs = tuple(hex(n) for n in m[1])
776 789 hexparents = None
777 790 if m[5] is not None:
778 791 hexparents = tuple(hex(n) for n in m[5])
779 792 newmarker = (hexprec, hexsucs) + m[2:5] + (hexparents,) + m[6:]
780 793 finalmarkers.append(newmarker)
781 794
782 795 data.append({b'successors': successors, b'markers': finalmarkers})
783 796
784 797 return templateutil.mappinglist(data)
785 798
786 799
787 800 @templatekeyword(b'p1', requires={b'ctx'})
788 801 def showp1(context, mapping):
789 802 """Changeset. The changeset's first parent. ``{p1.rev}`` for the revision
790 803 number, and ``{p1.node}`` for the identification hash."""
791 804 ctx = context.resource(mapping, b'ctx')
792 805 return templateutil.mappingdict({b'ctx': ctx.p1()}, tmpl=_changeidtmpl)
793 806
794 807
795 808 @templatekeyword(b'p2', requires={b'ctx'})
796 809 def showp2(context, mapping):
797 810 """Changeset. The changeset's second parent. ``{p2.rev}`` for the revision
798 811 number, and ``{p2.node}`` for the identification hash."""
799 812 ctx = context.resource(mapping, b'ctx')
800 813 return templateutil.mappingdict({b'ctx': ctx.p2()}, tmpl=_changeidtmpl)
801 814
802 815
803 816 @templatekeyword(b'p1rev', requires={b'ctx'})
804 817 def showp1rev(context, mapping):
805 818 """Integer. The repository-local revision number of the changeset's
806 819 first parent, or -1 if the changeset has no parents. (DEPRECATED)"""
807 820 ctx = context.resource(mapping, b'ctx')
808 821 return ctx.p1().rev()
809 822
810 823
811 824 @templatekeyword(b'p2rev', requires={b'ctx'})
812 825 def showp2rev(context, mapping):
813 826 """Integer. The repository-local revision number of the changeset's
814 827 second parent, or -1 if the changeset has no second parent. (DEPRECATED)"""
815 828 ctx = context.resource(mapping, b'ctx')
816 829 return ctx.p2().rev()
817 830
818 831
819 832 @templatekeyword(b'p1node', requires={b'ctx'})
820 833 def showp1node(context, mapping):
821 834 """String. The identification hash of the changeset's first parent,
822 835 as a 40 digit hexadecimal string. If the changeset has no parents, all
823 836 digits are 0. (DEPRECATED)"""
824 837 ctx = context.resource(mapping, b'ctx')
825 838 return ctx.p1().hex()
826 839
827 840
828 841 @templatekeyword(b'p2node', requires={b'ctx'})
829 842 def showp2node(context, mapping):
830 843 """String. The identification hash of the changeset's second
831 844 parent, as a 40 digit hexadecimal string. If the changeset has no second
832 845 parent, all digits are 0. (DEPRECATED)"""
833 846 ctx = context.resource(mapping, b'ctx')
834 847 return ctx.p2().hex()
835 848
836 849
837 850 @templatekeyword(b'parents', requires={b'repo', b'ctx'})
838 851 def showparents(context, mapping):
839 852 """List of strings. The parents of the changeset in "rev:node"
840 853 format. If the changeset has only one "natural" parent (the predecessor
841 854 revision) nothing is shown."""
842 855 repo = context.resource(mapping, b'repo')
843 856 ctx = context.resource(mapping, b'ctx')
844 857 pctxs = scmutil.meaningfulparents(repo, ctx)
845 858 prevs = [p.rev() for p in pctxs]
846 859 parents = [
847 860 [(b'rev', p.rev()), (b'node', p.hex()), (b'phase', p.phasestr())]
848 861 for p in pctxs
849 862 ]
850 863 f = _showcompatlist(context, mapping, b'parent', parents)
851 864 return _hybrid(
852 865 f,
853 866 prevs,
854 867 lambda x: {b'ctx': repo[x]},
855 868 lambda x: scmutil.formatchangeid(repo[x]),
856 869 keytype=int,
857 870 )
858 871
859 872
860 873 @templatekeyword(b'phase', requires={b'ctx'})
861 874 def showphase(context, mapping):
862 875 """String. The changeset phase name."""
863 876 ctx = context.resource(mapping, b'ctx')
864 877 return ctx.phasestr()
865 878
866 879
867 880 @templatekeyword(b'phaseidx', requires={b'ctx'})
868 881 def showphaseidx(context, mapping):
869 882 """Integer. The changeset phase index. (ADVANCED)"""
870 883 ctx = context.resource(mapping, b'ctx')
871 884 return ctx.phase()
872 885
873 886
874 887 @templatekeyword(b'rev', requires={b'ctx'})
875 888 def showrev(context, mapping):
876 889 """Integer. The repository-local changeset revision number."""
877 890 ctx = context.resource(mapping, b'ctx')
878 891 return scmutil.intrev(ctx)
879 892
880 893
881 894 @templatekeyword(b'subrepos', requires={b'ctx'})
882 895 def showsubrepos(context, mapping):
883 896 """List of strings. Updated subrepositories in the changeset."""
884 897 ctx = context.resource(mapping, b'ctx')
885 898 substate = ctx.substate
886 899 if not substate:
887 900 return compatlist(context, mapping, b'subrepo', [])
888 901 psubstate = ctx.p1().substate or {}
889 902 subrepos = []
890 903 for sub in substate:
891 904 if sub not in psubstate or substate[sub] != psubstate[sub]:
892 905 subrepos.append(sub) # modified or newly added in ctx
893 906 for sub in psubstate:
894 907 if sub not in substate:
895 908 subrepos.append(sub) # removed in ctx
896 909 return compatlist(context, mapping, b'subrepo', sorted(subrepos))
897 910
898 911
899 912 # don't remove "showtags" definition, even though namespaces will put
900 913 # a helper function for "tags" keyword into "keywords" map automatically,
901 914 # because online help text is built without namespaces initialization
902 915 @templatekeyword(b'tags', requires={b'repo', b'ctx'})
903 916 def showtags(context, mapping):
904 917 """List of strings. Any tags associated with the changeset."""
905 918 return shownames(context, mapping, b'tags')
906 919
907 920
908 921 @templatekeyword(b'termwidth', requires={b'ui'})
909 922 def showtermwidth(context, mapping):
910 923 """Integer. The width of the current terminal."""
911 924 ui = context.resource(mapping, b'ui')
912 925 return ui.termwidth()
913 926
914 927
915 928 @templatekeyword(b'user', requires={b'ctx'})
916 929 def showuser(context, mapping):
917 930 """String. The unmodified author of the changeset."""
918 931 ctx = context.resource(mapping, b'ctx')
919 932 return ctx.user()
920 933
921 934
922 935 @templatekeyword(b'instabilities', requires={b'ctx'})
923 936 def showinstabilities(context, mapping):
924 937 """List of strings. Evolution instabilities affecting the changeset.
925 938 (EXPERIMENTAL)
926 939 """
927 940 ctx = context.resource(mapping, b'ctx')
928 941 return compatlist(
929 942 context,
930 943 mapping,
931 944 b'instability',
932 945 ctx.instabilities(),
933 946 plural=b'instabilities',
934 947 )
935 948
936 949
937 950 @templatekeyword(b'verbosity', requires={b'ui'})
938 951 def showverbosity(context, mapping):
939 952 """String. The current output verbosity in 'debug', 'quiet', 'verbose',
940 953 or ''."""
941 954 ui = context.resource(mapping, b'ui')
942 955 # see logcmdutil.changesettemplater for priority of these flags
943 956 if ui.debugflag:
944 957 return b'debug'
945 958 elif ui.quiet:
946 959 return b'quiet'
947 960 elif ui.verbose:
948 961 return b'verbose'
949 962 return b''
950 963
951 964
952 965 @templatekeyword(b'whyunstable', requires={b'repo', b'ctx'})
953 966 def showwhyunstable(context, mapping):
954 967 """List of dicts explaining all instabilities of a changeset.
955 968 (EXPERIMENTAL)
956 969 """
957 970 repo = context.resource(mapping, b'repo')
958 971 ctx = context.resource(mapping, b'ctx')
959 972
960 973 def formatnode(ctx):
961 974 return b'%s (%s)' % (scmutil.formatchangeid(ctx), ctx.phasestr())
962 975
963 976 entries = obsutil.whyunstable(repo, ctx)
964 977
965 978 for entry in entries:
966 979 if entry.get(b'divergentnodes'):
967 980 dnodes = entry[b'divergentnodes']
968 981 dnhybrid = _hybrid(
969 982 None,
970 983 [dnode.hex() for dnode in dnodes],
971 984 lambda x: {b'ctx': repo[x]},
972 985 lambda x: formatnode(repo[x]),
973 986 )
974 987 entry[b'divergentnodes'] = dnhybrid
975 988
976 989 tmpl = (
977 990 b'{instability}:{if(divergentnodes, " ")}{divergentnodes} '
978 991 b'{reason} {node|short}'
979 992 )
980 993 return templateutil.mappinglist(entries, tmpl=tmpl, sep=b'\n')
981 994
982 995
983 996 def loadkeyword(ui, extname, registrarobj):
984 997 """Load template keyword from specified registrarobj
985 998 """
986 999 for name, func in pycompat.iteritems(registrarobj._table):
987 1000 keywords[name] = func
988 1001
989 1002
990 1003 # tell hggettext to extract docstrings from these functions:
991 1004 i18nfunctions = keywords.values()
@@ -1,1380 +1,1404 b''
1 1 Test template keywords
2 2 ======================
3 3
4 4 $ hg init a
5 5 $ cd a
6 6 $ echo a > a
7 7 $ hg add a
8 8 $ echo line 1 > b
9 9 $ echo line 2 >> b
10 10 $ hg commit -l b -d '1000000 0' -u 'User Name <user@hostname>'
11 11
12 12 $ hg add b
13 13 $ echo other 1 > c
14 14 $ echo other 2 >> c
15 15 $ echo >> c
16 16 $ echo other 3 >> c
17 17 $ hg commit -l c -d '1100000 0' -u 'A. N. Other <other@place>'
18 18
19 19 $ hg add c
20 20 $ hg commit -m 'no person' -d '1200000 0' -u 'other@place'
21 21 $ echo c >> c
22 22 $ hg commit -m 'no user, no domain' -d '1300000 0' -u 'person'
23 23
24 24 $ echo foo > .hg/branch
25 25 $ hg commit -m 'new branch' -d '1400000 0' -u 'person'
26 26
27 27 $ hg co -q 3
28 28 $ echo other 4 >> d
29 29 $ hg add d
30 30 $ hg commit -m 'new head' -d '1500000 0' -u 'person'
31 31
32 32 $ hg merge -q foo
33 33 $ hg commit -m 'merge' -d '1500001 0' -u 'person'
34 34
35 35 Second branch starting at nullrev:
36 36
37 37 $ hg update null
38 38 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
39 39 $ echo second > second
40 40 $ hg add second
41 41 $ hg commit -m second -d '1000000 0' -u 'User Name <user@hostname>'
42 42 created new head
43 43
44 44 $ echo third > third
45 45 $ hg add third
46 46 $ hg mv second fourth
47 47 $ hg commit -m third -d "2020-01-01 10:01"
48 48
49 49 Working-directory revision has special identifiers, though they are still
50 50 experimental:
51 51
52 52 $ hg log -r 'wdir()' -T '{rev}:{node}\n'
53 53 2147483647:ffffffffffffffffffffffffffffffffffffffff
54 54
55 55 $ hg log -r 'wdir()' -Tjson --debug
56 56 [
57 57 {
58 58 "added": [],
59 59 "bookmarks": [],
60 60 "branch": "default",
61 61 "date": [0, 0],
62 62 "desc": "",
63 63 "extra": {"branch": "default"},
64 64 "manifest": "ffffffffffffffffffffffffffffffffffffffff",
65 65 "modified": [],
66 66 "node": "ffffffffffffffffffffffffffffffffffffffff",
67 67 "parents": ["95c24699272ef57d062b8bccc32c878bf841784a"],
68 68 "phase": "draft",
69 69 "removed": [],
70 70 "rev": 2147483647,
71 71 "tags": [],
72 72 "user": "test"
73 73 }
74 74 ]
75 75
76 76 $ hg log -r 'wdir()' -T '{manifest}\n'
77 77 2147483647:ffffffffffff
78 78
79 79 However, for negrev, we refuse to output anything (as well as for null)
80 80
81 81 $ hg log -r 'wdir() + null' -T 'bla{negrev}nk\n'
82 82 blank
83 83 blank
84 84
85 85 Changectx-derived keywords are disabled within {manifest} as {node} changes:
86 86
87 87 $ hg log -r0 -T 'outer:{p1node} {manifest % "inner:{p1node}"}\n'
88 88 outer:0000000000000000000000000000000000000000 inner:
89 89
90 90 Check that {phase} works correctly on parents:
91 91
92 92 $ cat << EOF > parentphase
93 93 > changeset_debug = '{rev} ({phase}):{parents}\n'
94 94 > parent = ' {rev} ({phase})'
95 95 > EOF
96 96 $ hg phase -r 5 --public
97 97 $ hg phase -r 7 --secret --force
98 98 $ hg log --debug -G --style ./parentphase
99 99 @ 8 (secret): 7 (secret) -1 (public)
100 100 |
101 101 o 7 (secret): -1 (public) -1 (public)
102 102
103 103 o 6 (draft): 5 (public) 4 (draft)
104 104 |\
105 105 | o 5 (public): 3 (public) -1 (public)
106 106 | |
107 107 o | 4 (draft): 3 (public) -1 (public)
108 108 |/
109 109 o 3 (public): 2 (public) -1 (public)
110 110 |
111 111 o 2 (public): 1 (public) -1 (public)
112 112 |
113 113 o 1 (public): 0 (public) -1 (public)
114 114 |
115 115 o 0 (public): -1 (public) -1 (public)
116 116
117 Test {onelinesummary}
118
119 $ hg log -G -T '{onelinesummary}'
120 @ 8:95c24699272e tip "third"
121 |
122 o 7:29114dbae42b "second"
123
124 o 6:d41e714fe50d "merge"
125 |\
126 | o 5:13207e5a10d9 "new head"
127 | |
128 o | 4:bbe44766e73d "new branch"
129 |/
130 o 3:10e46f2dcbf4 "no user, no domain"
131 |
132 o 2:97054abb4ab8 "no person"
133 |
134 o 1:b608e9d1a3f0 "other 1"
135 |
136 o 0:1e4e1b8f71e0 "line 1"
137
138 $ hg log -T '{onelinesummary}' -r 0 \
139 > --config command-templates.oneline-summary='{rev} - {desc}'
140 0 - line 1 (no-eol)
117 141
118 142 Keys work:
119 143
120 144 $ for key in author branch branches date desc file_adds file_dels file_mods \
121 145 > file_copies file_copies_switch files \
122 146 > manifest node parents rev tags diffstat extras \
123 147 > p1rev p2rev p1node p2node user; do
124 148 > for mode in '' --verbose --debug; do
125 149 > hg log $mode --template "$key$mode: {$key}\n"
126 150 > done
127 151 > done
128 152 author: test
129 153 author: User Name <user@hostname>
130 154 author: person
131 155 author: person
132 156 author: person
133 157 author: person
134 158 author: other@place
135 159 author: A. N. Other <other@place>
136 160 author: User Name <user@hostname>
137 161 author--verbose: test
138 162 author--verbose: User Name <user@hostname>
139 163 author--verbose: person
140 164 author--verbose: person
141 165 author--verbose: person
142 166 author--verbose: person
143 167 author--verbose: other@place
144 168 author--verbose: A. N. Other <other@place>
145 169 author--verbose: User Name <user@hostname>
146 170 author--debug: test
147 171 author--debug: User Name <user@hostname>
148 172 author--debug: person
149 173 author--debug: person
150 174 author--debug: person
151 175 author--debug: person
152 176 author--debug: other@place
153 177 author--debug: A. N. Other <other@place>
154 178 author--debug: User Name <user@hostname>
155 179 branch: default
156 180 branch: default
157 181 branch: default
158 182 branch: default
159 183 branch: foo
160 184 branch: default
161 185 branch: default
162 186 branch: default
163 187 branch: default
164 188 branch--verbose: default
165 189 branch--verbose: default
166 190 branch--verbose: default
167 191 branch--verbose: default
168 192 branch--verbose: foo
169 193 branch--verbose: default
170 194 branch--verbose: default
171 195 branch--verbose: default
172 196 branch--verbose: default
173 197 branch--debug: default
174 198 branch--debug: default
175 199 branch--debug: default
176 200 branch--debug: default
177 201 branch--debug: foo
178 202 branch--debug: default
179 203 branch--debug: default
180 204 branch--debug: default
181 205 branch--debug: default
182 206 branches:
183 207 branches:
184 208 branches:
185 209 branches:
186 210 branches: foo
187 211 branches:
188 212 branches:
189 213 branches:
190 214 branches:
191 215 branches--verbose:
192 216 branches--verbose:
193 217 branches--verbose:
194 218 branches--verbose:
195 219 branches--verbose: foo
196 220 branches--verbose:
197 221 branches--verbose:
198 222 branches--verbose:
199 223 branches--verbose:
200 224 branches--debug:
201 225 branches--debug:
202 226 branches--debug:
203 227 branches--debug:
204 228 branches--debug: foo
205 229 branches--debug:
206 230 branches--debug:
207 231 branches--debug:
208 232 branches--debug:
209 233 date: 1577872860.00
210 234 date: 1000000.00
211 235 date: 1500001.00
212 236 date: 1500000.00
213 237 date: 1400000.00
214 238 date: 1300000.00
215 239 date: 1200000.00
216 240 date: 1100000.00
217 241 date: 1000000.00
218 242 date--verbose: 1577872860.00
219 243 date--verbose: 1000000.00
220 244 date--verbose: 1500001.00
221 245 date--verbose: 1500000.00
222 246 date--verbose: 1400000.00
223 247 date--verbose: 1300000.00
224 248 date--verbose: 1200000.00
225 249 date--verbose: 1100000.00
226 250 date--verbose: 1000000.00
227 251 date--debug: 1577872860.00
228 252 date--debug: 1000000.00
229 253 date--debug: 1500001.00
230 254 date--debug: 1500000.00
231 255 date--debug: 1400000.00
232 256 date--debug: 1300000.00
233 257 date--debug: 1200000.00
234 258 date--debug: 1100000.00
235 259 date--debug: 1000000.00
236 260 desc: third
237 261 desc: second
238 262 desc: merge
239 263 desc: new head
240 264 desc: new branch
241 265 desc: no user, no domain
242 266 desc: no person
243 267 desc: other 1
244 268 other 2
245 269
246 270 other 3
247 271 desc: line 1
248 272 line 2
249 273 desc--verbose: third
250 274 desc--verbose: second
251 275 desc--verbose: merge
252 276 desc--verbose: new head
253 277 desc--verbose: new branch
254 278 desc--verbose: no user, no domain
255 279 desc--verbose: no person
256 280 desc--verbose: other 1
257 281 other 2
258 282
259 283 other 3
260 284 desc--verbose: line 1
261 285 line 2
262 286 desc--debug: third
263 287 desc--debug: second
264 288 desc--debug: merge
265 289 desc--debug: new head
266 290 desc--debug: new branch
267 291 desc--debug: no user, no domain
268 292 desc--debug: no person
269 293 desc--debug: other 1
270 294 other 2
271 295
272 296 other 3
273 297 desc--debug: line 1
274 298 line 2
275 299 file_adds: fourth third
276 300 file_adds: second
277 301 file_adds:
278 302 file_adds: d
279 303 file_adds:
280 304 file_adds:
281 305 file_adds: c
282 306 file_adds: b
283 307 file_adds: a
284 308 file_adds--verbose: fourth third
285 309 file_adds--verbose: second
286 310 file_adds--verbose:
287 311 file_adds--verbose: d
288 312 file_adds--verbose:
289 313 file_adds--verbose:
290 314 file_adds--verbose: c
291 315 file_adds--verbose: b
292 316 file_adds--verbose: a
293 317 file_adds--debug: fourth third
294 318 file_adds--debug: second
295 319 file_adds--debug:
296 320 file_adds--debug: d
297 321 file_adds--debug:
298 322 file_adds--debug:
299 323 file_adds--debug: c
300 324 file_adds--debug: b
301 325 file_adds--debug: a
302 326 file_dels: second
303 327 file_dels:
304 328 file_dels:
305 329 file_dels:
306 330 file_dels:
307 331 file_dels:
308 332 file_dels:
309 333 file_dels:
310 334 file_dels:
311 335 file_dels--verbose: second
312 336 file_dels--verbose:
313 337 file_dels--verbose:
314 338 file_dels--verbose:
315 339 file_dels--verbose:
316 340 file_dels--verbose:
317 341 file_dels--verbose:
318 342 file_dels--verbose:
319 343 file_dels--verbose:
320 344 file_dels--debug: second
321 345 file_dels--debug:
322 346 file_dels--debug:
323 347 file_dels--debug:
324 348 file_dels--debug:
325 349 file_dels--debug:
326 350 file_dels--debug:
327 351 file_dels--debug:
328 352 file_dels--debug:
329 353 file_mods:
330 354 file_mods:
331 355 file_mods:
332 356 file_mods:
333 357 file_mods:
334 358 file_mods: c
335 359 file_mods:
336 360 file_mods:
337 361 file_mods:
338 362 file_mods--verbose:
339 363 file_mods--verbose:
340 364 file_mods--verbose:
341 365 file_mods--verbose:
342 366 file_mods--verbose:
343 367 file_mods--verbose: c
344 368 file_mods--verbose:
345 369 file_mods--verbose:
346 370 file_mods--verbose:
347 371 file_mods--debug:
348 372 file_mods--debug:
349 373 file_mods--debug:
350 374 file_mods--debug:
351 375 file_mods--debug:
352 376 file_mods--debug: c
353 377 file_mods--debug:
354 378 file_mods--debug:
355 379 file_mods--debug:
356 380 file_copies: fourth (second)
357 381 file_copies:
358 382 file_copies:
359 383 file_copies:
360 384 file_copies:
361 385 file_copies:
362 386 file_copies:
363 387 file_copies:
364 388 file_copies:
365 389 file_copies--verbose: fourth (second)
366 390 file_copies--verbose:
367 391 file_copies--verbose:
368 392 file_copies--verbose:
369 393 file_copies--verbose:
370 394 file_copies--verbose:
371 395 file_copies--verbose:
372 396 file_copies--verbose:
373 397 file_copies--verbose:
374 398 file_copies--debug: fourth (second)
375 399 file_copies--debug:
376 400 file_copies--debug:
377 401 file_copies--debug:
378 402 file_copies--debug:
379 403 file_copies--debug:
380 404 file_copies--debug:
381 405 file_copies--debug:
382 406 file_copies--debug:
383 407 file_copies_switch:
384 408 file_copies_switch:
385 409 file_copies_switch:
386 410 file_copies_switch:
387 411 file_copies_switch:
388 412 file_copies_switch:
389 413 file_copies_switch:
390 414 file_copies_switch:
391 415 file_copies_switch:
392 416 file_copies_switch--verbose:
393 417 file_copies_switch--verbose:
394 418 file_copies_switch--verbose:
395 419 file_copies_switch--verbose:
396 420 file_copies_switch--verbose:
397 421 file_copies_switch--verbose:
398 422 file_copies_switch--verbose:
399 423 file_copies_switch--verbose:
400 424 file_copies_switch--verbose:
401 425 file_copies_switch--debug:
402 426 file_copies_switch--debug:
403 427 file_copies_switch--debug:
404 428 file_copies_switch--debug:
405 429 file_copies_switch--debug:
406 430 file_copies_switch--debug:
407 431 file_copies_switch--debug:
408 432 file_copies_switch--debug:
409 433 file_copies_switch--debug:
410 434 files: fourth second third
411 435 files: second
412 436 files:
413 437 files: d
414 438 files:
415 439 files: c
416 440 files: c
417 441 files: b
418 442 files: a
419 443 files--verbose: fourth second third
420 444 files--verbose: second
421 445 files--verbose:
422 446 files--verbose: d
423 447 files--verbose:
424 448 files--verbose: c
425 449 files--verbose: c
426 450 files--verbose: b
427 451 files--verbose: a
428 452 files--debug: fourth second third
429 453 files--debug: second
430 454 files--debug:
431 455 files--debug: d
432 456 files--debug:
433 457 files--debug: c
434 458 files--debug: c
435 459 files--debug: b
436 460 files--debug: a
437 461 manifest: 6:94961b75a2da
438 462 manifest: 5:f2dbc354b94e
439 463 manifest: 4:4dc3def4f9b4
440 464 manifest: 4:4dc3def4f9b4
441 465 manifest: 3:cb5a1327723b
442 466 manifest: 3:cb5a1327723b
443 467 manifest: 2:6e0e82995c35
444 468 manifest: 1:4e8d705b1e53
445 469 manifest: 0:a0c8bcbbb45c
446 470 manifest--verbose: 6:94961b75a2da
447 471 manifest--verbose: 5:f2dbc354b94e
448 472 manifest--verbose: 4:4dc3def4f9b4
449 473 manifest--verbose: 4:4dc3def4f9b4
450 474 manifest--verbose: 3:cb5a1327723b
451 475 manifest--verbose: 3:cb5a1327723b
452 476 manifest--verbose: 2:6e0e82995c35
453 477 manifest--verbose: 1:4e8d705b1e53
454 478 manifest--verbose: 0:a0c8bcbbb45c
455 479 manifest--debug: 6:94961b75a2da554b4df6fb599e5bfc7d48de0c64
456 480 manifest--debug: 5:f2dbc354b94e5ec0b4f10680ee0cee816101d0bf
457 481 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
458 482 manifest--debug: 4:4dc3def4f9b4c6e8de820f6ee74737f91e96a216
459 483 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
460 484 manifest--debug: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
461 485 manifest--debug: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
462 486 manifest--debug: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
463 487 manifest--debug: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
464 488 node: 95c24699272ef57d062b8bccc32c878bf841784a
465 489 node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
466 490 node: d41e714fe50d9e4a5f11b4d595d543481b5f980b
467 491 node: 13207e5a10d9fd28ec424934298e176197f2c67f
468 492 node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
469 493 node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
470 494 node: 97054abb4ab824450e9164180baf491ae0078465
471 495 node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
472 496 node: 1e4e1b8f71e05681d422154f5421e385fec3454f
473 497 node--verbose: 95c24699272ef57d062b8bccc32c878bf841784a
474 498 node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
475 499 node--verbose: d41e714fe50d9e4a5f11b4d595d543481b5f980b
476 500 node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
477 501 node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
478 502 node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
479 503 node--verbose: 97054abb4ab824450e9164180baf491ae0078465
480 504 node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
481 505 node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
482 506 node--debug: 95c24699272ef57d062b8bccc32c878bf841784a
483 507 node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
484 508 node--debug: d41e714fe50d9e4a5f11b4d595d543481b5f980b
485 509 node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
486 510 node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
487 511 node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
488 512 node--debug: 97054abb4ab824450e9164180baf491ae0078465
489 513 node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
490 514 node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
491 515 parents:
492 516 parents: -1:000000000000
493 517 parents: 5:13207e5a10d9 4:bbe44766e73d
494 518 parents: 3:10e46f2dcbf4
495 519 parents:
496 520 parents:
497 521 parents:
498 522 parents:
499 523 parents:
500 524 parents--verbose:
501 525 parents--verbose: -1:000000000000
502 526 parents--verbose: 5:13207e5a10d9 4:bbe44766e73d
503 527 parents--verbose: 3:10e46f2dcbf4
504 528 parents--verbose:
505 529 parents--verbose:
506 530 parents--verbose:
507 531 parents--verbose:
508 532 parents--verbose:
509 533 parents--debug: 7:29114dbae42b9f078cf2714dbe3a86bba8ec7453 -1:0000000000000000000000000000000000000000
510 534 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
511 535 parents--debug: 5:13207e5a10d9fd28ec424934298e176197f2c67f 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
512 536 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
513 537 parents--debug: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47 -1:0000000000000000000000000000000000000000
514 538 parents--debug: 2:97054abb4ab824450e9164180baf491ae0078465 -1:0000000000000000000000000000000000000000
515 539 parents--debug: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965 -1:0000000000000000000000000000000000000000
516 540 parents--debug: 0:1e4e1b8f71e05681d422154f5421e385fec3454f -1:0000000000000000000000000000000000000000
517 541 parents--debug: -1:0000000000000000000000000000000000000000 -1:0000000000000000000000000000000000000000
518 542 rev: 8
519 543 rev: 7
520 544 rev: 6
521 545 rev: 5
522 546 rev: 4
523 547 rev: 3
524 548 rev: 2
525 549 rev: 1
526 550 rev: 0
527 551 rev--verbose: 8
528 552 rev--verbose: 7
529 553 rev--verbose: 6
530 554 rev--verbose: 5
531 555 rev--verbose: 4
532 556 rev--verbose: 3
533 557 rev--verbose: 2
534 558 rev--verbose: 1
535 559 rev--verbose: 0
536 560 rev--debug: 8
537 561 rev--debug: 7
538 562 rev--debug: 6
539 563 rev--debug: 5
540 564 rev--debug: 4
541 565 rev--debug: 3
542 566 rev--debug: 2
543 567 rev--debug: 1
544 568 rev--debug: 0
545 569 tags: tip
546 570 tags:
547 571 tags:
548 572 tags:
549 573 tags:
550 574 tags:
551 575 tags:
552 576 tags:
553 577 tags:
554 578 tags--verbose: tip
555 579 tags--verbose:
556 580 tags--verbose:
557 581 tags--verbose:
558 582 tags--verbose:
559 583 tags--verbose:
560 584 tags--verbose:
561 585 tags--verbose:
562 586 tags--verbose:
563 587 tags--debug: tip
564 588 tags--debug:
565 589 tags--debug:
566 590 tags--debug:
567 591 tags--debug:
568 592 tags--debug:
569 593 tags--debug:
570 594 tags--debug:
571 595 tags--debug:
572 596 diffstat: 3: +2/-1
573 597 diffstat: 1: +1/-0
574 598 diffstat: 0: +0/-0
575 599 diffstat: 1: +1/-0
576 600 diffstat: 0: +0/-0
577 601 diffstat: 1: +1/-0
578 602 diffstat: 1: +4/-0
579 603 diffstat: 1: +2/-0
580 604 diffstat: 1: +1/-0
581 605 diffstat--verbose: 3: +2/-1
582 606 diffstat--verbose: 1: +1/-0
583 607 diffstat--verbose: 0: +0/-0
584 608 diffstat--verbose: 1: +1/-0
585 609 diffstat--verbose: 0: +0/-0
586 610 diffstat--verbose: 1: +1/-0
587 611 diffstat--verbose: 1: +4/-0
588 612 diffstat--verbose: 1: +2/-0
589 613 diffstat--verbose: 1: +1/-0
590 614 diffstat--debug: 3: +2/-1
591 615 diffstat--debug: 1: +1/-0
592 616 diffstat--debug: 0: +0/-0
593 617 diffstat--debug: 1: +1/-0
594 618 diffstat--debug: 0: +0/-0
595 619 diffstat--debug: 1: +1/-0
596 620 diffstat--debug: 1: +4/-0
597 621 diffstat--debug: 1: +2/-0
598 622 diffstat--debug: 1: +1/-0
599 623 extras: branch=default
600 624 extras: branch=default
601 625 extras: branch=default
602 626 extras: branch=default
603 627 extras: branch=foo
604 628 extras: branch=default
605 629 extras: branch=default
606 630 extras: branch=default
607 631 extras: branch=default
608 632 extras--verbose: branch=default
609 633 extras--verbose: branch=default
610 634 extras--verbose: branch=default
611 635 extras--verbose: branch=default
612 636 extras--verbose: branch=foo
613 637 extras--verbose: branch=default
614 638 extras--verbose: branch=default
615 639 extras--verbose: branch=default
616 640 extras--verbose: branch=default
617 641 extras--debug: branch=default
618 642 extras--debug: branch=default
619 643 extras--debug: branch=default
620 644 extras--debug: branch=default
621 645 extras--debug: branch=foo
622 646 extras--debug: branch=default
623 647 extras--debug: branch=default
624 648 extras--debug: branch=default
625 649 extras--debug: branch=default
626 650 p1rev: 7
627 651 p1rev: -1
628 652 p1rev: 5
629 653 p1rev: 3
630 654 p1rev: 3
631 655 p1rev: 2
632 656 p1rev: 1
633 657 p1rev: 0
634 658 p1rev: -1
635 659 p1rev--verbose: 7
636 660 p1rev--verbose: -1
637 661 p1rev--verbose: 5
638 662 p1rev--verbose: 3
639 663 p1rev--verbose: 3
640 664 p1rev--verbose: 2
641 665 p1rev--verbose: 1
642 666 p1rev--verbose: 0
643 667 p1rev--verbose: -1
644 668 p1rev--debug: 7
645 669 p1rev--debug: -1
646 670 p1rev--debug: 5
647 671 p1rev--debug: 3
648 672 p1rev--debug: 3
649 673 p1rev--debug: 2
650 674 p1rev--debug: 1
651 675 p1rev--debug: 0
652 676 p1rev--debug: -1
653 677 p2rev: -1
654 678 p2rev: -1
655 679 p2rev: 4
656 680 p2rev: -1
657 681 p2rev: -1
658 682 p2rev: -1
659 683 p2rev: -1
660 684 p2rev: -1
661 685 p2rev: -1
662 686 p2rev--verbose: -1
663 687 p2rev--verbose: -1
664 688 p2rev--verbose: 4
665 689 p2rev--verbose: -1
666 690 p2rev--verbose: -1
667 691 p2rev--verbose: -1
668 692 p2rev--verbose: -1
669 693 p2rev--verbose: -1
670 694 p2rev--verbose: -1
671 695 p2rev--debug: -1
672 696 p2rev--debug: -1
673 697 p2rev--debug: 4
674 698 p2rev--debug: -1
675 699 p2rev--debug: -1
676 700 p2rev--debug: -1
677 701 p2rev--debug: -1
678 702 p2rev--debug: -1
679 703 p2rev--debug: -1
680 704 p1node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
681 705 p1node: 0000000000000000000000000000000000000000
682 706 p1node: 13207e5a10d9fd28ec424934298e176197f2c67f
683 707 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
684 708 p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
685 709 p1node: 97054abb4ab824450e9164180baf491ae0078465
686 710 p1node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
687 711 p1node: 1e4e1b8f71e05681d422154f5421e385fec3454f
688 712 p1node: 0000000000000000000000000000000000000000
689 713 p1node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
690 714 p1node--verbose: 0000000000000000000000000000000000000000
691 715 p1node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
692 716 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
693 717 p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
694 718 p1node--verbose: 97054abb4ab824450e9164180baf491ae0078465
695 719 p1node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
696 720 p1node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
697 721 p1node--verbose: 0000000000000000000000000000000000000000
698 722 p1node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
699 723 p1node--debug: 0000000000000000000000000000000000000000
700 724 p1node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
701 725 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
702 726 p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
703 727 p1node--debug: 97054abb4ab824450e9164180baf491ae0078465
704 728 p1node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
705 729 p1node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
706 730 p1node--debug: 0000000000000000000000000000000000000000
707 731 p2node: 0000000000000000000000000000000000000000
708 732 p2node: 0000000000000000000000000000000000000000
709 733 p2node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
710 734 p2node: 0000000000000000000000000000000000000000
711 735 p2node: 0000000000000000000000000000000000000000
712 736 p2node: 0000000000000000000000000000000000000000
713 737 p2node: 0000000000000000000000000000000000000000
714 738 p2node: 0000000000000000000000000000000000000000
715 739 p2node: 0000000000000000000000000000000000000000
716 740 p2node--verbose: 0000000000000000000000000000000000000000
717 741 p2node--verbose: 0000000000000000000000000000000000000000
718 742 p2node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
719 743 p2node--verbose: 0000000000000000000000000000000000000000
720 744 p2node--verbose: 0000000000000000000000000000000000000000
721 745 p2node--verbose: 0000000000000000000000000000000000000000
722 746 p2node--verbose: 0000000000000000000000000000000000000000
723 747 p2node--verbose: 0000000000000000000000000000000000000000
724 748 p2node--verbose: 0000000000000000000000000000000000000000
725 749 p2node--debug: 0000000000000000000000000000000000000000
726 750 p2node--debug: 0000000000000000000000000000000000000000
727 751 p2node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
728 752 p2node--debug: 0000000000000000000000000000000000000000
729 753 p2node--debug: 0000000000000000000000000000000000000000
730 754 p2node--debug: 0000000000000000000000000000000000000000
731 755 p2node--debug: 0000000000000000000000000000000000000000
732 756 p2node--debug: 0000000000000000000000000000000000000000
733 757 p2node--debug: 0000000000000000000000000000000000000000
734 758 user: test
735 759 user: User Name <user@hostname>
736 760 user: person
737 761 user: person
738 762 user: person
739 763 user: person
740 764 user: other@place
741 765 user: A. N. Other <other@place>
742 766 user: User Name <user@hostname>
743 767 user--verbose: test
744 768 user--verbose: User Name <user@hostname>
745 769 user--verbose: person
746 770 user--verbose: person
747 771 user--verbose: person
748 772 user--verbose: person
749 773 user--verbose: other@place
750 774 user--verbose: A. N. Other <other@place>
751 775 user--verbose: User Name <user@hostname>
752 776 user--debug: test
753 777 user--debug: User Name <user@hostname>
754 778 user--debug: person
755 779 user--debug: person
756 780 user--debug: person
757 781 user--debug: person
758 782 user--debug: other@place
759 783 user--debug: A. N. Other <other@place>
760 784 user--debug: User Name <user@hostname>
761 785
762 786 Add a dummy commit to make up for the instability of the above:
763 787
764 788 $ echo a > a
765 789 $ hg add a
766 790 $ hg ci -m future
767 791
768 792 Add a commit that does all possible modifications at once
769 793
770 794 $ echo modify >> third
771 795 $ touch b
772 796 $ hg add b
773 797 $ hg mv fourth fifth
774 798 $ hg rm a
775 799 $ hg ci -m "Modify, add, remove, rename"
776 800
777 801 Test files list:
778 802
779 803 $ hg log -l1 -T '{join(file_mods, " ")}\n'
780 804 third
781 805 $ hg log -l1 -T '{file_mods % "{file}\n"}'
782 806 third
783 807 $ hg log -l1 -T '{file_mods % "{path}\n"}'
784 808 third
785 809
786 810 $ hg log -l1 -T '{join(files, " ")}\n'
787 811 a b fifth fourth third
788 812 $ hg log -l1 -T '{files % "{file}\n"}'
789 813 a
790 814 b
791 815 fifth
792 816 fourth
793 817 third
794 818 $ hg log -l1 -T '{files % "{path}\n"}'
795 819 a
796 820 b
797 821 fifth
798 822 fourth
799 823 third
800 824
801 825 Test files lists on merge commit:
802 826
803 827 $ hg co '.^' -q
804 828 $ touch c
805 829 $ hg add c
806 830 $ hg ci -qm 'add file'
807 831 $ hg merge 10 -q
808 832 $ hg ci -m 'merge'
809 833 $ hg log -l1 -T '{files}\n'
810 834
811 835 $ hg log -l1 -T '{file_mods}\n'
812 836
813 837 $ hg log -l1 -T '{file_adds}\n'
814 838
815 839 $ hg log -l1 -T '{file_dels}\n'
816 840
817 841
818 842 Test file copies dict:
819 843
820 844 $ hg log -r8 -T '{join(file_copies, " ")}\n'
821 845 fourth (second)
822 846 $ hg log -r8 -T '{file_copies % "{name} <- {source}\n"}'
823 847 fourth <- second
824 848 $ hg log -r8 -T '{file_copies % "{path} <- {source}\n"}'
825 849 fourth <- second
826 850
827 851 $ hg log -r8 -T '{join(file_copies_switch, " ")}\n'
828 852
829 853 $ hg log -r8 -C -T '{join(file_copies_switch, " ")}\n'
830 854 fourth (second)
831 855 $ hg log -r8 -C -T '{file_copies_switch % "{name} <- {source}\n"}'
832 856 fourth <- second
833 857 $ hg log -r8 -C -T '{file_copies_switch % "{path} <- {source}\n"}'
834 858 fourth <- second
835 859
836 860 Test file attributes:
837 861
838 862 $ hg log -r10 -T '{files % "{status} {pad(size, 3, left=True)} {path}\n"}'
839 863 R a
840 864 A 0 b
841 865 A 7 fifth
842 866 R fourth
843 867 M 13 third
844 868
845 869 Test file status including clean ones:
846 870
847 871 $ hg log -r9 -T '{files("**") % "{status} {path}\n"}'
848 872 A a
849 873 C fourth
850 874 C third
851 875
852 876 Test index keyword:
853 877
854 878 $ hg log -r 10:9 -T '{index + 10}{files % " {index}:{file}"}\n'
855 879 10 0:a 1:b 2:fifth 3:fourth 4:third
856 880 11 0:a
857 881
858 882 $ hg branches -T '{index} {branch}\n'
859 883 0 default
860 884 1 foo
861 885
862 886 p1/p2 keywords:
863 887
864 888 $ hg log -r4:7 -GT '{rev} p1:{p1} p2:{p2} p1.rev:{p1.rev} p2.node:{p2.node}\n'
865 889 o 7 p1:-1:000000000000 p2:-1:000000000000 p1.rev:-1 p2.node:0000000000000000000000000000000000000000
866 890
867 891 o 6 p1:5:13207e5a10d9 p2:4:bbe44766e73d p1.rev:5 p2.node:bbe44766e73d5f11ed2177f1838de10c53ef3e74
868 892 |\
869 893 | o 5 p1:3:10e46f2dcbf4 p2:-1:000000000000 p1.rev:3 p2.node:0000000000000000000000000000000000000000
870 894 | |
871 895 | ~
872 896 o 4 p1:3:10e46f2dcbf4 p2:-1:000000000000 p1.rev:3 p2.node:0000000000000000000000000000000000000000
873 897 |
874 898 ~
875 899
876 900 TODO: no idea what should be displayed as a JSON representation
877 901 $ hg log -r6 -T 'p1:{p1|json}\np2:{p2|json}\n'
878 902 p1:{}
879 903 p2:{}
880 904
881 905 ui verbosity:
882 906
883 907 $ hg log -l1 -T '{verbosity}\n'
884 908
885 909 $ hg log -l1 -T '{verbosity}\n' --debug
886 910 debug
887 911 $ hg log -l1 -T '{verbosity}\n' --quiet
888 912 quiet
889 913 $ hg log -l1 -T '{verbosity}\n' --verbose
890 914 verbose
891 915
892 916 $ cd ..
893 917
894 918 latesttag:
895 919
896 920 $ hg init latesttag
897 921 $ cd latesttag
898 922
899 923 $ echo a > file
900 924 $ hg ci -Am a -d '0 0'
901 925 adding file
902 926
903 927 $ echo b >> file
904 928 $ hg ci -m b -d '1 0'
905 929
906 930 $ echo c >> head1
907 931 $ hg ci -Am h1c -d '2 0'
908 932 adding head1
909 933
910 934 $ hg update -q 1
911 935 $ echo d >> head2
912 936 $ hg ci -Am h2d -d '3 0'
913 937 adding head2
914 938 created new head
915 939
916 940 $ echo e >> head2
917 941 $ hg ci -m h2e -d '4 0'
918 942
919 943 $ hg merge -q
920 944 $ hg ci -m merge -d '5 -3600'
921 945
922 946 No tag set:
923 947
924 948 $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
925 949 @ 5: null+5
926 950 |\
927 951 | o 4: null+4
928 952 | |
929 953 | o 3: null+3
930 954 | |
931 955 o | 2: null+3
932 956 |/
933 957 o 1: null+2
934 958 |
935 959 o 0: null+1
936 960
937 961
938 962 One common tag: longest path wins for {latesttagdistance}:
939 963
940 964 $ hg tag -r 1 -m t1 -d '6 0' t1
941 965 $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
942 966 @ 6: t1+4
943 967 |
944 968 o 5: t1+3
945 969 |\
946 970 | o 4: t1+2
947 971 | |
948 972 | o 3: t1+1
949 973 | |
950 974 o | 2: t1+1
951 975 |/
952 976 o 1: t1+0
953 977 |
954 978 o 0: null+1
955 979
956 980
957 981 One ancestor tag: closest wins:
958 982
959 983 $ hg tag -r 2 -m t2 -d '7 0' t2
960 984 $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
961 985 @ 7: t2+3
962 986 |
963 987 o 6: t2+2
964 988 |
965 989 o 5: t2+1
966 990 |\
967 991 | o 4: t1+2
968 992 | |
969 993 | o 3: t1+1
970 994 | |
971 995 o | 2: t2+0
972 996 |/
973 997 o 1: t1+0
974 998 |
975 999 o 0: null+1
976 1000
977 1001
978 1002 Two branch tags: more recent wins if same number of changes:
979 1003
980 1004 $ hg tag -r 3 -m t3 -d '8 0' t3
981 1005 $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
982 1006 @ 8: t3+5
983 1007 |
984 1008 o 7: t3+4
985 1009 |
986 1010 o 6: t3+3
987 1011 |
988 1012 o 5: t3+2
989 1013 |\
990 1014 | o 4: t3+1
991 1015 | |
992 1016 | o 3: t3+0
993 1017 | |
994 1018 o | 2: t2+0
995 1019 |/
996 1020 o 1: t1+0
997 1021 |
998 1022 o 0: null+1
999 1023
1000 1024
1001 1025 Two branch tags: fewest changes wins:
1002 1026
1003 1027 $ hg tag -r 4 -m t4 -d '4 0' t4 # older than t2, but should not matter
1004 1028 $ hg log -G --template "{rev}: {latesttag % '{tag}+{distance},{changes} '}\n"
1005 1029 @ 9: t4+5,6
1006 1030 |
1007 1031 o 8: t4+4,5
1008 1032 |
1009 1033 o 7: t4+3,4
1010 1034 |
1011 1035 o 6: t4+2,3
1012 1036 |
1013 1037 o 5: t4+1,2
1014 1038 |\
1015 1039 | o 4: t4+0,0
1016 1040 | |
1017 1041 | o 3: t3+0,0
1018 1042 | |
1019 1043 o | 2: t2+0,0
1020 1044 |/
1021 1045 o 1: t1+0,0
1022 1046 |
1023 1047 o 0: null+1,1
1024 1048
1025 1049
1026 1050 Merged tag overrides:
1027 1051
1028 1052 $ hg tag -r 5 -m t5 -d '9 0' t5
1029 1053 $ hg tag -r 3 -m at3 -d '10 0' at3
1030 1054 $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
1031 1055 @ 11: t5+6
1032 1056 |
1033 1057 o 10: t5+5
1034 1058 |
1035 1059 o 9: t5+4
1036 1060 |
1037 1061 o 8: t5+3
1038 1062 |
1039 1063 o 7: t5+2
1040 1064 |
1041 1065 o 6: t5+1
1042 1066 |
1043 1067 o 5: t5+0
1044 1068 |\
1045 1069 | o 4: t4+0
1046 1070 | |
1047 1071 | o 3: at3:t3+0
1048 1072 | |
1049 1073 o | 2: t2+0
1050 1074 |/
1051 1075 o 1: t1+0
1052 1076 |
1053 1077 o 0: null+1
1054 1078
1055 1079
1056 1080 $ hg log -G --template "{rev}: {latesttag % '{tag}+{distance},{changes} '}\n"
1057 1081 @ 11: t5+6,6
1058 1082 |
1059 1083 o 10: t5+5,5
1060 1084 |
1061 1085 o 9: t5+4,4
1062 1086 |
1063 1087 o 8: t5+3,3
1064 1088 |
1065 1089 o 7: t5+2,2
1066 1090 |
1067 1091 o 6: t5+1,1
1068 1092 |
1069 1093 o 5: t5+0,0
1070 1094 |\
1071 1095 | o 4: t4+0,0
1072 1096 | |
1073 1097 | o 3: at3+0,0 t3+0,0
1074 1098 | |
1075 1099 o | 2: t2+0,0
1076 1100 |/
1077 1101 o 1: t1+0,0
1078 1102 |
1079 1103 o 0: null+1,1
1080 1104
1081 1105
1082 1106 Tags of working-directory parents (issue6055):
1083 1107
1084 1108 $ hg update -q 3
1085 1109 $ echo a > head3
1086 1110 $ hg ci -qAm h3a
1087 1111 $ hg merge -q 2
1088 1112 $ hg log -Gr'::wdir()' -T "{rev}: {latesttag % '{tag}+{distance},{changes} '}\n"
1089 1113 o 2147483647: at3+2,3 t3+2,3
1090 1114 |\
1091 1115 | @ 12: at3+1,1 t3+1,1
1092 1116 | |
1093 1117 | o 3: at3+0,0 t3+0,0
1094 1118 | |
1095 1119 @ | 2: t2+0,0
1096 1120 |/
1097 1121 o 1: t1+0,0
1098 1122 |
1099 1123 o 0: null+1,1
1100 1124
1101 1125
1102 1126 $ hg ci -m merge
1103 1127 $ hg log -Gr'::.' -T "{rev}: {latesttag % '{tag}+{distance},{changes} '}\n"
1104 1128 @ 13: at3+2,3 t3+2,3
1105 1129 |\
1106 1130 | o 12: at3+1,1 t3+1,1
1107 1131 | |
1108 1132 | o 3: at3+0,0 t3+0,0
1109 1133 | |
1110 1134 o | 2: t2+0,0
1111 1135 |/
1112 1136 o 1: t1+0,0
1113 1137 |
1114 1138 o 0: null+1,1
1115 1139
1116 1140
1117 1141 $ cd ..
1118 1142
1119 1143 Set up repository containing template fragments in commit metadata:
1120 1144
1121 1145 $ hg init r
1122 1146 $ cd r
1123 1147 $ echo a > a
1124 1148 $ hg ci -Am '{rev}'
1125 1149 adding a
1126 1150
1127 1151 $ hg branch -q 'text.{rev}'
1128 1152 $ echo aa >> aa
1129 1153 $ hg ci -u '{node|short}' -m 'desc to be wrapped desc to be wrapped'
1130 1154
1131 1155 Test termwidth:
1132 1156
1133 1157 $ COLUMNS=25 hg log -l1 --template '{fill(desc, termwidth, "{node|short}:", "termwidth.{rev}:")}'
1134 1158 bcc7ff960b8e:desc to be
1135 1159 termwidth.1:wrapped desc
1136 1160 termwidth.1:to be wrapped (no-eol)
1137 1161
1138 1162 Just one more commit:
1139 1163
1140 1164 $ echo b > b
1141 1165 $ hg ci -qAm b
1142 1166
1143 1167 Test 'originalnode'
1144 1168
1145 1169 $ hg log -r 1 -T '{revset("null") % "{node|short} {originalnode|short}"}\n'
1146 1170 000000000000 bcc7ff960b8e
1147 1171 $ hg log -r 0 -T '{manifest % "{node} {originalnode}"}\n'
1148 1172 a0c8bcbbb45c63b90b70ad007bf38961f64f2af0 f7769ec2ab975ad19684098ad1ffd9b81ecc71a1
1149 1173
1150 1174 Test active bookmark templating
1151 1175
1152 1176 $ hg book foo
1153 1177 $ hg book bar
1154 1178 $ hg log --template "{rev} {bookmarks % '{bookmark}{ifeq(bookmark, active, \"*\")} '}\n"
1155 1179 2 bar* foo
1156 1180 1
1157 1181 0
1158 1182 $ hg log --template "{rev} {activebookmark}\n"
1159 1183 2 bar
1160 1184 1
1161 1185 0
1162 1186 $ hg bookmarks --inactive bar
1163 1187 $ hg log --template "{rev} {activebookmark}\n"
1164 1188 2
1165 1189 1
1166 1190 0
1167 1191 $ hg book -r1 baz
1168 1192 $ hg log --template "{rev} {join(bookmarks, ' ')}\n"
1169 1193 2 bar foo
1170 1194 1 baz
1171 1195 0
1172 1196 $ hg log --template "{rev} {ifcontains('foo', bookmarks, 't', 'f')}\n"
1173 1197 2 t
1174 1198 1 f
1175 1199 0 f
1176 1200
1177 1201 Test namespaces dict
1178 1202
1179 1203 $ hg --config extensions.revnamesext=$TESTDIR/revnamesext.py log -T '{rev}\n{namespaces % " {namespace} color={colorname} builtin={builtin}\n {join(names, ",")}\n"}\n'
1180 1204 2
1181 1205 bookmarks color=bookmark builtin=True
1182 1206 bar,foo
1183 1207 tags color=tag builtin=True
1184 1208 tip
1185 1209 branches color=branch builtin=True
1186 1210 text.{rev}
1187 1211 revnames color=revname builtin=False
1188 1212 r2
1189 1213
1190 1214 1
1191 1215 bookmarks color=bookmark builtin=True
1192 1216 baz
1193 1217 tags color=tag builtin=True
1194 1218
1195 1219 branches color=branch builtin=True
1196 1220 text.{rev}
1197 1221 revnames color=revname builtin=False
1198 1222 r1
1199 1223
1200 1224 0
1201 1225 bookmarks color=bookmark builtin=True
1202 1226
1203 1227 tags color=tag builtin=True
1204 1228
1205 1229 branches color=branch builtin=True
1206 1230 default
1207 1231 revnames color=revname builtin=False
1208 1232 r0
1209 1233
1210 1234 $ hg log -r2 -T '{namespaces % "{namespace}: {names}\n"}'
1211 1235 bookmarks: bar foo
1212 1236 tags: tip
1213 1237 branches: text.{rev}
1214 1238 $ hg log -r2 -T '{namespaces % "{namespace}:\n{names % " {name}\n"}"}'
1215 1239 bookmarks:
1216 1240 bar
1217 1241 foo
1218 1242 tags:
1219 1243 tip
1220 1244 branches:
1221 1245 text.{rev}
1222 1246 $ hg log -r2 -T '{get(namespaces, "bookmarks") % "{name}\n"}'
1223 1247 bar
1224 1248 foo
1225 1249 $ hg log -r2 -T '{namespaces.bookmarks % "{bookmark}\n"}'
1226 1250 bar
1227 1251 foo
1228 1252
1229 1253 $ cd ..
1230 1254
1231 1255 Test 'graphwidth' in 'hg log' on various topologies. The key here is that the
1232 1256 printed graphwidths 3, 5, 7, etc. should all line up in their respective
1233 1257 columns. We don't care about other aspects of the graph rendering here.
1234 1258
1235 1259 $ hg init graphwidth
1236 1260 $ cd graphwidth
1237 1261
1238 1262 $ wrappabletext="a a a a a a a a a a a a"
1239 1263
1240 1264 $ printf "first\n" > file
1241 1265 $ hg add file
1242 1266 $ hg commit -m "$wrappabletext"
1243 1267
1244 1268 $ printf "first\nsecond\n" > file
1245 1269 $ hg commit -m "$wrappabletext"
1246 1270
1247 1271 $ hg checkout 0
1248 1272 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1249 1273 $ printf "third\nfirst\n" > file
1250 1274 $ hg commit -m "$wrappabletext"
1251 1275 created new head
1252 1276
1253 1277 $ hg merge
1254 1278 merging file
1255 1279 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1256 1280 (branch merge, don't forget to commit)
1257 1281
1258 1282 $ hg log --graph -T "{graphwidth}"
1259 1283 @ 3
1260 1284 |
1261 1285 | @ 5
1262 1286 |/
1263 1287 o 3
1264 1288
1265 1289 $ hg commit -m "$wrappabletext"
1266 1290
1267 1291 $ hg log --graph -T "{graphwidth}"
1268 1292 @ 5
1269 1293 |\
1270 1294 | o 5
1271 1295 | |
1272 1296 o | 5
1273 1297 |/
1274 1298 o 3
1275 1299
1276 1300
1277 1301 $ hg checkout 0
1278 1302 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1279 1303 $ printf "third\nfirst\nsecond\n" > file
1280 1304 $ hg commit -m "$wrappabletext"
1281 1305 created new head
1282 1306
1283 1307 $ hg log --graph -T "{graphwidth}"
1284 1308 @ 3
1285 1309 |
1286 1310 | o 7
1287 1311 | |\
1288 1312 +---o 7
1289 1313 | |
1290 1314 | o 5
1291 1315 |/
1292 1316 o 3
1293 1317
1294 1318
1295 1319 $ hg log --graph -T "{graphwidth}" -r 3
1296 1320 o 5
1297 1321 |\
1298 1322 ~ ~
1299 1323
1300 1324 $ hg log --graph -T "{graphwidth}" -r 1
1301 1325 o 3
1302 1326 |
1303 1327 ~
1304 1328
1305 1329 $ hg merge
1306 1330 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1307 1331 (branch merge, don't forget to commit)
1308 1332 $ hg commit -m "$wrappabletext"
1309 1333
1310 1334 $ printf "seventh\n" >> file
1311 1335 $ hg commit -m "$wrappabletext"
1312 1336
1313 1337 $ hg log --graph -T "{graphwidth}"
1314 1338 @ 3
1315 1339 |
1316 1340 o 5
1317 1341 |\
1318 1342 | o 5
1319 1343 | |
1320 1344 o | 7
1321 1345 |\ \
1322 1346 | o | 7
1323 1347 | |/
1324 1348 o / 5
1325 1349 |/
1326 1350 o 3
1327 1351
1328 1352
1329 1353 The point of graphwidth is to allow wrapping that accounts for the space taken
1330 1354 by the graph.
1331 1355
1332 1356 $ COLUMNS=10 hg log --graph -T "{fill(desc, termwidth - graphwidth)}"
1333 1357 @ a a a a
1334 1358 | a a a a
1335 1359 | a a a a
1336 1360 o a a a
1337 1361 |\ a a a
1338 1362 | | a a a
1339 1363 | | a a a
1340 1364 | o a a a
1341 1365 | | a a a
1342 1366 | | a a a
1343 1367 | | a a a
1344 1368 o | a a
1345 1369 |\ \ a a
1346 1370 | | | a a
1347 1371 | | | a a
1348 1372 | | | a a
1349 1373 | | | a a
1350 1374 | o | a a
1351 1375 | |/ a a
1352 1376 | | a a
1353 1377 | | a a
1354 1378 | | a a
1355 1379 | | a a
1356 1380 o | a a a
1357 1381 |/ a a a
1358 1382 | a a a
1359 1383 | a a a
1360 1384 o a a a a
1361 1385 a a a a
1362 1386 a a a a
1363 1387
1364 1388 Something tricky happens when there are elided nodes; the next drawn row of
1365 1389 edges can be more than one column wider, but the graph width only increases by
1366 1390 one column. The remaining columns are added in between the nodes.
1367 1391
1368 1392 $ hg log --graph -T "{graphwidth}" -r "0|2|4|5"
1369 1393 o 5
1370 1394 |\
1371 1395 | \
1372 1396 | :\
1373 1397 o : : 7
1374 1398 :/ /
1375 1399 : o 5
1376 1400 :/
1377 1401 o 3
1378 1402
1379 1403
1380 1404 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now