##// END OF EJS Templates
templatekw: reference predecessor node id as {node} in map operation...
Yuya Nishihara -
r32909:89610c58 default
parent child Browse files
Show More
@@ -1,687 +1,687 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 short,
15 15 )
16 16
17 17 from . import (
18 18 encoding,
19 19 error,
20 20 hbisect,
21 21 obsutil,
22 22 patch,
23 23 registrar,
24 24 scmutil,
25 25 util,
26 26 )
27 27
28 28 class _hybrid(object):
29 29 """Wrapper for list or dict to support legacy template
30 30
31 31 This class allows us to handle both:
32 32 - "{files}" (legacy command-line-specific list hack) and
33 33 - "{files % '{file}\n'}" (hgweb-style with inlining and function support)
34 34 and to access raw values:
35 35 - "{ifcontains(file, files, ...)}", "{ifcontains(key, extras, ...)}"
36 36 - "{get(extras, key)}"
37 37 - "{files|json}"
38 38 """
39 39
40 40 def __init__(self, gen, values, makemap, joinfmt):
41 41 if gen is not None:
42 42 self.gen = gen
43 43 self._values = values
44 44 self._makemap = makemap
45 45 self.joinfmt = joinfmt
46 46 @util.propertycache
47 47 def gen(self):
48 48 return self._defaultgen()
49 49 def _defaultgen(self):
50 50 """Generator to stringify this as {join(self, ' ')}"""
51 51 for i, d in enumerate(self.itermaps()):
52 52 if i > 0:
53 53 yield ' '
54 54 yield self.joinfmt(d)
55 55 def itermaps(self):
56 56 makemap = self._makemap
57 57 for x in self._values:
58 58 yield makemap(x)
59 59 def __contains__(self, x):
60 60 return x in self._values
61 61 def __len__(self):
62 62 return len(self._values)
63 63 def __iter__(self):
64 64 return iter(self._values)
65 65 def __getattr__(self, name):
66 66 if name not in ('get', 'items', 'iteritems', 'iterkeys', 'itervalues',
67 67 'keys', 'values'):
68 68 raise AttributeError(name)
69 69 return getattr(self._values, name)
70 70
71 71 def hybriddict(data, key='key', value='value', fmt='%s=%s', gen=None):
72 72 """Wrap data to support both dict-like and string-like operations"""
73 73 return _hybrid(gen, data, lambda k: {key: k, value: data[k]},
74 74 lambda d: fmt % (d[key], d[value]))
75 75
76 76 def hybridlist(data, name, fmt='%s', gen=None):
77 77 """Wrap data to support both list-like and string-like operations"""
78 78 return _hybrid(gen, data, lambda x: {name: x}, lambda d: fmt % d[name])
79 79
80 80 def unwraphybrid(thing):
81 81 """Return an object which can be stringified possibly by using a legacy
82 82 template"""
83 83 if not util.safehasattr(thing, 'gen'):
84 84 return thing
85 85 return thing.gen
86 86
87 87 def showdict(name, data, mapping, plural=None, key='key', value='value',
88 88 fmt='%s=%s', separator=' '):
89 89 c = [{key: k, value: v} for k, v in data.iteritems()]
90 90 f = _showlist(name, c, mapping, plural, separator)
91 91 return hybriddict(data, key=key, value=value, fmt=fmt, gen=f)
92 92
93 93 def showlist(name, values, mapping, plural=None, element=None, separator=' '):
94 94 if not element:
95 95 element = name
96 96 f = _showlist(name, values, mapping, plural, separator)
97 97 return hybridlist(values, name=element, gen=f)
98 98
99 99 def _showlist(name, values, mapping, plural=None, separator=' '):
100 100 '''expand set of values.
101 101 name is name of key in template map.
102 102 values is list of strings or dicts.
103 103 plural is plural of name, if not simply name + 's'.
104 104 separator is used to join values as a string
105 105
106 106 expansion works like this, given name 'foo'.
107 107
108 108 if values is empty, expand 'no_foos'.
109 109
110 110 if 'foo' not in template map, return values as a string,
111 111 joined by 'separator'.
112 112
113 113 expand 'start_foos'.
114 114
115 115 for each value, expand 'foo'. if 'last_foo' in template
116 116 map, expand it instead of 'foo' for last key.
117 117
118 118 expand 'end_foos'.
119 119 '''
120 120 templ = mapping['templ']
121 121 if not plural:
122 122 plural = name + 's'
123 123 if not values:
124 124 noname = 'no_' + plural
125 125 if noname in templ:
126 126 yield templ(noname, **mapping)
127 127 return
128 128 if name not in templ:
129 129 if isinstance(values[0], str):
130 130 yield separator.join(values)
131 131 else:
132 132 for v in values:
133 133 yield dict(v, **mapping)
134 134 return
135 135 startname = 'start_' + plural
136 136 if startname in templ:
137 137 yield templ(startname, **mapping)
138 138 vmapping = mapping.copy()
139 139 def one(v, tag=name):
140 140 try:
141 141 vmapping.update(v)
142 142 except (AttributeError, ValueError):
143 143 try:
144 144 for a, b in v:
145 145 vmapping[a] = b
146 146 except ValueError:
147 147 vmapping[name] = v
148 148 return templ(tag, **vmapping)
149 149 lastname = 'last_' + name
150 150 if lastname in templ:
151 151 last = values.pop()
152 152 else:
153 153 last = None
154 154 for v in values:
155 155 yield one(v)
156 156 if last is not None:
157 157 yield one(last, tag=lastname)
158 158 endname = 'end_' + plural
159 159 if endname in templ:
160 160 yield templ(endname, **mapping)
161 161
162 162 def _formatrevnode(ctx):
163 163 """Format changeset as '{rev}:{node|formatnode}', which is the default
164 164 template provided by cmdutil.changeset_templater"""
165 165 repo = ctx.repo()
166 166 if repo.ui.debugflag:
167 167 hexfunc = hex
168 168 else:
169 169 hexfunc = short
170 170 return '%d:%s' % (scmutil.intrev(ctx), hexfunc(scmutil.binnode(ctx)))
171 171
172 172 def getfiles(repo, ctx, revcache):
173 173 if 'files' not in revcache:
174 174 revcache['files'] = repo.status(ctx.p1(), ctx)[:3]
175 175 return revcache['files']
176 176
177 177 def getlatesttags(repo, ctx, cache, pattern=None):
178 178 '''return date, distance and name for the latest tag of rev'''
179 179
180 180 cachename = 'latesttags'
181 181 if pattern is not None:
182 182 cachename += '-' + pattern
183 183 match = util.stringmatcher(pattern)[2]
184 184 else:
185 185 match = util.always
186 186
187 187 if cachename not in cache:
188 188 # Cache mapping from rev to a tuple with tag date, tag
189 189 # distance and tag name
190 190 cache[cachename] = {-1: (0, 0, ['null'])}
191 191 latesttags = cache[cachename]
192 192
193 193 rev = ctx.rev()
194 194 todo = [rev]
195 195 while todo:
196 196 rev = todo.pop()
197 197 if rev in latesttags:
198 198 continue
199 199 ctx = repo[rev]
200 200 tags = [t for t in ctx.tags()
201 201 if (repo.tagtype(t) and repo.tagtype(t) != 'local'
202 202 and match(t))]
203 203 if tags:
204 204 latesttags[rev] = ctx.date()[0], 0, [t for t in sorted(tags)]
205 205 continue
206 206 try:
207 207 # The tuples are laid out so the right one can be found by
208 208 # comparison.
209 209 pdate, pdist, ptag = max(
210 210 latesttags[p.rev()] for p in ctx.parents())
211 211 except KeyError:
212 212 # Cache miss - recurse
213 213 todo.append(rev)
214 214 todo.extend(p.rev() for p in ctx.parents())
215 215 continue
216 216 latesttags[rev] = pdate, pdist + 1, ptag
217 217 return latesttags[rev]
218 218
219 219 def getrenamedfn(repo, endrev=None):
220 220 rcache = {}
221 221 if endrev is None:
222 222 endrev = len(repo)
223 223
224 224 def getrenamed(fn, rev):
225 225 '''looks up all renames for a file (up to endrev) the first
226 226 time the file is given. It indexes on the changerev and only
227 227 parses the manifest if linkrev != changerev.
228 228 Returns rename info for fn at changerev rev.'''
229 229 if fn not in rcache:
230 230 rcache[fn] = {}
231 231 fl = repo.file(fn)
232 232 for i in fl:
233 233 lr = fl.linkrev(i)
234 234 renamed = fl.renamed(fl.node(i))
235 235 rcache[fn][lr] = renamed
236 236 if lr >= endrev:
237 237 break
238 238 if rev in rcache[fn]:
239 239 return rcache[fn][rev]
240 240
241 241 # If linkrev != rev (i.e. rev not found in rcache) fallback to
242 242 # filectx logic.
243 243 try:
244 244 return repo[rev][fn].renamed()
245 245 except error.LookupError:
246 246 return None
247 247
248 248 return getrenamed
249 249
250 250 # default templates internally used for rendering of lists
251 251 defaulttempl = {
252 252 'parent': '{rev}:{node|formatnode} ',
253 253 'manifest': '{rev}:{node|formatnode}',
254 254 'file_copy': '{name} ({source})',
255 255 'envvar': '{key}={value}',
256 256 'extra': '{key}={value|stringescape}'
257 257 }
258 258 # filecopy is preserved for compatibility reasons
259 259 defaulttempl['filecopy'] = defaulttempl['file_copy']
260 260
261 261 # keywords are callables like:
262 262 # fn(repo, ctx, templ, cache, revcache, **args)
263 263 # with:
264 264 # repo - current repository instance
265 265 # ctx - the changectx being displayed
266 266 # templ - the templater instance
267 267 # cache - a cache dictionary for the whole templater run
268 268 # revcache - a cache dictionary for the current revision
269 269 keywords = {}
270 270
271 271 templatekeyword = registrar.templatekeyword(keywords)
272 272
273 273 @templatekeyword('author')
274 274 def showauthor(repo, ctx, templ, **args):
275 275 """String. The unmodified author of the changeset."""
276 276 return ctx.user()
277 277
278 278 @templatekeyword('bisect')
279 279 def showbisect(repo, ctx, templ, **args):
280 280 """String. The changeset bisection status."""
281 281 return hbisect.label(repo, ctx.node())
282 282
283 283 @templatekeyword('branch')
284 284 def showbranch(**args):
285 285 """String. The name of the branch on which the changeset was
286 286 committed.
287 287 """
288 288 return args['ctx'].branch()
289 289
290 290 @templatekeyword('branches')
291 291 def showbranches(**args):
292 292 """List of strings. The name of the branch on which the
293 293 changeset was committed. Will be empty if the branch name was
294 294 default. (DEPRECATED)
295 295 """
296 296 branch = args['ctx'].branch()
297 297 if branch != 'default':
298 298 return showlist('branch', [branch], args, plural='branches')
299 299 return showlist('branch', [], args, plural='branches')
300 300
301 301 @templatekeyword('bookmarks')
302 302 def showbookmarks(**args):
303 303 """List of strings. Any bookmarks associated with the
304 304 changeset. Also sets 'active', the name of the active bookmark.
305 305 """
306 306 repo = args['ctx']._repo
307 307 bookmarks = args['ctx'].bookmarks()
308 308 active = repo._activebookmark
309 309 makemap = lambda v: {'bookmark': v, 'active': active, 'current': active}
310 310 f = _showlist('bookmark', bookmarks, args)
311 311 return _hybrid(f, bookmarks, makemap, lambda x: x['bookmark'])
312 312
313 313 @templatekeyword('children')
314 314 def showchildren(**args):
315 315 """List of strings. The children of the changeset."""
316 316 ctx = args['ctx']
317 317 childrevs = ['%d:%s' % (cctx, cctx) for cctx in ctx.children()]
318 318 return showlist('children', childrevs, args, element='child')
319 319
320 320 # Deprecated, but kept alive for help generation a purpose.
321 321 @templatekeyword('currentbookmark')
322 322 def showcurrentbookmark(**args):
323 323 """String. The active bookmark, if it is
324 324 associated with the changeset (DEPRECATED)"""
325 325 return showactivebookmark(**args)
326 326
327 327 @templatekeyword('activebookmark')
328 328 def showactivebookmark(**args):
329 329 """String. The active bookmark, if it is
330 330 associated with the changeset"""
331 331 active = args['repo']._activebookmark
332 332 if active and active in args['ctx'].bookmarks():
333 333 return active
334 334 return ''
335 335
336 336 @templatekeyword('date')
337 337 def showdate(repo, ctx, templ, **args):
338 338 """Date information. The date when the changeset was committed."""
339 339 return ctx.date()
340 340
341 341 @templatekeyword('desc')
342 342 def showdescription(repo, ctx, templ, **args):
343 343 """String. The text of the changeset description."""
344 344 s = ctx.description()
345 345 if isinstance(s, encoding.localstr):
346 346 # try hard to preserve utf-8 bytes
347 347 return encoding.tolocal(encoding.fromlocal(s).strip())
348 348 else:
349 349 return s.strip()
350 350
351 351 @templatekeyword('diffstat')
352 352 def showdiffstat(repo, ctx, templ, **args):
353 353 """String. Statistics of changes with the following format:
354 354 "modified files: +added/-removed lines"
355 355 """
356 356 stats = patch.diffstatdata(util.iterlines(ctx.diff(noprefix=False)))
357 357 maxname, maxtotal, adds, removes, binary = patch.diffstatsum(stats)
358 358 return '%s: +%s/-%s' % (len(stats), adds, removes)
359 359
360 360 @templatekeyword('envvars')
361 361 def showenvvars(repo, **args):
362 362 """A dictionary of environment variables. (EXPERIMENTAL)"""
363 363 env = repo.ui.exportableenviron()
364 364 env = util.sortdict((k, env[k]) for k in sorted(env))
365 365 return showdict('envvar', env, args, plural='envvars')
366 366
367 367 @templatekeyword('extras')
368 368 def showextras(**args):
369 369 """List of dicts with key, value entries of the 'extras'
370 370 field of this changeset."""
371 371 extras = args['ctx'].extra()
372 372 extras = util.sortdict((k, extras[k]) for k in sorted(extras))
373 373 makemap = lambda k: {'key': k, 'value': extras[k]}
374 374 c = [makemap(k) for k in extras]
375 375 f = _showlist('extra', c, args, plural='extras')
376 376 return _hybrid(f, extras, makemap,
377 377 lambda x: '%s=%s' % (x['key'], util.escapestr(x['value'])))
378 378
379 379 @templatekeyword('file_adds')
380 380 def showfileadds(**args):
381 381 """List of strings. Files added by this changeset."""
382 382 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
383 383 return showlist('file_add', getfiles(repo, ctx, revcache)[1], args,
384 384 element='file')
385 385
386 386 @templatekeyword('file_copies')
387 387 def showfilecopies(**args):
388 388 """List of strings. Files copied in this changeset with
389 389 their sources.
390 390 """
391 391 cache, ctx = args['cache'], args['ctx']
392 392 copies = args['revcache'].get('copies')
393 393 if copies is None:
394 394 if 'getrenamed' not in cache:
395 395 cache['getrenamed'] = getrenamedfn(args['repo'])
396 396 copies = []
397 397 getrenamed = cache['getrenamed']
398 398 for fn in ctx.files():
399 399 rename = getrenamed(fn, ctx.rev())
400 400 if rename:
401 401 copies.append((fn, rename[0]))
402 402
403 403 copies = util.sortdict(copies)
404 404 return showdict('file_copy', copies, args, plural='file_copies',
405 405 key='name', value='source', fmt='%s (%s)')
406 406
407 407 # showfilecopiesswitch() displays file copies only if copy records are
408 408 # provided before calling the templater, usually with a --copies
409 409 # command line switch.
410 410 @templatekeyword('file_copies_switch')
411 411 def showfilecopiesswitch(**args):
412 412 """List of strings. Like "file_copies" but displayed
413 413 only if the --copied switch is set.
414 414 """
415 415 copies = args['revcache'].get('copies') or []
416 416 copies = util.sortdict(copies)
417 417 return showdict('file_copy', copies, args, plural='file_copies',
418 418 key='name', value='source', fmt='%s (%s)')
419 419
420 420 @templatekeyword('file_dels')
421 421 def showfiledels(**args):
422 422 """List of strings. Files removed by this changeset."""
423 423 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
424 424 return showlist('file_del', getfiles(repo, ctx, revcache)[2], args,
425 425 element='file')
426 426
427 427 @templatekeyword('file_mods')
428 428 def showfilemods(**args):
429 429 """List of strings. Files modified by this changeset."""
430 430 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
431 431 return showlist('file_mod', getfiles(repo, ctx, revcache)[0], args,
432 432 element='file')
433 433
434 434 @templatekeyword('files')
435 435 def showfiles(**args):
436 436 """List of strings. All files modified, added, or removed by this
437 437 changeset.
438 438 """
439 439 return showlist('file', args['ctx'].files(), args)
440 440
441 441 @templatekeyword('graphnode')
442 442 def showgraphnode(repo, ctx, **args):
443 443 """String. The character representing the changeset node in
444 444 an ASCII revision graph"""
445 445 wpnodes = repo.dirstate.parents()
446 446 if wpnodes[1] == nullid:
447 447 wpnodes = wpnodes[:1]
448 448 if ctx.node() in wpnodes:
449 449 return '@'
450 450 elif ctx.obsolete():
451 451 return 'x'
452 452 elif ctx.closesbranch():
453 453 return '_'
454 454 else:
455 455 return 'o'
456 456
457 457 @templatekeyword('index')
458 458 def showindex(**args):
459 459 """Integer. The current iteration of the loop. (0 indexed)"""
460 460 # just hosts documentation; should be overridden by template mapping
461 461 raise error.Abort(_("can't use index in this context"))
462 462
463 463 @templatekeyword('latesttag')
464 464 def showlatesttag(**args):
465 465 """List of strings. The global tags on the most recent globally
466 466 tagged ancestor of this changeset. If no such tags exist, the list
467 467 consists of the single string "null".
468 468 """
469 469 return showlatesttags(None, **args)
470 470
471 471 def showlatesttags(pattern, **args):
472 472 """helper method for the latesttag keyword and function"""
473 473 repo, ctx = args['repo'], args['ctx']
474 474 cache = args['cache']
475 475 latesttags = getlatesttags(repo, ctx, cache, pattern)
476 476
477 477 # latesttag[0] is an implementation detail for sorting csets on different
478 478 # branches in a stable manner- it is the date the tagged cset was created,
479 479 # not the date the tag was created. Therefore it isn't made visible here.
480 480 makemap = lambda v: {
481 481 'changes': _showchangessincetag,
482 482 'distance': latesttags[1],
483 483 'latesttag': v, # BC with {latesttag % '{latesttag}'}
484 484 'tag': v
485 485 }
486 486
487 487 tags = latesttags[2]
488 488 f = _showlist('latesttag', tags, args, separator=':')
489 489 return _hybrid(f, tags, makemap, lambda x: x['latesttag'])
490 490
491 491 @templatekeyword('latesttagdistance')
492 492 def showlatesttagdistance(repo, ctx, templ, cache, **args):
493 493 """Integer. Longest path to the latest tag."""
494 494 return getlatesttags(repo, ctx, cache)[1]
495 495
496 496 @templatekeyword('changessincelatesttag')
497 497 def showchangessincelatesttag(repo, ctx, templ, cache, **args):
498 498 """Integer. All ancestors not in the latest tag."""
499 499 latesttag = getlatesttags(repo, ctx, cache)[2][0]
500 500
501 501 return _showchangessincetag(repo, ctx, tag=latesttag, **args)
502 502
503 503 def _showchangessincetag(repo, ctx, **args):
504 504 offset = 0
505 505 revs = [ctx.rev()]
506 506 tag = args['tag']
507 507
508 508 # The only() revset doesn't currently support wdir()
509 509 if ctx.rev() is None:
510 510 offset = 1
511 511 revs = [p.rev() for p in ctx.parents()]
512 512
513 513 return len(repo.revs('only(%ld, %s)', revs, tag)) + offset
514 514
515 515 @templatekeyword('manifest')
516 516 def showmanifest(**args):
517 517 repo, ctx, templ = args['repo'], args['ctx'], args['templ']
518 518 mnode = ctx.manifestnode()
519 519 if mnode is None:
520 520 # just avoid crash, we might want to use the 'ff...' hash in future
521 521 return
522 522 args = args.copy()
523 523 args.update({'rev': repo.manifestlog._revlog.rev(mnode),
524 524 'node': hex(mnode)})
525 525 return templ('manifest', **args)
526 526
527 527 def shownames(namespace, **args):
528 528 """helper method to generate a template keyword for a namespace"""
529 529 ctx = args['ctx']
530 530 repo = ctx.repo()
531 531 ns = repo.names[namespace]
532 532 names = ns.names(repo, ctx.node())
533 533 return showlist(ns.templatename, names, args, plural=namespace)
534 534
535 535 @templatekeyword('namespaces')
536 536 def shownamespaces(**args):
537 537 """Dict of lists. Names attached to this changeset per
538 538 namespace."""
539 539 ctx = args['ctx']
540 540 repo = ctx.repo()
541 541 namespaces = util.sortdict((k, showlist('name', ns.names(repo, ctx.node()),
542 542 args))
543 543 for k, ns in repo.names.iteritems())
544 544 f = _showlist('namespace', list(namespaces), args)
545 545 return _hybrid(f, namespaces,
546 546 lambda k: {'namespace': k, 'names': namespaces[k]},
547 547 lambda x: x['namespace'])
548 548
549 549 @templatekeyword('node')
550 550 def shownode(repo, ctx, templ, **args):
551 551 """String. The changeset identification hash, as a 40 hexadecimal
552 552 digit string.
553 553 """
554 554 return ctx.hex()
555 555
556 556 @templatekeyword('obsolete')
557 557 def showobsolete(repo, ctx, templ, **args):
558 558 """String. Whether the changeset is obsolete.
559 559 """
560 560 if ctx.obsolete():
561 561 return 'obsolete'
562 562 return ''
563 563
564 564 @templatekeyword("predecessors")
565 565 def showpredecessors(repo, ctx, **args):
566 566 """Returns the list if the closest visible successors
567 567 """
568 568 predecessors = sorted(obsutil.closestpredecessors(repo, ctx.node()))
569 569 predecessors = map(hex, predecessors)
570 570
571 return _hybrid(None, predecessors, lambda x: {'predecessor': x},
572 lambda d: d['predecessor'][:12])
571 return _hybrid(None, predecessors, lambda x: {'node': x},
572 lambda d: d['node'][:12])
573 573
574 574 @templatekeyword('p1rev')
575 575 def showp1rev(repo, ctx, templ, **args):
576 576 """Integer. The repository-local revision number of the changeset's
577 577 first parent, or -1 if the changeset has no parents."""
578 578 return ctx.p1().rev()
579 579
580 580 @templatekeyword('p2rev')
581 581 def showp2rev(repo, ctx, templ, **args):
582 582 """Integer. The repository-local revision number of the changeset's
583 583 second parent, or -1 if the changeset has no second parent."""
584 584 return ctx.p2().rev()
585 585
586 586 @templatekeyword('p1node')
587 587 def showp1node(repo, ctx, templ, **args):
588 588 """String. The identification hash of the changeset's first parent,
589 589 as a 40 digit hexadecimal string. If the changeset has no parents, all
590 590 digits are 0."""
591 591 return ctx.p1().hex()
592 592
593 593 @templatekeyword('p2node')
594 594 def showp2node(repo, ctx, templ, **args):
595 595 """String. The identification hash of the changeset's second
596 596 parent, as a 40 digit hexadecimal string. If the changeset has no second
597 597 parent, all digits are 0."""
598 598 return ctx.p2().hex()
599 599
600 600 @templatekeyword('parents')
601 601 def showparents(**args):
602 602 """List of strings. The parents of the changeset in "rev:node"
603 603 format. If the changeset has only one "natural" parent (the predecessor
604 604 revision) nothing is shown."""
605 605 repo = args['repo']
606 606 ctx = args['ctx']
607 607 pctxs = scmutil.meaningfulparents(repo, ctx)
608 608 prevs = [str(p.rev()) for p in pctxs] # ifcontains() needs a list of str
609 609 parents = [[('rev', p.rev()),
610 610 ('node', p.hex()),
611 611 ('phase', p.phasestr())]
612 612 for p in pctxs]
613 613 f = _showlist('parent', parents, args)
614 614 return _hybrid(f, prevs, lambda x: {'ctx': repo[int(x)], 'revcache': {}},
615 615 lambda d: _formatrevnode(d['ctx']))
616 616
617 617 @templatekeyword('phase')
618 618 def showphase(repo, ctx, templ, **args):
619 619 """String. The changeset phase name."""
620 620 return ctx.phasestr()
621 621
622 622 @templatekeyword('phaseidx')
623 623 def showphaseidx(repo, ctx, templ, **args):
624 624 """Integer. The changeset phase index."""
625 625 return ctx.phase()
626 626
627 627 @templatekeyword('rev')
628 628 def showrev(repo, ctx, templ, **args):
629 629 """Integer. The repository-local changeset revision number."""
630 630 return scmutil.intrev(ctx)
631 631
632 632 def showrevslist(name, revs, **args):
633 633 """helper to generate a list of revisions in which a mapped template will
634 634 be evaluated"""
635 635 repo = args['ctx'].repo()
636 636 revs = [str(r) for r in revs] # ifcontains() needs a list of str
637 637 f = _showlist(name, revs, args)
638 638 return _hybrid(f, revs,
639 639 lambda x: {name: x, 'ctx': repo[int(x)], 'revcache': {}},
640 640 lambda d: d[name])
641 641
642 642 @templatekeyword('subrepos')
643 643 def showsubrepos(**args):
644 644 """List of strings. Updated subrepositories in the changeset."""
645 645 ctx = args['ctx']
646 646 substate = ctx.substate
647 647 if not substate:
648 648 return showlist('subrepo', [], args)
649 649 psubstate = ctx.parents()[0].substate or {}
650 650 subrepos = []
651 651 for sub in substate:
652 652 if sub not in psubstate or substate[sub] != psubstate[sub]:
653 653 subrepos.append(sub) # modified or newly added in ctx
654 654 for sub in psubstate:
655 655 if sub not in substate:
656 656 subrepos.append(sub) # removed in ctx
657 657 return showlist('subrepo', sorted(subrepos), args)
658 658
659 659 # don't remove "showtags" definition, even though namespaces will put
660 660 # a helper function for "tags" keyword into "keywords" map automatically,
661 661 # because online help text is built without namespaces initialization
662 662 @templatekeyword('tags')
663 663 def showtags(**args):
664 664 """List of strings. Any tags associated with the changeset."""
665 665 return shownames('tags', **args)
666 666
667 667 def loadkeyword(ui, extname, registrarobj):
668 668 """Load template keyword from specified registrarobj
669 669 """
670 670 for name, func in registrarobj._table.iteritems():
671 671 keywords[name] = func
672 672
673 673 @templatekeyword('termwidth')
674 674 def termwidth(repo, ctx, templ, **args):
675 675 """Integer. The width of the current terminal."""
676 676 return repo.ui.termwidth()
677 677
678 678 @templatekeyword('troubles')
679 679 def showtroubles(**args):
680 680 """List of strings. Evolution troubles affecting the changeset.
681 681
682 682 (EXPERIMENTAL)
683 683 """
684 684 return showlist('trouble', args['ctx'].troubles(), args)
685 685
686 686 # tell hggettext to extract docstrings from these functions:
687 687 i18nfunctions = keywords.values()
@@ -1,855 +1,888 b''
1 1 This test file test the various templates related to obsmarkers.
2 2
3 3 Global setup
4 4 ============
5 5
6 6 $ . $TESTDIR/testlib/obsmarker-common.sh
7 7 $ cat >> $HGRCPATH <<EOF
8 8 > [ui]
9 9 > interactive = true
10 10 > [phases]
11 11 > publish=False
12 12 > [experimental]
13 13 > evolution=all
14 14 > [alias]
15 15 > tlog = log -G -T '{node|short}\
16 16 > {if(predecessors, "\n Predecessors: {predecessors}")}\
17 17 > {if(predecessors, "\n semi-colon: {join(predecessors, "; ")}")}\
18 > {if(predecessors, "\n json: {predecessors|json}")}\n'
18 > {if(predecessors, "\n json: {predecessors|json}")}\
19 > {if(predecessors, "\n map: {join(predecessors % "{node}", " ")}")}\n'
19 20 > EOF
20 21
21 22 Test templates on amended commit
22 23 ================================
23 24
24 25 Test setup
25 26 ----------
26 27
27 28 $ hg init $TESTTMP/templates-local-amend
28 29 $ cd $TESTTMP/templates-local-amend
29 30 $ mkcommit ROOT
30 31 $ mkcommit A0
31 32 $ echo 42 >> A0
32 33 $ hg commit --amend -m "A1"
33 34 $ hg commit --amend -m "A2"
34 35
35 36 $ hg log --hidden -G
36 37 @ changeset: 4:d004c8f274b9
37 38 | tag: tip
38 39 | parent: 0:ea207398892e
39 40 | user: test
40 41 | date: Thu Jan 01 00:00:00 1970 +0000
41 42 | summary: A2
42 43 |
43 44 | x changeset: 3:a468dc9b3633
44 45 |/ parent: 0:ea207398892e
45 46 | user: test
46 47 | date: Thu Jan 01 00:00:00 1970 +0000
47 48 | summary: A1
48 49 |
49 50 | x changeset: 2:f137d23bb3e1
50 51 | | user: test
51 52 | | date: Thu Jan 01 00:00:00 1970 +0000
52 53 | | summary: temporary amend commit for 471f378eab4c
53 54 | |
54 55 | x changeset: 1:471f378eab4c
55 56 |/ user: test
56 57 | date: Thu Jan 01 00:00:00 1970 +0000
57 58 | summary: A0
58 59 |
59 60 o changeset: 0:ea207398892e
60 61 user: test
61 62 date: Thu Jan 01 00:00:00 1970 +0000
62 63 summary: ROOT
63 64
64 65 Check templates
65 66 ---------------
66 67 $ hg up 'desc(A0)' --hidden
67 68 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
68 69
69 70 Predecessors template should show current revision as it is the working copy
70 71 $ hg tlog
71 72 o d004c8f274b9
72 73 | Predecessors: 471f378eab4c
73 74 | semi-colon: 471f378eab4c
74 75 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
76 | map: 471f378eab4c5e25f6c77f785b27c936efb22874
75 77 | @ 471f378eab4c
76 78 |/
77 79 o ea207398892e
78 80
79 81 $ hg up 'desc(A1)' --hidden
80 82 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
81 83
82 84 Predecessors template should show current revision as it is the working copy
83 85 $ hg tlog
84 86 o d004c8f274b9
85 87 | Predecessors: a468dc9b3633
86 88 | semi-colon: a468dc9b3633
87 89 | json: ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"]
90 | map: a468dc9b36338b14fdb7825f55ce3df4e71517ad
88 91 | @ a468dc9b3633
89 92 |/
90 93 o ea207398892e
91 94
92 95 Predecessors template should show all the predecessors as we force their display
93 96 with --hidden
94 97 $ hg tlog --hidden
95 98 o d004c8f274b9
96 99 | Predecessors: a468dc9b3633
97 100 | semi-colon: a468dc9b3633
98 101 | json: ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"]
102 | map: a468dc9b36338b14fdb7825f55ce3df4e71517ad
99 103 | @ a468dc9b3633
100 104 |/ Predecessors: 471f378eab4c
101 105 | semi-colon: 471f378eab4c
102 106 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
107 | map: 471f378eab4c5e25f6c77f785b27c936efb22874
103 108 | x f137d23bb3e1
104 109 | |
105 110 | x 471f378eab4c
106 111 |/
107 112 o ea207398892e
108 113
109 114
110 115 Predecessors template shouldn't show anything as all obsolete commit are not
111 116 visible.
112 117 $ hg up 'desc(A2)'
113 118 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
114 119 $ hg tlog
115 120 @ d004c8f274b9
116 121 |
117 122 o ea207398892e
118 123
119 124 $ hg tlog --hidden
120 125 @ d004c8f274b9
121 126 | Predecessors: a468dc9b3633
122 127 | semi-colon: a468dc9b3633
123 128 | json: ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"]
129 | map: a468dc9b36338b14fdb7825f55ce3df4e71517ad
124 130 | x a468dc9b3633
125 131 |/ Predecessors: 471f378eab4c
126 132 | semi-colon: 471f378eab4c
127 133 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
134 | map: 471f378eab4c5e25f6c77f785b27c936efb22874
128 135 | x f137d23bb3e1
129 136 | |
130 137 | x 471f378eab4c
131 138 |/
132 139 o ea207398892e
133 140
134 141
135 142 Test templates with splitted commit
136 143 ===================================
137 144
138 145 $ hg init $TESTTMP/templates-local-split
139 146 $ cd $TESTTMP/templates-local-split
140 147 $ mkcommit ROOT
141 148 $ echo 42 >> a
142 149 $ echo 43 >> b
143 150 $ hg commit -A -m "A0"
144 151 adding a
145 152 adding b
146 153 $ hg log --hidden -G
147 154 @ changeset: 1:471597cad322
148 155 | tag: tip
149 156 | user: test
150 157 | date: Thu Jan 01 00:00:00 1970 +0000
151 158 | summary: A0
152 159 |
153 160 o changeset: 0:ea207398892e
154 161 user: test
155 162 date: Thu Jan 01 00:00:00 1970 +0000
156 163 summary: ROOT
157 164
158 165 # Simulate split
159 166 $ hg up -r "desc(ROOT)"
160 167 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
161 168 $ echo 42 >> a
162 169 $ hg commit -A -m "A0"
163 170 adding a
164 171 created new head
165 172 $ echo 43 >> b
166 173 $ hg commit -A -m "A0"
167 174 adding b
168 175 $ hg debugobsolete `getid "1"` `getid "2"` `getid "3"`
169 176
170 177 $ hg log --hidden -G
171 178 @ changeset: 3:f257fde29c7a
172 179 | tag: tip
173 180 | user: test
174 181 | date: Thu Jan 01 00:00:00 1970 +0000
175 182 | summary: A0
176 183 |
177 184 o changeset: 2:337fec4d2edc
178 185 | parent: 0:ea207398892e
179 186 | user: test
180 187 | date: Thu Jan 01 00:00:00 1970 +0000
181 188 | summary: A0
182 189 |
183 190 | x changeset: 1:471597cad322
184 191 |/ user: test
185 192 | date: Thu Jan 01 00:00:00 1970 +0000
186 193 | summary: A0
187 194 |
188 195 o changeset: 0:ea207398892e
189 196 user: test
190 197 date: Thu Jan 01 00:00:00 1970 +0000
191 198 summary: ROOT
192 199
193 200 Check templates
194 201 ---------------
195 202
196 203 $ hg up 'obsolete()' --hidden
197 204 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
198 205
199 206 Predecessors template should show current revision as it is the working copy
200 207 $ hg tlog
201 208 o f257fde29c7a
202 209 | Predecessors: 471597cad322
203 210 | semi-colon: 471597cad322
204 211 | json: ["471597cad322d1f659bb169751be9133dad92ef3"]
212 | map: 471597cad322d1f659bb169751be9133dad92ef3
205 213 o 337fec4d2edc
206 214 | Predecessors: 471597cad322
207 215 | semi-colon: 471597cad322
208 216 | json: ["471597cad322d1f659bb169751be9133dad92ef3"]
217 | map: 471597cad322d1f659bb169751be9133dad92ef3
209 218 | @ 471597cad322
210 219 |/
211 220 o ea207398892e
212 221
213 222 $ hg up f257fde29c7a
214 223 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
215 224
216 225 Predecessors template should not show a predecessor as it's not displayed in
217 226 the log
218 227 $ hg tlog
219 228 @ f257fde29c7a
220 229 |
221 230 o 337fec4d2edc
222 231 |
223 232 o ea207398892e
224 233
225 234 Predecessors template should show both predecessors as we force their display
226 235 with --hidden
227 236 $ hg tlog --hidden
228 237 @ f257fde29c7a
229 238 | Predecessors: 471597cad322
230 239 | semi-colon: 471597cad322
231 240 | json: ["471597cad322d1f659bb169751be9133dad92ef3"]
241 | map: 471597cad322d1f659bb169751be9133dad92ef3
232 242 o 337fec4d2edc
233 243 | Predecessors: 471597cad322
234 244 | semi-colon: 471597cad322
235 245 | json: ["471597cad322d1f659bb169751be9133dad92ef3"]
246 | map: 471597cad322d1f659bb169751be9133dad92ef3
236 247 | x 471597cad322
237 248 |/
238 249 o ea207398892e
239 250
240 251 Test templates with folded commit
241 252 =================================
242 253
243 254 Test setup
244 255 ----------
245 256
246 257 $ hg init $TESTTMP/templates-local-fold
247 258 $ cd $TESTTMP/templates-local-fold
248 259 $ mkcommit ROOT
249 260 $ mkcommit A0
250 261 $ mkcommit B0
251 262 $ hg log --hidden -G
252 263 @ changeset: 2:0dec01379d3b
253 264 | tag: tip
254 265 | user: test
255 266 | date: Thu Jan 01 00:00:00 1970 +0000
256 267 | summary: B0
257 268 |
258 269 o changeset: 1:471f378eab4c
259 270 | user: test
260 271 | date: Thu Jan 01 00:00:00 1970 +0000
261 272 | summary: A0
262 273 |
263 274 o changeset: 0:ea207398892e
264 275 user: test
265 276 date: Thu Jan 01 00:00:00 1970 +0000
266 277 summary: ROOT
267 278
268 279 Simulate a fold
269 280 $ hg up -r "desc(ROOT)"
270 281 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
271 282 $ echo "A0" > A0
272 283 $ echo "B0" > B0
273 284 $ hg commit -A -m "C0"
274 285 adding A0
275 286 adding B0
276 287 created new head
277 288 $ hg debugobsolete `getid "desc(A0)"` `getid "desc(C0)"`
278 289 $ hg debugobsolete `getid "desc(B0)"` `getid "desc(C0)"`
279 290
280 291 $ hg log --hidden -G
281 292 @ changeset: 3:eb5a0daa2192
282 293 | tag: tip
283 294 | parent: 0:ea207398892e
284 295 | user: test
285 296 | date: Thu Jan 01 00:00:00 1970 +0000
286 297 | summary: C0
287 298 |
288 299 | x changeset: 2:0dec01379d3b
289 300 | | user: test
290 301 | | date: Thu Jan 01 00:00:00 1970 +0000
291 302 | | summary: B0
292 303 | |
293 304 | x changeset: 1:471f378eab4c
294 305 |/ user: test
295 306 | date: Thu Jan 01 00:00:00 1970 +0000
296 307 | summary: A0
297 308 |
298 309 o changeset: 0:ea207398892e
299 310 user: test
300 311 date: Thu Jan 01 00:00:00 1970 +0000
301 312 summary: ROOT
302 313
303 314 Check templates
304 315 ---------------
305 316
306 317 $ hg up 'desc(A0)' --hidden
307 318 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
308 319
309 320 Predecessors template should show current revision as it is the working copy
310 321 $ hg tlog
311 322 o eb5a0daa2192
312 323 | Predecessors: 471f378eab4c
313 324 | semi-colon: 471f378eab4c
314 325 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
326 | map: 471f378eab4c5e25f6c77f785b27c936efb22874
315 327 | @ 471f378eab4c
316 328 |/
317 329 o ea207398892e
318 330
319 331 $ hg up 'desc(B0)' --hidden
320 332 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
321 333
322 334 Predecessors template should show both predecessors as they should be both
323 335 displayed
324 336 $ hg tlog
325 337 o eb5a0daa2192
326 338 | Predecessors: 0dec01379d3b 471f378eab4c
327 339 | semi-colon: 0dec01379d3b; 471f378eab4c
328 340 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", "471f378eab4c5e25f6c77f785b27c936efb22874"]
341 | map: 0dec01379d3be6318c470ead31b1fe7ae7cb53d5 471f378eab4c5e25f6c77f785b27c936efb22874
329 342 | @ 0dec01379d3b
330 343 | |
331 344 | x 471f378eab4c
332 345 |/
333 346 o ea207398892e
334 347
335 348 $ hg up 'desc(C0)'
336 349 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
337 350
338 351 Predecessors template should not show predecessors as they are not displayed in
339 352 the log
340 353 $ hg tlog
341 354 @ eb5a0daa2192
342 355 |
343 356 o ea207398892e
344 357
345 358 Predecessors template should show both predecessors as we force their display
346 359 with --hidden
347 360 $ hg tlog --hidden
348 361 @ eb5a0daa2192
349 362 | Predecessors: 0dec01379d3b 471f378eab4c
350 363 | semi-colon: 0dec01379d3b; 471f378eab4c
351 364 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", "471f378eab4c5e25f6c77f785b27c936efb22874"]
365 | map: 0dec01379d3be6318c470ead31b1fe7ae7cb53d5 471f378eab4c5e25f6c77f785b27c936efb22874
352 366 | x 0dec01379d3b
353 367 | |
354 368 | x 471f378eab4c
355 369 |/
356 370 o ea207398892e
357 371
358 372
359 373 Test templates with divergence
360 374 ==============================
361 375
362 376 Test setup
363 377 ----------
364 378
365 379 $ hg init $TESTTMP/templates-local-divergence
366 380 $ cd $TESTTMP/templates-local-divergence
367 381 $ mkcommit ROOT
368 382 $ mkcommit A0
369 383 $ hg commit --amend -m "A1"
370 384 $ hg log --hidden -G
371 385 @ changeset: 2:fdf9bde5129a
372 386 | tag: tip
373 387 | parent: 0:ea207398892e
374 388 | user: test
375 389 | date: Thu Jan 01 00:00:00 1970 +0000
376 390 | summary: A1
377 391 |
378 392 | x changeset: 1:471f378eab4c
379 393 |/ user: test
380 394 | date: Thu Jan 01 00:00:00 1970 +0000
381 395 | summary: A0
382 396 |
383 397 o changeset: 0:ea207398892e
384 398 user: test
385 399 date: Thu Jan 01 00:00:00 1970 +0000
386 400 summary: ROOT
387 401
388 402 $ hg update --hidden 'desc(A0)'
389 403 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
390 404 $ hg commit --amend -m "A2"
391 405 $ hg log --hidden -G
392 406 @ changeset: 3:65b757b745b9
393 407 | tag: tip
394 408 | parent: 0:ea207398892e
395 409 | user: test
396 410 | date: Thu Jan 01 00:00:00 1970 +0000
397 411 | trouble: divergent
398 412 | summary: A2
399 413 |
400 414 | o changeset: 2:fdf9bde5129a
401 415 |/ parent: 0:ea207398892e
402 416 | user: test
403 417 | date: Thu Jan 01 00:00:00 1970 +0000
404 418 | trouble: divergent
405 419 | summary: A1
406 420 |
407 421 | x changeset: 1:471f378eab4c
408 422 |/ user: test
409 423 | date: Thu Jan 01 00:00:00 1970 +0000
410 424 | summary: A0
411 425 |
412 426 o changeset: 0:ea207398892e
413 427 user: test
414 428 date: Thu Jan 01 00:00:00 1970 +0000
415 429 summary: ROOT
416 430
417 431 $ hg commit --amend -m 'A3'
418 432 $ hg log --hidden -G
419 433 @ changeset: 4:019fadeab383
420 434 | tag: tip
421 435 | parent: 0:ea207398892e
422 436 | user: test
423 437 | date: Thu Jan 01 00:00:00 1970 +0000
424 438 | trouble: divergent
425 439 | summary: A3
426 440 |
427 441 | x changeset: 3:65b757b745b9
428 442 |/ parent: 0:ea207398892e
429 443 | user: test
430 444 | date: Thu Jan 01 00:00:00 1970 +0000
431 445 | summary: A2
432 446 |
433 447 | o changeset: 2:fdf9bde5129a
434 448 |/ parent: 0:ea207398892e
435 449 | user: test
436 450 | date: Thu Jan 01 00:00:00 1970 +0000
437 451 | trouble: divergent
438 452 | summary: A1
439 453 |
440 454 | x changeset: 1:471f378eab4c
441 455 |/ user: test
442 456 | date: Thu Jan 01 00:00:00 1970 +0000
443 457 | summary: A0
444 458 |
445 459 o changeset: 0:ea207398892e
446 460 user: test
447 461 date: Thu Jan 01 00:00:00 1970 +0000
448 462 summary: ROOT
449 463
450 464
451 465 Check templates
452 466 ---------------
453 467
454 468 $ hg up 'desc(A0)' --hidden
455 469 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
456 470
457 471 Predecessors template should show current revision as it is the working copy
458 472 $ hg tlog
459 473 o 019fadeab383
460 474 | Predecessors: 471f378eab4c
461 475 | semi-colon: 471f378eab4c
462 476 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
477 | map: 471f378eab4c5e25f6c77f785b27c936efb22874
463 478 | o fdf9bde5129a
464 479 |/ Predecessors: 471f378eab4c
465 480 | semi-colon: 471f378eab4c
466 481 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
482 | map: 471f378eab4c5e25f6c77f785b27c936efb22874
467 483 | @ 471f378eab4c
468 484 |/
469 485 o ea207398892e
470 486
471 487 $ hg up 'desc(A1)'
472 488 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
473 489
474 490 Predecessors template should not show predecessors as they are not displayed in
475 491 the log
476 492 $ hg tlog
477 493 o 019fadeab383
478 494 |
479 495 | @ fdf9bde5129a
480 496 |/
481 497 o ea207398892e
482 498
483 499 Predecessors template should the predecessors as we force their display with
484 500 --hidden
485 501 $ hg tlog --hidden
486 502 o 019fadeab383
487 503 | Predecessors: 65b757b745b9
488 504 | semi-colon: 65b757b745b9
489 505 | json: ["65b757b745b935093c87a2bccd877521cccffcbd"]
506 | map: 65b757b745b935093c87a2bccd877521cccffcbd
490 507 | x 65b757b745b9
491 508 |/ Predecessors: 471f378eab4c
492 509 | semi-colon: 471f378eab4c
493 510 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
511 | map: 471f378eab4c5e25f6c77f785b27c936efb22874
494 512 | @ fdf9bde5129a
495 513 |/ Predecessors: 471f378eab4c
496 514 | semi-colon: 471f378eab4c
497 515 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
516 | map: 471f378eab4c5e25f6c77f785b27c936efb22874
498 517 | x 471f378eab4c
499 518 |/
500 519 o ea207398892e
501 520
502 521
503 522 Test templates with amended + folded commit
504 523 ===========================================
505 524
506 525 Test setup
507 526 ----------
508 527
509 528 $ hg init $TESTTMP/templates-local-amend-fold
510 529 $ cd $TESTTMP/templates-local-amend-fold
511 530 $ mkcommit ROOT
512 531 $ mkcommit A0
513 532 $ mkcommit B0
514 533 $ hg commit --amend -m "B1"
515 534 $ hg log --hidden -G
516 535 @ changeset: 3:b7ea6d14e664
517 536 | tag: tip
518 537 | parent: 1:471f378eab4c
519 538 | user: test
520 539 | date: Thu Jan 01 00:00:00 1970 +0000
521 540 | summary: B1
522 541 |
523 542 | x changeset: 2:0dec01379d3b
524 543 |/ user: test
525 544 | date: Thu Jan 01 00:00:00 1970 +0000
526 545 | summary: B0
527 546 |
528 547 o changeset: 1:471f378eab4c
529 548 | user: test
530 549 | date: Thu Jan 01 00:00:00 1970 +0000
531 550 | summary: A0
532 551 |
533 552 o changeset: 0:ea207398892e
534 553 user: test
535 554 date: Thu Jan 01 00:00:00 1970 +0000
536 555 summary: ROOT
537 556
538 557 # Simulate a fold
539 558 $ hg up -r "desc(ROOT)"
540 559 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
541 560 $ echo "A0" > A0
542 561 $ echo "B0" > B0
543 562 $ hg commit -A -m "C0"
544 563 adding A0
545 564 adding B0
546 565 created new head
547 566 $ hg debugobsolete `getid "desc(A0)"` `getid "desc(C0)"`
548 567 $ hg debugobsolete `getid "desc(B1)"` `getid "desc(C0)"`
549 568
550 569 $ hg log --hidden -G
551 570 @ changeset: 4:eb5a0daa2192
552 571 | tag: tip
553 572 | parent: 0:ea207398892e
554 573 | user: test
555 574 | date: Thu Jan 01 00:00:00 1970 +0000
556 575 | summary: C0
557 576 |
558 577 | x changeset: 3:b7ea6d14e664
559 578 | | parent: 1:471f378eab4c
560 579 | | user: test
561 580 | | date: Thu Jan 01 00:00:00 1970 +0000
562 581 | | summary: B1
563 582 | |
564 583 | | x changeset: 2:0dec01379d3b
565 584 | |/ user: test
566 585 | | date: Thu Jan 01 00:00:00 1970 +0000
567 586 | | summary: B0
568 587 | |
569 588 | x changeset: 1:471f378eab4c
570 589 |/ user: test
571 590 | date: Thu Jan 01 00:00:00 1970 +0000
572 591 | summary: A0
573 592 |
574 593 o changeset: 0:ea207398892e
575 594 user: test
576 595 date: Thu Jan 01 00:00:00 1970 +0000
577 596 summary: ROOT
578 597
579 598 Check templates
580 599 ---------------
581 600
582 601 $ hg up 'desc(A0)' --hidden
583 602 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
584 603
585 604 Predecessors template should show current revision as it is the working copy
586 605 $ hg tlog
587 606 o eb5a0daa2192
588 607 | Predecessors: 471f378eab4c
589 608 | semi-colon: 471f378eab4c
590 609 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
610 | map: 471f378eab4c5e25f6c77f785b27c936efb22874
591 611 | @ 471f378eab4c
592 612 |/
593 613 o ea207398892e
594 614
595 615 $ hg up 'desc(B0)' --hidden
596 616 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
597 617
598 618 Predecessors template should both predecessors as they are visible
599 619 $ hg tlog
600 620 o eb5a0daa2192
601 621 | Predecessors: 0dec01379d3b 471f378eab4c
602 622 | semi-colon: 0dec01379d3b; 471f378eab4c
603 623 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", "471f378eab4c5e25f6c77f785b27c936efb22874"]
624 | map: 0dec01379d3be6318c470ead31b1fe7ae7cb53d5 471f378eab4c5e25f6c77f785b27c936efb22874
604 625 | @ 0dec01379d3b
605 626 | |
606 627 | x 471f378eab4c
607 628 |/
608 629 o ea207398892e
609 630
610 631 $ hg up 'desc(B1)' --hidden
611 632 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
612 633
613 634 Predecessors template should both predecessors as they are visible
614 635 $ hg tlog
615 636 o eb5a0daa2192
616 637 | Predecessors: 471f378eab4c b7ea6d14e664
617 638 | semi-colon: 471f378eab4c; b7ea6d14e664
618 639 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874", "b7ea6d14e664bdc8922221f7992631b50da3fb07"]
640 | map: 471f378eab4c5e25f6c77f785b27c936efb22874 b7ea6d14e664bdc8922221f7992631b50da3fb07
619 641 | @ b7ea6d14e664
620 642 | |
621 643 | x 471f378eab4c
622 644 |/
623 645 o ea207398892e
624 646
625 647 $ hg up 'desc(C0)'
626 648 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
627 649
628 650 Predecessors template should show no predecessors as they are both non visible
629 651 $ hg tlog
630 652 @ eb5a0daa2192
631 653 |
632 654 o ea207398892e
633 655
634 656 Predecessors template should show all predecessors as we force their display
635 657 with --hidden
636 658 $ hg tlog --hidden
637 659 @ eb5a0daa2192
638 660 | Predecessors: 471f378eab4c b7ea6d14e664
639 661 | semi-colon: 471f378eab4c; b7ea6d14e664
640 662 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874", "b7ea6d14e664bdc8922221f7992631b50da3fb07"]
663 | map: 471f378eab4c5e25f6c77f785b27c936efb22874 b7ea6d14e664bdc8922221f7992631b50da3fb07
641 664 | x b7ea6d14e664
642 665 | | Predecessors: 0dec01379d3b
643 666 | | semi-colon: 0dec01379d3b
644 667 | | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
668 | | map: 0dec01379d3be6318c470ead31b1fe7ae7cb53d5
645 669 | | x 0dec01379d3b
646 670 | |/
647 671 | x 471f378eab4c
648 672 |/
649 673 o ea207398892e
650 674
651 675
652 676 Test template with pushed and pulled obs markers
653 677 ================================================
654 678
655 679 Test setup
656 680 ----------
657 681
658 682 $ hg init $TESTTMP/templates-local-remote-markers-1
659 683 $ cd $TESTTMP/templates-local-remote-markers-1
660 684 $ mkcommit ROOT
661 685 $ mkcommit A0
662 686 $ hg clone $TESTTMP/templates-local-remote-markers-1 $TESTTMP/templates-local-remote-markers-2
663 687 updating to branch default
664 688 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
665 689 $ cd $TESTTMP/templates-local-remote-markers-2
666 690 $ hg log --hidden -G
667 691 @ changeset: 1:471f378eab4c
668 692 | tag: tip
669 693 | user: test
670 694 | date: Thu Jan 01 00:00:00 1970 +0000
671 695 | summary: A0
672 696 |
673 697 o changeset: 0:ea207398892e
674 698 user: test
675 699 date: Thu Jan 01 00:00:00 1970 +0000
676 700 summary: ROOT
677 701
678 702 $ cd $TESTTMP/templates-local-remote-markers-1
679 703 $ hg commit --amend -m "A1"
680 704 $ hg commit --amend -m "A2"
681 705 $ hg log --hidden -G
682 706 @ changeset: 3:7a230b46bf61
683 707 | tag: tip
684 708 | parent: 0:ea207398892e
685 709 | user: test
686 710 | date: Thu Jan 01 00:00:00 1970 +0000
687 711 | summary: A2
688 712 |
689 713 | x changeset: 2:fdf9bde5129a
690 714 |/ parent: 0:ea207398892e
691 715 | user: test
692 716 | date: Thu Jan 01 00:00:00 1970 +0000
693 717 | summary: A1
694 718 |
695 719 | x changeset: 1:471f378eab4c
696 720 |/ user: test
697 721 | date: Thu Jan 01 00:00:00 1970 +0000
698 722 | summary: A0
699 723 |
700 724 o changeset: 0:ea207398892e
701 725 user: test
702 726 date: Thu Jan 01 00:00:00 1970 +0000
703 727 summary: ROOT
704 728
705 729 $ cd $TESTTMP/templates-local-remote-markers-2
706 730 $ hg pull
707 731 pulling from $TESTTMP/templates-local-remote-markers-1 (glob)
708 732 searching for changes
709 733 adding changesets
710 734 adding manifests
711 735 adding file changes
712 736 added 1 changesets with 0 changes to 1 files (+1 heads)
713 737 2 new obsolescence markers
714 738 (run 'hg heads' to see heads, 'hg merge' to merge)
715 739 $ hg log --hidden -G
716 740 o changeset: 2:7a230b46bf61
717 741 | tag: tip
718 742 | parent: 0:ea207398892e
719 743 | user: test
720 744 | date: Thu Jan 01 00:00:00 1970 +0000
721 745 | summary: A2
722 746 |
723 747 | @ changeset: 1:471f378eab4c
724 748 |/ user: test
725 749 | date: Thu Jan 01 00:00:00 1970 +0000
726 750 | summary: A0
727 751 |
728 752 o changeset: 0:ea207398892e
729 753 user: test
730 754 date: Thu Jan 01 00:00:00 1970 +0000
731 755 summary: ROOT
732 756
733 757
734 758 $ hg debugobsolete
735 759 471f378eab4c5e25f6c77f785b27c936efb22874 fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
736 760 fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e 7a230b46bf61e50b30308c6cfd7bd1269ef54702 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
737 761
738 762 Check templates
739 763 ---------------
740 764
741 765 Predecessors template should show current revision as it is the working copy
742 766 $ hg tlog
743 767 o 7a230b46bf61
744 768 | Predecessors: 471f378eab4c
745 769 | semi-colon: 471f378eab4c
746 770 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
771 | map: 471f378eab4c5e25f6c77f785b27c936efb22874
747 772 | @ 471f378eab4c
748 773 |/
749 774 o ea207398892e
750 775
751 776 $ hg up 'desc(A2)'
752 777 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
753 778
754 779 Predecessors template should show no predecessors as they are non visible
755 780 $ hg tlog
756 781 @ 7a230b46bf61
757 782 |
758 783 o ea207398892e
759 784
760 785 Predecessors template should show all predecessors as we force their display
761 786 with --hidden
762 787 $ hg tlog --hidden
763 788 @ 7a230b46bf61
764 789 | Predecessors: 471f378eab4c
765 790 | semi-colon: 471f378eab4c
766 791 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
792 | map: 471f378eab4c5e25f6c77f785b27c936efb22874
767 793 | x 471f378eab4c
768 794 |/
769 795 o ea207398892e
770 796
771 797
772 798 Test template with obsmarkers cycle
773 799 ===================================
774 800
775 801 Test setup
776 802 ----------
777 803
778 804 $ hg init $TESTTMP/templates-local-cycle
779 805 $ cd $TESTTMP/templates-local-cycle
780 806 $ mkcommit ROOT
781 807 $ mkcommit A0
782 808 $ mkcommit B0
783 809 $ hg up -r 0
784 810 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
785 811 $ mkcommit C0
786 812 created new head
787 813
788 814 Create the cycle
789 815
790 816 $ hg debugobsolete `getid "desc(A0)"` `getid "desc(B0)"`
791 817 $ hg debugobsolete `getid "desc(B0)"` `getid "desc(C0)"`
792 818 $ hg debugobsolete `getid "desc(B0)"` `getid "desc(A0)"`
793 819
794 820 Check templates
795 821 ---------------
796 822
797 823 $ hg tlog
798 824 @ f897c6137566
799 825 |
800 826 o ea207398892e
801 827
802 828
803 829 $ hg up -r "desc(B0)" --hidden
804 830 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
805 831 $ hg tlog
806 832 o f897c6137566
807 833 | Predecessors: 0dec01379d3b
808 834 | semi-colon: 0dec01379d3b
809 835 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
836 | map: 0dec01379d3be6318c470ead31b1fe7ae7cb53d5
810 837 | @ 0dec01379d3b
811 838 | | Predecessors: 471f378eab4c
812 839 | | semi-colon: 471f378eab4c
813 840 | | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
841 | | map: 471f378eab4c5e25f6c77f785b27c936efb22874
814 842 | x 471f378eab4c
815 843 |/ Predecessors: 0dec01379d3b
816 844 | semi-colon: 0dec01379d3b
817 845 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
846 | map: 0dec01379d3be6318c470ead31b1fe7ae7cb53d5
818 847 o ea207398892e
819 848
820 849
821 850 $ hg up -r "desc(A0)" --hidden
822 851 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
823 852 $ hg tlog
824 853 o f897c6137566
825 854 | Predecessors: 471f378eab4c
826 855 | semi-colon: 471f378eab4c
827 856 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
857 | map: 471f378eab4c5e25f6c77f785b27c936efb22874
828 858 | @ 471f378eab4c
829 859 |/
830 860 o ea207398892e
831 861
832 862
833 863 $ hg up -r "desc(ROOT)" --hidden
834 864 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
835 865 $ hg tlog
836 866 o f897c6137566
837 867 |
838 868 @ ea207398892e
839 869
840 870
841 871 $ hg tlog --hidden
842 872 o f897c6137566
843 873 | Predecessors: 0dec01379d3b
844 874 | semi-colon: 0dec01379d3b
845 875 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
876 | map: 0dec01379d3be6318c470ead31b1fe7ae7cb53d5
846 877 | x 0dec01379d3b
847 878 | | Predecessors: 471f378eab4c
848 879 | | semi-colon: 471f378eab4c
849 880 | | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
881 | | map: 471f378eab4c5e25f6c77f785b27c936efb22874
850 882 | x 471f378eab4c
851 883 |/ Predecessors: 0dec01379d3b
852 884 | semi-colon: 0dec01379d3b
853 885 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
886 | map: 0dec01379d3be6318c470ead31b1fe7ae7cb53d5
854 887 @ ea207398892e
855 888
General Comments 0
You need to be logged in to leave comments. Login now