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