##// END OF EJS Templates
templatekw: add an "obsolete" keyword...
Denis Laxalde -
r31699:568c4e74 default
parent child Browse files
Show More
@@ -1,630 +1,638 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 .node import hex, nullid
11 11 from . import (
12 12 encoding,
13 13 error,
14 14 hbisect,
15 15 patch,
16 16 registrar,
17 17 scmutil,
18 18 util,
19 19 )
20 20
21 21 # This helper class allows us to handle both:
22 22 # "{files}" (legacy command-line-specific list hack) and
23 23 # "{files % '{file}\n'}" (hgweb-style with inlining and function support)
24 24 # and to access raw values:
25 25 # "{ifcontains(file, files, ...)}", "{ifcontains(key, extras, ...)}"
26 26 # "{get(extras, key)}"
27 27
28 28 class _hybrid(object):
29 29 def __init__(self, gen, values, makemap, joinfmt):
30 30 self.gen = gen
31 31 self.values = values
32 32 self._makemap = makemap
33 33 self.joinfmt = joinfmt
34 34 def __iter__(self):
35 35 return self.gen
36 36 def itermaps(self):
37 37 makemap = self._makemap
38 38 for x in self.values:
39 39 yield makemap(x)
40 40 def __contains__(self, x):
41 41 return x in self.values
42 42 def __len__(self):
43 43 return len(self.values)
44 44 def __getattr__(self, name):
45 45 if name != 'get':
46 46 raise AttributeError(name)
47 47 return getattr(self.values, name)
48 48
49 49 def showlist(name, values, plural=None, element=None, separator=' ', **args):
50 50 if not element:
51 51 element = name
52 52 f = _showlist(name, values, plural, separator, **args)
53 53 return _hybrid(f, values, lambda x: {element: x}, lambda d: d[element])
54 54
55 55 def _showlist(name, values, plural=None, separator=' ', **args):
56 56 '''expand set of values.
57 57 name is name of key in template map.
58 58 values is list of strings or dicts.
59 59 plural is plural of name, if not simply name + 's'.
60 60 separator is used to join values as a string
61 61
62 62 expansion works like this, given name 'foo'.
63 63
64 64 if values is empty, expand 'no_foos'.
65 65
66 66 if 'foo' not in template map, return values as a string,
67 67 joined by 'separator'.
68 68
69 69 expand 'start_foos'.
70 70
71 71 for each value, expand 'foo'. if 'last_foo' in template
72 72 map, expand it instead of 'foo' for last key.
73 73
74 74 expand 'end_foos'.
75 75 '''
76 76 templ = args['templ']
77 77 if plural:
78 78 names = plural
79 79 else: names = name + 's'
80 80 if not values:
81 81 noname = 'no_' + names
82 82 if noname in templ:
83 83 yield templ(noname, **args)
84 84 return
85 85 if name not in templ:
86 86 if isinstance(values[0], str):
87 87 yield separator.join(values)
88 88 else:
89 89 for v in values:
90 90 yield dict(v, **args)
91 91 return
92 92 startname = 'start_' + names
93 93 if startname in templ:
94 94 yield templ(startname, **args)
95 95 vargs = args.copy()
96 96 def one(v, tag=name):
97 97 try:
98 98 vargs.update(v)
99 99 except (AttributeError, ValueError):
100 100 try:
101 101 for a, b in v:
102 102 vargs[a] = b
103 103 except ValueError:
104 104 vargs[name] = v
105 105 return templ(tag, **vargs)
106 106 lastname = 'last_' + name
107 107 if lastname in templ:
108 108 last = values.pop()
109 109 else:
110 110 last = None
111 111 for v in values:
112 112 yield one(v)
113 113 if last is not None:
114 114 yield one(last, tag=lastname)
115 115 endname = 'end_' + names
116 116 if endname in templ:
117 117 yield templ(endname, **args)
118 118
119 119 def _formatrevnode(ctx):
120 120 """Format changeset as '{rev}:{node|formatnode}', which is the default
121 121 template provided by cmdutil.changeset_templater"""
122 122 repo = ctx.repo()
123 123 if repo.ui.debugflag:
124 124 hexnode = ctx.hex()
125 125 else:
126 126 hexnode = ctx.hex()[:12]
127 127 return '%d:%s' % (scmutil.intrev(ctx.rev()), hexnode)
128 128
129 129 def getfiles(repo, ctx, revcache):
130 130 if 'files' not in revcache:
131 131 revcache['files'] = repo.status(ctx.p1(), ctx)[:3]
132 132 return revcache['files']
133 133
134 134 def getlatesttags(repo, ctx, cache, pattern=None):
135 135 '''return date, distance and name for the latest tag of rev'''
136 136
137 137 cachename = 'latesttags'
138 138 if pattern is not None:
139 139 cachename += '-' + pattern
140 140 match = util.stringmatcher(pattern)[2]
141 141 else:
142 142 match = util.always
143 143
144 144 if cachename not in cache:
145 145 # Cache mapping from rev to a tuple with tag date, tag
146 146 # distance and tag name
147 147 cache[cachename] = {-1: (0, 0, ['null'])}
148 148 latesttags = cache[cachename]
149 149
150 150 rev = ctx.rev()
151 151 todo = [rev]
152 152 while todo:
153 153 rev = todo.pop()
154 154 if rev in latesttags:
155 155 continue
156 156 ctx = repo[rev]
157 157 tags = [t for t in ctx.tags()
158 158 if (repo.tagtype(t) and repo.tagtype(t) != 'local'
159 159 and match(t))]
160 160 if tags:
161 161 latesttags[rev] = ctx.date()[0], 0, [t for t in sorted(tags)]
162 162 continue
163 163 try:
164 164 # The tuples are laid out so the right one can be found by
165 165 # comparison.
166 166 pdate, pdist, ptag = max(
167 167 latesttags[p.rev()] for p in ctx.parents())
168 168 except KeyError:
169 169 # Cache miss - recurse
170 170 todo.append(rev)
171 171 todo.extend(p.rev() for p in ctx.parents())
172 172 continue
173 173 latesttags[rev] = pdate, pdist + 1, ptag
174 174 return latesttags[rev]
175 175
176 176 def getrenamedfn(repo, endrev=None):
177 177 rcache = {}
178 178 if endrev is None:
179 179 endrev = len(repo)
180 180
181 181 def getrenamed(fn, rev):
182 182 '''looks up all renames for a file (up to endrev) the first
183 183 time the file is given. It indexes on the changerev and only
184 184 parses the manifest if linkrev != changerev.
185 185 Returns rename info for fn at changerev rev.'''
186 186 if fn not in rcache:
187 187 rcache[fn] = {}
188 188 fl = repo.file(fn)
189 189 for i in fl:
190 190 lr = fl.linkrev(i)
191 191 renamed = fl.renamed(fl.node(i))
192 192 rcache[fn][lr] = renamed
193 193 if lr >= endrev:
194 194 break
195 195 if rev in rcache[fn]:
196 196 return rcache[fn][rev]
197 197
198 198 # If linkrev != rev (i.e. rev not found in rcache) fallback to
199 199 # filectx logic.
200 200 try:
201 201 return repo[rev][fn].renamed()
202 202 except error.LookupError:
203 203 return None
204 204
205 205 return getrenamed
206 206
207 207 # default templates internally used for rendering of lists
208 208 defaulttempl = {
209 209 'parent': '{rev}:{node|formatnode} ',
210 210 'manifest': '{rev}:{node|formatnode}',
211 211 'file_copy': '{name} ({source})',
212 212 'envvar': '{key}={value}',
213 213 'extra': '{key}={value|stringescape}'
214 214 }
215 215 # filecopy is preserved for compatibility reasons
216 216 defaulttempl['filecopy'] = defaulttempl['file_copy']
217 217
218 218 # keywords are callables like:
219 219 # fn(repo, ctx, templ, cache, revcache, **args)
220 220 # with:
221 221 # repo - current repository instance
222 222 # ctx - the changectx being displayed
223 223 # templ - the templater instance
224 224 # cache - a cache dictionary for the whole templater run
225 225 # revcache - a cache dictionary for the current revision
226 226 keywords = {}
227 227
228 228 templatekeyword = registrar.templatekeyword(keywords)
229 229
230 230 @templatekeyword('author')
231 231 def showauthor(repo, ctx, templ, **args):
232 232 """String. The unmodified author of the changeset."""
233 233 return ctx.user()
234 234
235 235 @templatekeyword('bisect')
236 236 def showbisect(repo, ctx, templ, **args):
237 237 """String. The changeset bisection status."""
238 238 return hbisect.label(repo, ctx.node())
239 239
240 240 @templatekeyword('branch')
241 241 def showbranch(**args):
242 242 """String. The name of the branch on which the changeset was
243 243 committed.
244 244 """
245 245 return args['ctx'].branch()
246 246
247 247 @templatekeyword('branches')
248 248 def showbranches(**args):
249 249 """List of strings. The name of the branch on which the
250 250 changeset was committed. Will be empty if the branch name was
251 251 default. (DEPRECATED)
252 252 """
253 253 branch = args['ctx'].branch()
254 254 if branch != 'default':
255 255 return showlist('branch', [branch], plural='branches', **args)
256 256 return showlist('branch', [], plural='branches', **args)
257 257
258 258 @templatekeyword('bookmarks')
259 259 def showbookmarks(**args):
260 260 """List of strings. Any bookmarks associated with the
261 261 changeset. Also sets 'active', the name of the active bookmark.
262 262 """
263 263 repo = args['ctx']._repo
264 264 bookmarks = args['ctx'].bookmarks()
265 265 active = repo._activebookmark
266 266 makemap = lambda v: {'bookmark': v, 'active': active, 'current': active}
267 267 f = _showlist('bookmark', bookmarks, **args)
268 268 return _hybrid(f, bookmarks, makemap, lambda x: x['bookmark'])
269 269
270 270 @templatekeyword('children')
271 271 def showchildren(**args):
272 272 """List of strings. The children of the changeset."""
273 273 ctx = args['ctx']
274 274 childrevs = ['%d:%s' % (cctx, cctx) for cctx in ctx.children()]
275 275 return showlist('children', childrevs, element='child', **args)
276 276
277 277 # Deprecated, but kept alive for help generation a purpose.
278 278 @templatekeyword('currentbookmark')
279 279 def showcurrentbookmark(**args):
280 280 """String. The active bookmark, if it is
281 281 associated with the changeset (DEPRECATED)"""
282 282 return showactivebookmark(**args)
283 283
284 284 @templatekeyword('activebookmark')
285 285 def showactivebookmark(**args):
286 286 """String. The active bookmark, if it is
287 287 associated with the changeset"""
288 288 active = args['repo']._activebookmark
289 289 if active and active in args['ctx'].bookmarks():
290 290 return active
291 291 return ''
292 292
293 293 @templatekeyword('date')
294 294 def showdate(repo, ctx, templ, **args):
295 295 """Date information. The date when the changeset was committed."""
296 296 return ctx.date()
297 297
298 298 @templatekeyword('desc')
299 299 def showdescription(repo, ctx, templ, **args):
300 300 """String. The text of the changeset description."""
301 301 s = ctx.description()
302 302 if isinstance(s, encoding.localstr):
303 303 # try hard to preserve utf-8 bytes
304 304 return encoding.tolocal(encoding.fromlocal(s).strip())
305 305 else:
306 306 return s.strip()
307 307
308 308 @templatekeyword('diffstat')
309 309 def showdiffstat(repo, ctx, templ, **args):
310 310 """String. Statistics of changes with the following format:
311 311 "modified files: +added/-removed lines"
312 312 """
313 313 stats = patch.diffstatdata(util.iterlines(ctx.diff(noprefix=False)))
314 314 maxname, maxtotal, adds, removes, binary = patch.diffstatsum(stats)
315 315 return '%s: +%s/-%s' % (len(stats), adds, removes)
316 316
317 317 @templatekeyword('envvars')
318 318 def showenvvars(repo, **args):
319 319 """A dictionary of environment variables. (EXPERIMENTAL)"""
320 320
321 321 env = repo.ui.exportableenviron()
322 322 env = util.sortdict((k, env[k]) for k in sorted(env))
323 323 makemap = lambda k: {'key': k, 'value': env[k]}
324 324 c = [makemap(k) for k in env]
325 325 f = _showlist('envvar', c, plural='envvars', **args)
326 326 return _hybrid(f, env, makemap,
327 327 lambda x: '%s=%s' % (x['key'], x['value']))
328 328
329 329 @templatekeyword('extras')
330 330 def showextras(**args):
331 331 """List of dicts with key, value entries of the 'extras'
332 332 field of this changeset."""
333 333 extras = args['ctx'].extra()
334 334 extras = util.sortdict((k, extras[k]) for k in sorted(extras))
335 335 makemap = lambda k: {'key': k, 'value': extras[k]}
336 336 c = [makemap(k) for k in extras]
337 337 f = _showlist('extra', c, plural='extras', **args)
338 338 return _hybrid(f, extras, makemap,
339 339 lambda x: '%s=%s' % (x['key'], util.escapestr(x['value'])))
340 340
341 341 @templatekeyword('file_adds')
342 342 def showfileadds(**args):
343 343 """List of strings. Files added by this changeset."""
344 344 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
345 345 return showlist('file_add', getfiles(repo, ctx, revcache)[1],
346 346 element='file', **args)
347 347
348 348 @templatekeyword('file_copies')
349 349 def showfilecopies(**args):
350 350 """List of strings. Files copied in this changeset with
351 351 their sources.
352 352 """
353 353 cache, ctx = args['cache'], args['ctx']
354 354 copies = args['revcache'].get('copies')
355 355 if copies is None:
356 356 if 'getrenamed' not in cache:
357 357 cache['getrenamed'] = getrenamedfn(args['repo'])
358 358 copies = []
359 359 getrenamed = cache['getrenamed']
360 360 for fn in ctx.files():
361 361 rename = getrenamed(fn, ctx.rev())
362 362 if rename:
363 363 copies.append((fn, rename[0]))
364 364
365 365 copies = util.sortdict(copies)
366 366 makemap = lambda k: {'name': k, 'source': copies[k]}
367 367 c = [makemap(k) for k in copies]
368 368 f = _showlist('file_copy', c, plural='file_copies', **args)
369 369 return _hybrid(f, copies, makemap,
370 370 lambda x: '%s (%s)' % (x['name'], x['source']))
371 371
372 372 # showfilecopiesswitch() displays file copies only if copy records are
373 373 # provided before calling the templater, usually with a --copies
374 374 # command line switch.
375 375 @templatekeyword('file_copies_switch')
376 376 def showfilecopiesswitch(**args):
377 377 """List of strings. Like "file_copies" but displayed
378 378 only if the --copied switch is set.
379 379 """
380 380 copies = args['revcache'].get('copies') or []
381 381 copies = util.sortdict(copies)
382 382 makemap = lambda k: {'name': k, 'source': copies[k]}
383 383 c = [makemap(k) for k in copies]
384 384 f = _showlist('file_copy', c, plural='file_copies', **args)
385 385 return _hybrid(f, copies, makemap,
386 386 lambda x: '%s (%s)' % (x['name'], x['source']))
387 387
388 388 @templatekeyword('file_dels')
389 389 def showfiledels(**args):
390 390 """List of strings. Files removed by this changeset."""
391 391 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
392 392 return showlist('file_del', getfiles(repo, ctx, revcache)[2],
393 393 element='file', **args)
394 394
395 395 @templatekeyword('file_mods')
396 396 def showfilemods(**args):
397 397 """List of strings. Files modified by this changeset."""
398 398 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
399 399 return showlist('file_mod', getfiles(repo, ctx, revcache)[0],
400 400 element='file', **args)
401 401
402 402 @templatekeyword('files')
403 403 def showfiles(**args):
404 404 """List of strings. All files modified, added, or removed by this
405 405 changeset.
406 406 """
407 407 return showlist('file', args['ctx'].files(), **args)
408 408
409 409 @templatekeyword('graphnode')
410 410 def showgraphnode(repo, ctx, **args):
411 411 """String. The character representing the changeset node in
412 412 an ASCII revision graph"""
413 413 wpnodes = repo.dirstate.parents()
414 414 if wpnodes[1] == nullid:
415 415 wpnodes = wpnodes[:1]
416 416 if ctx.node() in wpnodes:
417 417 return '@'
418 418 elif ctx.obsolete():
419 419 return 'x'
420 420 elif ctx.closesbranch():
421 421 return '_'
422 422 else:
423 423 return 'o'
424 424
425 425 @templatekeyword('latesttag')
426 426 def showlatesttag(**args):
427 427 """List of strings. The global tags on the most recent globally
428 428 tagged ancestor of this changeset.
429 429 """
430 430 return showlatesttags(None, **args)
431 431
432 432 def showlatesttags(pattern, **args):
433 433 """helper method for the latesttag keyword and function"""
434 434 repo, ctx = args['repo'], args['ctx']
435 435 cache = args['cache']
436 436 latesttags = getlatesttags(repo, ctx, cache, pattern)
437 437
438 438 # latesttag[0] is an implementation detail for sorting csets on different
439 439 # branches in a stable manner- it is the date the tagged cset was created,
440 440 # not the date the tag was created. Therefore it isn't made visible here.
441 441 makemap = lambda v: {
442 442 'changes': _showchangessincetag,
443 443 'distance': latesttags[1],
444 444 'latesttag': v, # BC with {latesttag % '{latesttag}'}
445 445 'tag': v
446 446 }
447 447
448 448 tags = latesttags[2]
449 449 f = _showlist('latesttag', tags, separator=':', **args)
450 450 return _hybrid(f, tags, makemap, lambda x: x['latesttag'])
451 451
452 452 @templatekeyword('latesttagdistance')
453 453 def showlatesttagdistance(repo, ctx, templ, cache, **args):
454 454 """Integer. Longest path to the latest tag."""
455 455 return getlatesttags(repo, ctx, cache)[1]
456 456
457 457 @templatekeyword('changessincelatesttag')
458 458 def showchangessincelatesttag(repo, ctx, templ, cache, **args):
459 459 """Integer. All ancestors not in the latest tag."""
460 460 latesttag = getlatesttags(repo, ctx, cache)[2][0]
461 461
462 462 return _showchangessincetag(repo, ctx, tag=latesttag, **args)
463 463
464 464 def _showchangessincetag(repo, ctx, **args):
465 465 offset = 0
466 466 revs = [ctx.rev()]
467 467 tag = args['tag']
468 468
469 469 # The only() revset doesn't currently support wdir()
470 470 if ctx.rev() is None:
471 471 offset = 1
472 472 revs = [p.rev() for p in ctx.parents()]
473 473
474 474 return len(repo.revs('only(%ld, %s)', revs, tag)) + offset
475 475
476 476 @templatekeyword('manifest')
477 477 def showmanifest(**args):
478 478 repo, ctx, templ = args['repo'], args['ctx'], args['templ']
479 479 mnode = ctx.manifestnode()
480 480 if mnode is None:
481 481 # just avoid crash, we might want to use the 'ff...' hash in future
482 482 return
483 483 args = args.copy()
484 484 args.update({'rev': repo.manifestlog._revlog.rev(mnode),
485 485 'node': hex(mnode)})
486 486 return templ('manifest', **args)
487 487
488 488 def shownames(namespace, **args):
489 489 """helper method to generate a template keyword for a namespace"""
490 490 ctx = args['ctx']
491 491 repo = ctx.repo()
492 492 ns = repo.names[namespace]
493 493 names = ns.names(repo, ctx.node())
494 494 return showlist(ns.templatename, names, plural=namespace, **args)
495 495
496 496 @templatekeyword('namespaces')
497 497 def shownamespaces(**args):
498 498 """Dict of lists. Names attached to this changeset per
499 499 namespace."""
500 500 ctx = args['ctx']
501 501 repo = ctx.repo()
502 502 namespaces = util.sortdict((k, showlist('name', ns.names(repo, ctx.node()),
503 503 **args))
504 504 for k, ns in repo.names.iteritems())
505 505 f = _showlist('namespace', list(namespaces), **args)
506 506 return _hybrid(f, namespaces,
507 507 lambda k: {'namespace': k, 'names': namespaces[k]},
508 508 lambda x: x['namespace'])
509 509
510 510 @templatekeyword('node')
511 511 def shownode(repo, ctx, templ, **args):
512 512 """String. The changeset identification hash, as a 40 hexadecimal
513 513 digit string.
514 514 """
515 515 return ctx.hex()
516 516
517 @templatekeyword('obsolete')
518 def showobsolete(repo, ctx, templ, **args):
519 """String. Whether the changeset is obsolete.
520 """
521 if ctx.obsolete():
522 return 'obsolete'
523 return ''
524
517 525 @templatekeyword('p1rev')
518 526 def showp1rev(repo, ctx, templ, **args):
519 527 """Integer. The repository-local revision number of the changeset's
520 528 first parent, or -1 if the changeset has no parents."""
521 529 return ctx.p1().rev()
522 530
523 531 @templatekeyword('p2rev')
524 532 def showp2rev(repo, ctx, templ, **args):
525 533 """Integer. The repository-local revision number of the changeset's
526 534 second parent, or -1 if the changeset has no second parent."""
527 535 return ctx.p2().rev()
528 536
529 537 @templatekeyword('p1node')
530 538 def showp1node(repo, ctx, templ, **args):
531 539 """String. The identification hash of the changeset's first parent,
532 540 as a 40 digit hexadecimal string. If the changeset has no parents, all
533 541 digits are 0."""
534 542 return ctx.p1().hex()
535 543
536 544 @templatekeyword('p2node')
537 545 def showp2node(repo, ctx, templ, **args):
538 546 """String. The identification hash of the changeset's second
539 547 parent, as a 40 digit hexadecimal string. If the changeset has no second
540 548 parent, all digits are 0."""
541 549 return ctx.p2().hex()
542 550
543 551 @templatekeyword('parents')
544 552 def showparents(**args):
545 553 """List of strings. The parents of the changeset in "rev:node"
546 554 format. If the changeset has only one "natural" parent (the predecessor
547 555 revision) nothing is shown."""
548 556 repo = args['repo']
549 557 ctx = args['ctx']
550 558 pctxs = scmutil.meaningfulparents(repo, ctx)
551 559 prevs = [str(p.rev()) for p in pctxs] # ifcontains() needs a list of str
552 560 parents = [[('rev', p.rev()),
553 561 ('node', p.hex()),
554 562 ('phase', p.phasestr())]
555 563 for p in pctxs]
556 564 f = _showlist('parent', parents, **args)
557 565 return _hybrid(f, prevs, lambda x: {'ctx': repo[int(x)], 'revcache': {}},
558 566 lambda d: _formatrevnode(d['ctx']))
559 567
560 568 @templatekeyword('phase')
561 569 def showphase(repo, ctx, templ, **args):
562 570 """String. The changeset phase name."""
563 571 return ctx.phasestr()
564 572
565 573 @templatekeyword('phaseidx')
566 574 def showphaseidx(repo, ctx, templ, **args):
567 575 """Integer. The changeset phase index."""
568 576 return ctx.phase()
569 577
570 578 @templatekeyword('rev')
571 579 def showrev(repo, ctx, templ, **args):
572 580 """Integer. The repository-local changeset revision number."""
573 581 return scmutil.intrev(ctx.rev())
574 582
575 583 def showrevslist(name, revs, **args):
576 584 """helper to generate a list of revisions in which a mapped template will
577 585 be evaluated"""
578 586 repo = args['ctx'].repo()
579 587 revs = [str(r) for r in revs] # ifcontains() needs a list of str
580 588 f = _showlist(name, revs, **args)
581 589 return _hybrid(f, revs,
582 590 lambda x: {name: x, 'ctx': repo[int(x)], 'revcache': {}},
583 591 lambda d: d[name])
584 592
585 593 @templatekeyword('subrepos')
586 594 def showsubrepos(**args):
587 595 """List of strings. Updated subrepositories in the changeset."""
588 596 ctx = args['ctx']
589 597 substate = ctx.substate
590 598 if not substate:
591 599 return showlist('subrepo', [], **args)
592 600 psubstate = ctx.parents()[0].substate or {}
593 601 subrepos = []
594 602 for sub in substate:
595 603 if sub not in psubstate or substate[sub] != psubstate[sub]:
596 604 subrepos.append(sub) # modified or newly added in ctx
597 605 for sub in psubstate:
598 606 if sub not in substate:
599 607 subrepos.append(sub) # removed in ctx
600 608 return showlist('subrepo', sorted(subrepos), **args)
601 609
602 610 # don't remove "showtags" definition, even though namespaces will put
603 611 # a helper function for "tags" keyword into "keywords" map automatically,
604 612 # because online help text is built without namespaces initialization
605 613 @templatekeyword('tags')
606 614 def showtags(**args):
607 615 """List of strings. Any tags associated with the changeset."""
608 616 return shownames('tags', **args)
609 617
610 618 def loadkeyword(ui, extname, registrarobj):
611 619 """Load template keyword from specified registrarobj
612 620 """
613 621 for name, func in registrarobj._table.iteritems():
614 622 keywords[name] = func
615 623
616 624 @templatekeyword('termwidth')
617 625 def termwidth(repo, ctx, templ, **args):
618 626 """Integer. The width of the current terminal."""
619 627 return repo.ui.termwidth()
620 628
621 629 @templatekeyword('troubles')
622 630 def showtroubles(**args):
623 631 """List of strings. Evolution troubles affecting the changeset.
624 632
625 633 (EXPERIMENTAL)
626 634 """
627 635 return showlist('trouble', args['ctx'].troubles(), **args)
628 636
629 637 # tell hggettext to extract docstrings from these functions:
630 638 i18nfunctions = keywords.values()
@@ -1,1261 +1,1266 b''
1 1 $ cat >> $HGRCPATH << EOF
2 2 > [phases]
3 3 > # public changeset are not obsolete
4 4 > publish=false
5 5 > [ui]
6 > logtemplate="{rev}:{node|short} ({phase}{if(troubles, ' {troubles}')}) [{tags} {bookmarks}] {desc|firstline}\n"
6 > logtemplate="{rev}:{node|short} ({phase}{if(obsolete, ' *{obsolete}*')}{if(troubles, ' {troubles}')}) [{tags} {bookmarks}] {desc|firstline}\n"
7 7 > EOF
8 8 $ mkcommit() {
9 9 > echo "$1" > "$1"
10 10 > hg add "$1"
11 11 > hg ci -m "add $1"
12 12 > }
13 13 $ getid() {
14 14 > hg log -T "{node}\n" --hidden -r "desc('$1')"
15 15 > }
16 16
17 17 $ cat > debugkeys.py <<EOF
18 18 > def reposetup(ui, repo):
19 19 > class debugkeysrepo(repo.__class__):
20 20 > def listkeys(self, namespace):
21 21 > ui.write('listkeys %s\n' % (namespace,))
22 22 > return super(debugkeysrepo, self).listkeys(namespace)
23 23 >
24 24 > if repo.local():
25 25 > repo.__class__ = debugkeysrepo
26 26 > EOF
27 27
28 28 $ hg init tmpa
29 29 $ cd tmpa
30 30 $ mkcommit kill_me
31 31
32 32 Checking that the feature is properly disabled
33 33
34 34 $ hg debugobsolete -d '0 0' `getid kill_me` -u babar
35 35 abort: creating obsolete markers is not enabled on this repo
36 36 [255]
37 37
38 38 Enabling it
39 39
40 40 $ cat >> $HGRCPATH << EOF
41 41 > [experimental]
42 42 > evolution=createmarkers,exchange
43 43 > EOF
44 44
45 45 Killing a single changeset without replacement
46 46
47 47 $ hg debugobsolete 0
48 48 abort: changeset references must be full hexadecimal node identifiers
49 49 [255]
50 50 $ hg debugobsolete '00'
51 51 abort: changeset references must be full hexadecimal node identifiers
52 52 [255]
53 53 $ hg debugobsolete -d '0 0' `getid kill_me` -u babar
54 54 $ hg debugobsolete
55 55 97b7c2d76b1845ed3eb988cd612611e72406cef0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'babar'}
56 56
57 57 (test that mercurial is not confused)
58 58
59 59 $ hg up null --quiet # having 0 as parent prevents it to be hidden
60 60 $ hg tip
61 61 -1:000000000000 (public) [tip ]
62 62 $ hg up --hidden tip --quiet
63 63
64 64 Killing a single changeset with itself should fail
65 65 (simple local safeguard)
66 66
67 67 $ hg debugobsolete `getid kill_me` `getid kill_me`
68 68 abort: bad obsmarker input: in-marker cycle with 97b7c2d76b1845ed3eb988cd612611e72406cef0
69 69 [255]
70 70
71 71 $ cd ..
72 72
73 73 Killing a single changeset with replacement
74 74 (and testing the format option)
75 75
76 76 $ hg init tmpb
77 77 $ cd tmpb
78 78 $ mkcommit a
79 79 $ mkcommit b
80 80 $ mkcommit original_c
81 81 $ hg up "desc('b')"
82 82 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
83 83 $ mkcommit new_c
84 84 created new head
85 85 $ hg log -r 'hidden()' --template '{rev}:{node|short} {desc}\n' --hidden
86 86 $ hg debugobsolete --config format.obsstore-version=0 --flag 12 `getid original_c` `getid new_c` -d '121 120'
87 87 $ hg log -r 'hidden()' --template '{rev}:{node|short} {desc}\n' --hidden
88 88 2:245bde4270cd add original_c
89 89 $ hg debugrevlog -cd
90 90 # rev p1rev p2rev start end deltastart base p1 p2 rawsize totalsize compression heads chainlen
91 91 0 -1 -1 0 59 0 0 0 0 58 58 0 1 0
92 92 1 0 -1 59 118 59 59 0 0 58 116 0 1 0
93 93 2 1 -1 118 193 118 118 59 0 76 192 0 1 0
94 94 3 1 -1 193 260 193 193 59 0 66 258 0 2 0
95 95 $ hg debugobsolete
96 96 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
97 97
98 98 (check for version number of the obsstore)
99 99
100 100 $ dd bs=1 count=1 if=.hg/store/obsstore 2>/dev/null
101 101 \x00 (no-eol) (esc)
102 102
103 103 do it again (it read the obsstore before adding new changeset)
104 104
105 105 $ hg up '.^'
106 106 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
107 107 $ mkcommit new_2_c
108 108 created new head
109 109 $ hg debugobsolete -d '1337 0' `getid new_c` `getid new_2_c`
110 110 $ hg debugobsolete
111 111 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
112 112 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
113 113
114 114 Register two markers with a missing node
115 115
116 116 $ hg up '.^'
117 117 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
118 118 $ mkcommit new_3_c
119 119 created new head
120 120 $ hg debugobsolete -d '1338 0' `getid new_2_c` 1337133713371337133713371337133713371337
121 121 $ hg debugobsolete -d '1339 0' 1337133713371337133713371337133713371337 `getid new_3_c`
122 122 $ hg debugobsolete
123 123 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
124 124 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
125 125 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
126 126 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
127 127
128 128 Test the --index option of debugobsolete command
129 129 $ hg debugobsolete --index
130 130 0 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
131 131 1 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
132 132 2 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
133 133 3 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
134 134
135 135 Refuse pathological nullid successors
136 136 $ hg debugobsolete -d '9001 0' 1337133713371337133713371337133713371337 0000000000000000000000000000000000000000
137 137 transaction abort!
138 138 rollback completed
139 139 abort: bad obsolescence marker detected: invalid successors nullid
140 140 [255]
141 141
142 142 Check that graphlog detect that a changeset is obsolete:
143 143
144 144 $ hg log -G
145 145 @ 5:5601fb93a350 (draft) [tip ] add new_3_c
146 146 |
147 147 o 1:7c3bad9141dc (draft) [ ] add b
148 148 |
149 149 o 0:1f0dee641bb7 (draft) [ ] add a
150 150
151 151
152 152 check that heads does not report them
153 153
154 154 $ hg heads
155 155 5:5601fb93a350 (draft) [tip ] add new_3_c
156 156 $ hg heads --hidden
157 157 5:5601fb93a350 (draft) [tip ] add new_3_c
158 4:ca819180edb9 (draft) [ ] add new_2_c
159 3:cdbce2fbb163 (draft) [ ] add new_c
160 2:245bde4270cd (draft) [ ] add original_c
158 4:ca819180edb9 (draft *obsolete*) [ ] add new_2_c
159 3:cdbce2fbb163 (draft *obsolete*) [ ] add new_c
160 2:245bde4270cd (draft *obsolete*) [ ] add original_c
161 161
162 162
163 163 check that summary does not report them
164 164
165 165 $ hg init ../sink
166 166 $ echo '[paths]' >> .hg/hgrc
167 167 $ echo 'default=../sink' >> .hg/hgrc
168 168 $ hg summary --remote
169 169 parent: 5:5601fb93a350 tip
170 170 add new_3_c
171 171 branch: default
172 172 commit: (clean)
173 173 update: (current)
174 174 phases: 3 draft
175 175 remote: 3 outgoing
176 176
177 177 $ hg summary --remote --hidden
178 178 parent: 5:5601fb93a350 tip
179 179 add new_3_c
180 180 branch: default
181 181 commit: (clean)
182 182 update: 3 new changesets, 4 branch heads (merge)
183 183 phases: 6 draft
184 184 remote: 3 outgoing
185 185
186 186 check that various commands work well with filtering
187 187
188 188 $ hg tip
189 189 5:5601fb93a350 (draft) [tip ] add new_3_c
190 190 $ hg log -r 6
191 191 abort: unknown revision '6'!
192 192 [255]
193 193 $ hg log -r 4
194 194 abort: hidden revision '4'!
195 195 (use --hidden to access hidden revisions)
196 196 [255]
197 197 $ hg debugrevspec 'rev(6)'
198 198 $ hg debugrevspec 'rev(4)'
199 199 $ hg debugrevspec 'null'
200 200 -1
201 201
202 202 Check that public changeset are not accounted as obsolete:
203 203
204 204 $ hg --hidden phase --public 2
205 205 $ hg log -G
206 206 @ 5:5601fb93a350 (draft bumped) [tip ] add new_3_c
207 207 |
208 208 | o 2:245bde4270cd (public) [ ] add original_c
209 209 |/
210 210 o 1:7c3bad9141dc (public) [ ] add b
211 211 |
212 212 o 0:1f0dee641bb7 (public) [ ] add a
213 213
214 214
215 215 And that bumped changeset are detected
216 216 --------------------------------------
217 217
218 218 If we didn't filtered obsolete changesets out, 3 and 4 would show up too. Also
219 219 note that the bumped changeset (5:5601fb93a350) is not a direct successor of
220 220 the public changeset
221 221
222 222 $ hg log --hidden -r 'bumped()'
223 223 5:5601fb93a350 (draft bumped) [tip ] add new_3_c
224 224
225 225 And that we can't push bumped changeset
226 226
227 227 $ hg push ../tmpa -r 0 --force #(make repo related)
228 228 pushing to ../tmpa
229 229 searching for changes
230 230 warning: repository is unrelated
231 231 adding changesets
232 232 adding manifests
233 233 adding file changes
234 234 added 1 changesets with 1 changes to 1 files (+1 heads)
235 235 $ hg push ../tmpa
236 236 pushing to ../tmpa
237 237 searching for changes
238 238 abort: push includes bumped changeset: 5601fb93a350!
239 239 [255]
240 240
241 241 Fixing "bumped" situation
242 242 We need to create a clone of 5 and add a special marker with a flag
243 243
244 244 $ hg summary
245 245 parent: 5:5601fb93a350 tip (bumped)
246 246 add new_3_c
247 247 branch: default
248 248 commit: (clean)
249 249 update: 1 new changesets, 2 branch heads (merge)
250 250 phases: 1 draft
251 251 bumped: 1 changesets
252 252 $ hg up '5^'
253 253 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
254 254 $ hg revert -ar 5
255 255 adding new_3_c
256 256 $ hg ci -m 'add n3w_3_c'
257 257 created new head
258 258 $ hg debugobsolete -d '1338 0' --flags 1 `getid new_3_c` `getid n3w_3_c`
259 259 $ hg log -r 'bumped()'
260 260 $ hg log -G
261 261 @ 6:6f9641995072 (draft) [tip ] add n3w_3_c
262 262 |
263 263 | o 2:245bde4270cd (public) [ ] add original_c
264 264 |/
265 265 o 1:7c3bad9141dc (public) [ ] add b
266 266 |
267 267 o 0:1f0dee641bb7 (public) [ ] add a
268 268
269 269
270 270 $ cd ..
271 271
272 272 Revision 0 is hidden
273 273 --------------------
274 274
275 275 $ hg init rev0hidden
276 276 $ cd rev0hidden
277 277
278 278 $ mkcommit kill0
279 279 $ hg up -q null
280 280 $ hg debugobsolete `getid kill0`
281 281 $ mkcommit a
282 282 $ mkcommit b
283 283
284 284 Should pick the first visible revision as "repo" node
285 285
286 286 $ hg archive ../archive-null
287 287 $ cat ../archive-null/.hg_archival.txt
288 288 repo: 1f0dee641bb7258c56bd60e93edfa2405381c41e
289 289 node: 7c3bad9141dcb46ff89abf5f61856facd56e476c
290 290 branch: default
291 291 latesttag: null
292 292 latesttagdistance: 2
293 293 changessincelatesttag: 2
294 294
295 295
296 296 $ cd ..
297 297
298 298 Exchange Test
299 299 ============================
300 300
301 301 Destination repo does not have any data
302 302 ---------------------------------------
303 303
304 304 Simple incoming test
305 305
306 306 $ hg init tmpc
307 307 $ cd tmpc
308 308 $ hg incoming ../tmpb
309 309 comparing with ../tmpb
310 310 0:1f0dee641bb7 (public) [ ] add a
311 311 1:7c3bad9141dc (public) [ ] add b
312 312 2:245bde4270cd (public) [ ] add original_c
313 313 6:6f9641995072 (draft) [tip ] add n3w_3_c
314 314
315 315 Try to pull markers
316 316 (extinct changeset are excluded but marker are pushed)
317 317
318 318 $ hg pull ../tmpb
319 319 pulling from ../tmpb
320 320 requesting all changes
321 321 adding changesets
322 322 adding manifests
323 323 adding file changes
324 324 added 4 changesets with 4 changes to 4 files (+1 heads)
325 325 5 new obsolescence markers
326 326 (run 'hg heads' to see heads, 'hg merge' to merge)
327 327 $ hg debugobsolete
328 328 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
329 329 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
330 330 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
331 331 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
332 332 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
333 333
334 334 Rollback//Transaction support
335 335
336 336 $ hg debugobsolete -d '1340 0' aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
337 337 $ hg debugobsolete
338 338 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
339 339 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
340 340 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
341 341 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
342 342 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
343 343 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 0 (Thu Jan 01 00:22:20 1970 +0000) {'user': 'test'}
344 344 $ hg rollback -n
345 345 repository tip rolled back to revision 3 (undo debugobsolete)
346 346 $ hg rollback
347 347 repository tip rolled back to revision 3 (undo debugobsolete)
348 348 $ hg debugobsolete
349 349 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
350 350 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
351 351 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
352 352 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
353 353 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
354 354
355 355 $ cd ..
356 356
357 357 Try to push markers
358 358
359 359 $ hg init tmpd
360 360 $ hg -R tmpb push tmpd
361 361 pushing to tmpd
362 362 searching for changes
363 363 adding changesets
364 364 adding manifests
365 365 adding file changes
366 366 added 4 changesets with 4 changes to 4 files (+1 heads)
367 367 5 new obsolescence markers
368 368 $ hg -R tmpd debugobsolete | sort
369 369 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
370 370 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
371 371 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
372 372 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
373 373 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
374 374
375 375 Check obsolete keys are exchanged only if source has an obsolete store
376 376
377 377 $ hg init empty
378 378 $ hg --config extensions.debugkeys=debugkeys.py -R empty push tmpd
379 379 pushing to tmpd
380 380 listkeys phases
381 381 listkeys bookmarks
382 382 no changes found
383 383 listkeys phases
384 384 [1]
385 385
386 386 clone support
387 387 (markers are copied and extinct changesets are included to allow hardlinks)
388 388
389 389 $ hg clone tmpb clone-dest
390 390 updating to branch default
391 391 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
392 392 $ hg -R clone-dest log -G --hidden
393 393 @ 6:6f9641995072 (draft) [tip ] add n3w_3_c
394 394 |
395 | x 5:5601fb93a350 (draft) [ ] add new_3_c
395 | x 5:5601fb93a350 (draft *obsolete*) [ ] add new_3_c
396 396 |/
397 | x 4:ca819180edb9 (draft) [ ] add new_2_c
397 | x 4:ca819180edb9 (draft *obsolete*) [ ] add new_2_c
398 398 |/
399 | x 3:cdbce2fbb163 (draft) [ ] add new_c
399 | x 3:cdbce2fbb163 (draft *obsolete*) [ ] add new_c
400 400 |/
401 401 | o 2:245bde4270cd (public) [ ] add original_c
402 402 |/
403 403 o 1:7c3bad9141dc (public) [ ] add b
404 404 |
405 405 o 0:1f0dee641bb7 (public) [ ] add a
406 406
407 407 $ hg -R clone-dest debugobsolete
408 408 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
409 409 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
410 410 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
411 411 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
412 412 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
413 413
414 414
415 415 Destination repo have existing data
416 416 ---------------------------------------
417 417
418 418 On pull
419 419
420 420 $ hg init tmpe
421 421 $ cd tmpe
422 422 $ hg debugobsolete -d '1339 0' 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00
423 423 $ hg pull ../tmpb
424 424 pulling from ../tmpb
425 425 requesting all changes
426 426 adding changesets
427 427 adding manifests
428 428 adding file changes
429 429 added 4 changesets with 4 changes to 4 files (+1 heads)
430 430 5 new obsolescence markers
431 431 (run 'hg heads' to see heads, 'hg merge' to merge)
432 432 $ hg debugobsolete
433 433 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
434 434 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
435 435 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
436 436 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
437 437 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
438 438 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
439 439
440 440
441 441 On push
442 442
443 443 $ hg push ../tmpc
444 444 pushing to ../tmpc
445 445 searching for changes
446 446 no changes found
447 447 1 new obsolescence markers
448 448 [1]
449 449 $ hg -R ../tmpc debugobsolete
450 450 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
451 451 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
452 452 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
453 453 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
454 454 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
455 455 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
456 456
457 457 detect outgoing obsolete and unstable
458 458 ---------------------------------------
459 459
460 460
461 461 $ hg log -G
462 462 o 3:6f9641995072 (draft) [tip ] add n3w_3_c
463 463 |
464 464 | o 2:245bde4270cd (public) [ ] add original_c
465 465 |/
466 466 o 1:7c3bad9141dc (public) [ ] add b
467 467 |
468 468 o 0:1f0dee641bb7 (public) [ ] add a
469 469
470 470 $ hg up 'desc("n3w_3_c")'
471 471 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
472 472 $ mkcommit original_d
473 473 $ mkcommit original_e
474 474 $ hg debugobsolete --record-parents `getid original_d` -d '0 0'
475 475 $ hg debugobsolete | grep `getid original_d`
476 476 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
477 477 $ hg log -r 'obsolete()'
478 4:94b33453f93b (draft) [ ] add original_d
478 4:94b33453f93b (draft *obsolete*) [ ] add original_d
479 479 $ hg summary
480 480 parent: 5:cda648ca50f5 tip (unstable)
481 481 add original_e
482 482 branch: default
483 483 commit: (clean)
484 484 update: 1 new changesets, 2 branch heads (merge)
485 485 phases: 3 draft
486 486 unstable: 1 changesets
487 487 $ hg log -G -r '::unstable()'
488 488 @ 5:cda648ca50f5 (draft unstable) [tip ] add original_e
489 489 |
490 x 4:94b33453f93b (draft) [ ] add original_d
490 x 4:94b33453f93b (draft *obsolete*) [ ] add original_d
491 491 |
492 492 o 3:6f9641995072 (draft) [ ] add n3w_3_c
493 493 |
494 494 o 1:7c3bad9141dc (public) [ ] add b
495 495 |
496 496 o 0:1f0dee641bb7 (public) [ ] add a
497 497
498 498
499 499 refuse to push obsolete changeset
500 500
501 501 $ hg push ../tmpc/ -r 'desc("original_d")'
502 502 pushing to ../tmpc/
503 503 searching for changes
504 504 abort: push includes obsolete changeset: 94b33453f93b!
505 505 [255]
506 506
507 507 refuse to push unstable changeset
508 508
509 509 $ hg push ../tmpc/
510 510 pushing to ../tmpc/
511 511 searching for changes
512 512 abort: push includes unstable changeset: cda648ca50f5!
513 513 [255]
514 514
515 515 Test that extinct changeset are properly detected
516 516
517 517 $ hg log -r 'extinct()'
518 518
519 519 Don't try to push extinct changeset
520 520
521 521 $ hg init ../tmpf
522 522 $ hg out ../tmpf
523 523 comparing with ../tmpf
524 524 searching for changes
525 525 0:1f0dee641bb7 (public) [ ] add a
526 526 1:7c3bad9141dc (public) [ ] add b
527 527 2:245bde4270cd (public) [ ] add original_c
528 528 3:6f9641995072 (draft) [ ] add n3w_3_c
529 4:94b33453f93b (draft) [ ] add original_d
529 4:94b33453f93b (draft *obsolete*) [ ] add original_d
530 530 5:cda648ca50f5 (draft unstable) [tip ] add original_e
531 531 $ hg push ../tmpf -f # -f because be push unstable too
532 532 pushing to ../tmpf
533 533 searching for changes
534 534 adding changesets
535 535 adding manifests
536 536 adding file changes
537 537 added 6 changesets with 6 changes to 6 files (+1 heads)
538 538 7 new obsolescence markers
539 539
540 540 no warning displayed
541 541
542 542 $ hg push ../tmpf
543 543 pushing to ../tmpf
544 544 searching for changes
545 545 no changes found
546 546 [1]
547 547
548 548 Do not warn about new head when the new head is a successors of a remote one
549 549
550 550 $ hg log -G
551 551 @ 5:cda648ca50f5 (draft unstable) [tip ] add original_e
552 552 |
553 x 4:94b33453f93b (draft) [ ] add original_d
553 x 4:94b33453f93b (draft *obsolete*) [ ] add original_d
554 554 |
555 555 o 3:6f9641995072 (draft) [ ] add n3w_3_c
556 556 |
557 557 | o 2:245bde4270cd (public) [ ] add original_c
558 558 |/
559 559 o 1:7c3bad9141dc (public) [ ] add b
560 560 |
561 561 o 0:1f0dee641bb7 (public) [ ] add a
562 562
563 563 $ hg up -q 'desc(n3w_3_c)'
564 564 $ mkcommit obsolete_e
565 565 created new head
566 566 $ hg debugobsolete `getid 'original_e'` `getid 'obsolete_e'`
567 567 $ hg outgoing ../tmpf # parasite hg outgoing testin
568 568 comparing with ../tmpf
569 569 searching for changes
570 570 6:3de5eca88c00 (draft) [tip ] add obsolete_e
571 571 $ hg push ../tmpf
572 572 pushing to ../tmpf
573 573 searching for changes
574 574 adding changesets
575 575 adding manifests
576 576 adding file changes
577 577 added 1 changesets with 1 changes to 1 files (+1 heads)
578 578 1 new obsolescence markers
579 579
580 580 test relevance computation
581 581 ---------------------------------------
582 582
583 583 Checking simple case of "marker relevance".
584 584
585 585
586 586 Reminder of the repo situation
587 587
588 588 $ hg log --hidden --graph
589 589 @ 6:3de5eca88c00 (draft) [tip ] add obsolete_e
590 590 |
591 | x 5:cda648ca50f5 (draft) [ ] add original_e
591 | x 5:cda648ca50f5 (draft *obsolete*) [ ] add original_e
592 592 | |
593 | x 4:94b33453f93b (draft) [ ] add original_d
593 | x 4:94b33453f93b (draft *obsolete*) [ ] add original_d
594 594 |/
595 595 o 3:6f9641995072 (draft) [ ] add n3w_3_c
596 596 |
597 597 | o 2:245bde4270cd (public) [ ] add original_c
598 598 |/
599 599 o 1:7c3bad9141dc (public) [ ] add b
600 600 |
601 601 o 0:1f0dee641bb7 (public) [ ] add a
602 602
603 603
604 604 List of all markers
605 605
606 606 $ hg debugobsolete
607 607 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
608 608 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
609 609 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
610 610 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
611 611 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
612 612 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
613 613 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
614 614 cda648ca50f50482b7055c0b0c4c117bba6733d9 3de5eca88c00aa039da7399a220f4a5221faa585 0 (*) {'user': 'test'} (glob)
615 615
616 616 List of changesets with no chain
617 617
618 618 $ hg debugobsolete --hidden --rev ::2
619 619
620 620 List of changesets that are included on marker chain
621 621
622 622 $ hg debugobsolete --hidden --rev 6
623 623 cda648ca50f50482b7055c0b0c4c117bba6733d9 3de5eca88c00aa039da7399a220f4a5221faa585 0 (*) {'user': 'test'} (glob)
624 624
625 625 List of changesets with a longer chain, (including a pruned children)
626 626
627 627 $ hg debugobsolete --hidden --rev 3
628 628 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
629 629 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
630 630 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
631 631 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
632 632 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
633 633 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
634 634 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
635 635
636 636 List of both
637 637
638 638 $ hg debugobsolete --hidden --rev 3::6
639 639 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
640 640 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
641 641 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
642 642 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
643 643 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
644 644 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
645 645 cda648ca50f50482b7055c0b0c4c117bba6733d9 3de5eca88c00aa039da7399a220f4a5221faa585 0 (*) {'user': 'test'} (glob)
646 646 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
647 647
648 648 List of all markers in JSON
649 649
650 650 $ hg debugobsolete -Tjson
651 651 [
652 652 {
653 653 "date": [1339.0, 0],
654 654 "flag": 0,
655 655 "metadata": {"user": "test"},
656 656 "precnode": "1339133913391339133913391339133913391339",
657 657 "succnodes": ["ca819180edb99ed25ceafb3e9584ac287e240b00"]
658 658 },
659 659 {
660 660 "date": [1339.0, 0],
661 661 "flag": 0,
662 662 "metadata": {"user": "test"},
663 663 "precnode": "1337133713371337133713371337133713371337",
664 664 "succnodes": ["5601fb93a350734d935195fee37f4054c529ff39"]
665 665 },
666 666 {
667 667 "date": [121.0, 120],
668 668 "flag": 12,
669 669 "metadata": {"user": "test"},
670 670 "precnode": "245bde4270cd1072a27757984f9cda8ba26f08ca",
671 671 "succnodes": ["cdbce2fbb16313928851e97e0d85413f3f7eb77f"]
672 672 },
673 673 {
674 674 "date": [1338.0, 0],
675 675 "flag": 1,
676 676 "metadata": {"user": "test"},
677 677 "precnode": "5601fb93a350734d935195fee37f4054c529ff39",
678 678 "succnodes": ["6f96419950729f3671185b847352890f074f7557"]
679 679 },
680 680 {
681 681 "date": [1338.0, 0],
682 682 "flag": 0,
683 683 "metadata": {"user": "test"},
684 684 "precnode": "ca819180edb99ed25ceafb3e9584ac287e240b00",
685 685 "succnodes": ["1337133713371337133713371337133713371337"]
686 686 },
687 687 {
688 688 "date": [1337.0, 0],
689 689 "flag": 0,
690 690 "metadata": {"user": "test"},
691 691 "precnode": "cdbce2fbb16313928851e97e0d85413f3f7eb77f",
692 692 "succnodes": ["ca819180edb99ed25ceafb3e9584ac287e240b00"]
693 693 },
694 694 {
695 695 "date": [0.0, 0],
696 696 "flag": 0,
697 697 "metadata": {"user": "test"},
698 698 "parentnodes": ["6f96419950729f3671185b847352890f074f7557"],
699 699 "precnode": "94b33453f93bdb8d457ef9b770851a618bf413e1",
700 700 "succnodes": []
701 701 },
702 702 {
703 703 "date": *, (glob)
704 704 "flag": 0,
705 705 "metadata": {"user": "test"},
706 706 "precnode": "cda648ca50f50482b7055c0b0c4c117bba6733d9",
707 707 "succnodes": ["3de5eca88c00aa039da7399a220f4a5221faa585"]
708 708 }
709 709 ]
710 710
711 711 Template keywords
712 712
713 713 $ hg debugobsolete -r6 -T '{succnodes % "{node|short}"} {date|shortdate}\n'
714 714 3de5eca88c00 ????-??-?? (glob)
715 715 $ hg debugobsolete -r6 -T '{join(metadata % "{key}={value}", " ")}\n'
716 716 user=test
717 717 $ hg debugobsolete -r6 -T '{metadata}\n'
718 718 'user': 'test'
719 719 $ hg debugobsolete -r6 -T '{flag} {get(metadata, "user")}\n'
720 720 0 test
721 721
722 722 Test the debug output for exchange
723 723 ----------------------------------
724 724
725 725 $ hg pull ../tmpb --config 'experimental.obsmarkers-exchange-debug=True' # bundle2
726 726 pulling from ../tmpb
727 727 searching for changes
728 728 no changes found
729 729 obsmarker-exchange: 346 bytes received
730 730
731 731 check hgweb does not explode
732 732 ====================================
733 733
734 734 $ hg unbundle $TESTDIR/bundles/hgweb+obs.hg
735 735 adding changesets
736 736 adding manifests
737 737 adding file changes
738 738 added 62 changesets with 63 changes to 9 files (+60 heads)
739 739 (run 'hg heads .' to see heads, 'hg merge' to merge)
740 740 $ for node in `hg log -r 'desc(babar_)' --template '{node}\n'`;
741 741 > do
742 742 > hg debugobsolete $node
743 743 > done
744 744 $ hg up tip
745 745 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
746 746
747 747 #if serve
748 748
749 749 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
750 750 $ cat hg.pid >> $DAEMON_PIDS
751 751
752 752 check changelog view
753 753
754 754 $ get-with-headers.py --headeronly localhost:$HGPORT 'shortlog/'
755 755 200 Script output follows
756 756
757 757 check graph view
758 758
759 759 $ get-with-headers.py --headeronly localhost:$HGPORT 'graph'
760 760 200 Script output follows
761 761
762 762 check filelog view
763 763
764 764 $ get-with-headers.py --headeronly localhost:$HGPORT 'log/'`hg log -r . -T "{node}"`/'babar'
765 765 200 Script output follows
766 766
767 767 $ get-with-headers.py --headeronly localhost:$HGPORT 'rev/68'
768 768 200 Script output follows
769 769 $ get-with-headers.py --headeronly localhost:$HGPORT 'rev/67'
770 770 404 Not Found
771 771 [1]
772 772
773 773 check that web.view config option:
774 774
775 775 $ killdaemons.py hg.pid
776 776 $ cat >> .hg/hgrc << EOF
777 777 > [web]
778 778 > view=all
779 779 > EOF
780 780 $ wait
781 781 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
782 782 $ get-with-headers.py --headeronly localhost:$HGPORT 'rev/67'
783 783 200 Script output follows
784 784 $ killdaemons.py hg.pid
785 785
786 786 Checking _enable=False warning if obsolete marker exists
787 787
788 788 $ echo '[experimental]' >> $HGRCPATH
789 789 $ echo "evolution=" >> $HGRCPATH
790 790 $ hg log -r tip
791 791 obsolete feature not enabled but 68 markers found!
792 792 68:c15e9edfca13 (draft) [tip ] add celestine
793 793
794 794 reenable for later test
795 795
796 796 $ echo '[experimental]' >> $HGRCPATH
797 797 $ echo "evolution=createmarkers,exchange" >> $HGRCPATH
798 798
799 799 $ rm hg.pid access.log errors.log
800 800 #endif
801 801
802 802 Several troubles on the same changeset (create an unstable and bumped changeset)
803 803
804 804 $ hg debugobsolete `getid obsolete_e`
805 805 $ hg debugobsolete `getid original_c` `getid babar`
806 806 $ hg log --config ui.logtemplate= -r 'bumped() and unstable()'
807 807 changeset: 7:50c51b361e60
808 808 user: test
809 809 date: Thu Jan 01 00:00:00 1970 +0000
810 810 trouble: unstable, bumped
811 811 summary: add babar
812 812
813 813
814 test the "obsolete" templatekw
815
816 $ hg log -r 'obsolete()'
817 6:3de5eca88c00 (draft *obsolete*) [ ] add obsolete_e
818
814 819 test the "troubles" templatekw
815 820
816 821 $ hg log -r 'bumped() and unstable()'
817 822 7:50c51b361e60 (draft unstable bumped) [ ] add babar
818 823
819 824 test the default cmdline template
820 825
821 826 $ hg log -T default -r 'bumped()'
822 827 changeset: 7:50c51b361e60
823 828 user: test
824 829 date: Thu Jan 01 00:00:00 1970 +0000
825 830 trouble: unstable, bumped
826 831 summary: add babar
827 832
828 833
829 834 test summary output
830 835
831 836 $ hg up -r 'bumped() and unstable()'
832 837 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
833 838 $ hg summary
834 839 parent: 7:50c51b361e60 (unstable, bumped)
835 840 add babar
836 841 branch: default
837 842 commit: (clean)
838 843 update: 2 new changesets (update)
839 844 phases: 4 draft
840 845 unstable: 2 changesets
841 846 bumped: 1 changesets
842 847
843 848 Test incoming/outcoming with changesets obsoleted remotely, known locally
844 849 ===============================================================================
845 850
846 851 This test issue 3805
847 852
848 853 $ hg init repo-issue3805
849 854 $ cd repo-issue3805
850 855 $ echo "base" > base
851 856 $ hg ci -Am "base"
852 857 adding base
853 858 $ echo "foo" > foo
854 859 $ hg ci -Am "A"
855 860 adding foo
856 861 $ hg clone . ../other-issue3805
857 862 updating to branch default
858 863 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
859 864 $ echo "bar" >> foo
860 865 $ hg ci --amend
861 866 $ cd ../other-issue3805
862 867 $ hg log -G
863 868 @ 1:29f0c6921ddd (draft) [tip ] A
864 869 |
865 870 o 0:d20a80d4def3 (draft) [ ] base
866 871
867 872 $ hg log -G -R ../repo-issue3805
868 873 @ 3:323a9c3ddd91 (draft) [tip ] A
869 874 |
870 875 o 0:d20a80d4def3 (draft) [ ] base
871 876
872 877 $ hg incoming
873 878 comparing with $TESTTMP/tmpe/repo-issue3805 (glob)
874 879 searching for changes
875 880 3:323a9c3ddd91 (draft) [tip ] A
876 881 $ hg incoming --bundle ../issue3805.hg
877 882 comparing with $TESTTMP/tmpe/repo-issue3805 (glob)
878 883 searching for changes
879 884 3:323a9c3ddd91 (draft) [tip ] A
880 885 $ hg outgoing
881 886 comparing with $TESTTMP/tmpe/repo-issue3805 (glob)
882 887 searching for changes
883 888 1:29f0c6921ddd (draft) [tip ] A
884 889
885 890 #if serve
886 891
887 892 $ hg serve -R ../repo-issue3805 -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
888 893 $ cat hg.pid >> $DAEMON_PIDS
889 894
890 895 $ hg incoming http://localhost:$HGPORT
891 896 comparing with http://localhost:$HGPORT/
892 897 searching for changes
893 898 2:323a9c3ddd91 (draft) [tip ] A
894 899 $ hg outgoing http://localhost:$HGPORT
895 900 comparing with http://localhost:$HGPORT/
896 901 searching for changes
897 902 1:29f0c6921ddd (draft) [tip ] A
898 903
899 904 $ killdaemons.py
900 905
901 906 #endif
902 907
903 908 This test issue 3814
904 909
905 910 (nothing to push but locally hidden changeset)
906 911
907 912 $ cd ..
908 913 $ hg init repo-issue3814
909 914 $ cd repo-issue3805
910 915 $ hg push -r 323a9c3ddd91 ../repo-issue3814
911 916 pushing to ../repo-issue3814
912 917 searching for changes
913 918 adding changesets
914 919 adding manifests
915 920 adding file changes
916 921 added 2 changesets with 2 changes to 2 files
917 922 2 new obsolescence markers
918 923 $ hg out ../repo-issue3814
919 924 comparing with ../repo-issue3814
920 925 searching for changes
921 926 no changes found
922 927 [1]
923 928
924 929 Test that a local tag blocks a changeset from being hidden
925 930
926 931 $ hg tag -l visible -r 1 --hidden
927 932 $ hg log -G
928 933 @ 3:323a9c3ddd91 (draft) [tip ] A
929 934 |
930 | x 1:29f0c6921ddd (draft) [visible ] A
935 | x 1:29f0c6921ddd (draft *obsolete*) [visible ] A
931 936 |/
932 937 o 0:d20a80d4def3 (draft) [ ] base
933 938
934 939 Test that removing a local tag does not cause some commands to fail
935 940
936 941 $ hg tag -l -r tip tiptag
937 942 $ hg tags
938 943 tiptag 3:323a9c3ddd91
939 944 tip 3:323a9c3ddd91
940 945 visible 1:29f0c6921ddd
941 946 $ hg --config extensions.strip= strip -r tip --no-backup
942 947 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
943 948 $ hg tags
944 949 visible 1:29f0c6921ddd
945 950 tip 1:29f0c6921ddd
946 951
947 952 Test bundle overlay onto hidden revision
948 953
949 954 $ cd ..
950 955 $ hg init repo-bundleoverlay
951 956 $ cd repo-bundleoverlay
952 957 $ echo "A" > foo
953 958 $ hg ci -Am "A"
954 959 adding foo
955 960 $ echo "B" >> foo
956 961 $ hg ci -m "B"
957 962 $ hg up 0
958 963 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
959 964 $ echo "C" >> foo
960 965 $ hg ci -m "C"
961 966 created new head
962 967 $ hg log -G
963 968 @ 2:c186d7714947 (draft) [tip ] C
964 969 |
965 970 | o 1:44526ebb0f98 (draft) [ ] B
966 971 |/
967 972 o 0:4b34ecfb0d56 (draft) [ ] A
968 973
969 974
970 975 $ hg clone -r1 . ../other-bundleoverlay
971 976 adding changesets
972 977 adding manifests
973 978 adding file changes
974 979 added 2 changesets with 2 changes to 1 files
975 980 updating to branch default
976 981 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
977 982 $ cd ../other-bundleoverlay
978 983 $ echo "B+" >> foo
979 984 $ hg ci --amend -m "B+"
980 985 $ hg log -G --hidden
981 986 @ 3:b7d587542d40 (draft) [tip ] B+
982 987 |
983 | x 2:eb95e9297e18 (draft) [ ] temporary amend commit for 44526ebb0f98
988 | x 2:eb95e9297e18 (draft *obsolete*) [ ] temporary amend commit for 44526ebb0f98
984 989 | |
985 | x 1:44526ebb0f98 (draft) [ ] B
990 | x 1:44526ebb0f98 (draft *obsolete*) [ ] B
986 991 |/
987 992 o 0:4b34ecfb0d56 (draft) [ ] A
988 993
989 994
990 995 $ hg incoming ../repo-bundleoverlay --bundle ../bundleoverlay.hg
991 996 comparing with ../repo-bundleoverlay
992 997 searching for changes
993 998 1:44526ebb0f98 (draft) [ ] B
994 999 2:c186d7714947 (draft) [tip ] C
995 1000 $ hg log -G -R ../bundleoverlay.hg
996 1001 o 4:c186d7714947 (draft) [tip ] C
997 1002 |
998 1003 | @ 3:b7d587542d40 (draft) [ ] B+
999 1004 |/
1000 1005 o 0:4b34ecfb0d56 (draft) [ ] A
1001 1006
1002 1007
1003 1008 #if serve
1004 1009
1005 1010 Test issue 4506
1006 1011
1007 1012 $ cd ..
1008 1013 $ hg init repo-issue4506
1009 1014 $ cd repo-issue4506
1010 1015 $ echo "0" > foo
1011 1016 $ hg add foo
1012 1017 $ hg ci -m "content-0"
1013 1018
1014 1019 $ hg up null
1015 1020 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1016 1021 $ echo "1" > bar
1017 1022 $ hg add bar
1018 1023 $ hg ci -m "content-1"
1019 1024 created new head
1020 1025 $ hg up 0
1021 1026 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1022 1027 $ hg graft 1
1023 1028 grafting 1:1c9eddb02162 "content-1" (tip)
1024 1029
1025 1030 $ hg debugobsolete `hg log -r1 -T'{node}'` `hg log -r2 -T'{node}'`
1026 1031
1027 1032 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
1028 1033 $ cat hg.pid >> $DAEMON_PIDS
1029 1034
1030 1035 $ get-with-headers.py --headeronly localhost:$HGPORT 'rev/1'
1031 1036 404 Not Found
1032 1037 [1]
1033 1038 $ get-with-headers.py --headeronly localhost:$HGPORT 'file/tip/bar'
1034 1039 200 Script output follows
1035 1040 $ get-with-headers.py --headeronly localhost:$HGPORT 'annotate/tip/bar'
1036 1041 200 Script output follows
1037 1042
1038 1043 $ killdaemons.py
1039 1044
1040 1045 #endif
1041 1046
1042 1047 Test heads computation on pending index changes with obsolescence markers
1043 1048 $ cd ..
1044 1049 $ cat >$TESTTMP/test_extension.py << EOF
1045 1050 > from mercurial import cmdutil
1046 1051 > from mercurial.i18n import _
1047 1052 >
1048 1053 > cmdtable = {}
1049 1054 > command = cmdutil.command(cmdtable)
1050 1055 > @command("amendtransient",[], _('hg amendtransient [rev]'))
1051 1056 > def amend(ui, repo, *pats, **opts):
1052 1057 > def commitfunc(ui, repo, message, match, opts):
1053 1058 > return repo.commit(message, repo['.'].user(), repo['.'].date(), match)
1054 1059 > opts['message'] = 'Test'
1055 1060 > opts['logfile'] = None
1056 1061 > cmdutil.amend(ui, repo, commitfunc, repo['.'], {}, pats, opts)
1057 1062 > ui.write('%s\n' % repo.changelog.headrevs())
1058 1063 > EOF
1059 1064 $ cat >> $HGRCPATH << EOF
1060 1065 > [extensions]
1061 1066 > testextension=$TESTTMP/test_extension.py
1062 1067 > EOF
1063 1068 $ hg init repo-issue-nativerevs-pending-changes
1064 1069 $ cd repo-issue-nativerevs-pending-changes
1065 1070 $ mkcommit a
1066 1071 $ mkcommit b
1067 1072 $ hg up ".^"
1068 1073 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1069 1074 $ echo aa > a
1070 1075 $ hg amendtransient
1071 1076 [1, 3]
1072 1077
1073 1078 Check that corrupted hidden cache does not crash
1074 1079
1075 1080 $ printf "" > .hg/cache/hidden
1076 1081 $ hg log -r . -T '{node}' --debug
1077 1082 corrupted hidden cache
1078 1083 8fd96dfc63e51ed5a8af1bec18eb4b19dbf83812 (no-eol)
1079 1084 $ hg log -r . -T '{node}' --debug
1080 1085 8fd96dfc63e51ed5a8af1bec18eb4b19dbf83812 (no-eol)
1081 1086
1082 1087 #if unix-permissions
1083 1088 Check that wrong hidden cache permission does not crash
1084 1089
1085 1090 $ chmod 000 .hg/cache/hidden
1086 1091 $ hg log -r . -T '{node}' --debug
1087 1092 cannot read hidden cache
1088 1093 error writing hidden changesets cache
1089 1094 8fd96dfc63e51ed5a8af1bec18eb4b19dbf83812 (no-eol)
1090 1095 #endif
1091 1096
1092 1097 Test cache consistency for the visible filter
1093 1098 1) We want to make sure that the cached filtered revs are invalidated when
1094 1099 bookmarks change
1095 1100 $ cd ..
1096 1101 $ cat >$TESTTMP/test_extension.py << EOF
1097 1102 > import weakref
1098 1103 > from mercurial import cmdutil, extensions, bookmarks, repoview
1099 1104 > def _bookmarkchanged(orig, bkmstoreinst, *args, **kwargs):
1100 1105 > reporef = weakref.ref(bkmstoreinst._repo)
1101 1106 > def trhook(tr):
1102 1107 > repo = reporef()
1103 1108 > hidden1 = repoview.computehidden(repo)
1104 1109 > hidden = repoview.filterrevs(repo, 'visible')
1105 1110 > if sorted(hidden1) != sorted(hidden):
1106 1111 > print "cache inconsistency"
1107 1112 > bkmstoreinst._repo.currenttransaction().addpostclose('test_extension', trhook)
1108 1113 > orig(bkmstoreinst, *args, **kwargs)
1109 1114 > def extsetup(ui):
1110 1115 > extensions.wrapfunction(bookmarks.bmstore, 'recordchange',
1111 1116 > _bookmarkchanged)
1112 1117 > EOF
1113 1118
1114 1119 $ hg init repo-cache-inconsistency
1115 1120 $ cd repo-issue-nativerevs-pending-changes
1116 1121 $ mkcommit a
1117 1122 a already tracked!
1118 1123 $ mkcommit b
1119 1124 $ hg id
1120 1125 13bedc178fce tip
1121 1126 $ echo "hello" > b
1122 1127 $ hg commit --amend -m "message"
1123 1128 $ hg book bookb -r 13bedc178fce --hidden
1124 1129 $ hg log -r 13bedc178fce
1125 5:13bedc178fce (draft) [ bookb] add b
1130 5:13bedc178fce (draft *obsolete*) [ bookb] add b
1126 1131 $ hg book -d bookb
1127 1132 $ hg log -r 13bedc178fce
1128 1133 abort: hidden revision '13bedc178fce'!
1129 1134 (use --hidden to access hidden revisions)
1130 1135 [255]
1131 1136
1132 1137 Empty out the test extension, as it isn't compatible with later parts
1133 1138 of the test.
1134 1139 $ echo > $TESTTMP/test_extension.py
1135 1140
1136 1141 Test ability to pull changeset with locally applying obsolescence markers
1137 1142 (issue4945)
1138 1143
1139 1144 $ cd ..
1140 1145 $ hg init issue4845
1141 1146 $ cd issue4845
1142 1147
1143 1148 $ echo foo > f0
1144 1149 $ hg add f0
1145 1150 $ hg ci -m '0'
1146 1151 $ echo foo > f1
1147 1152 $ hg add f1
1148 1153 $ hg ci -m '1'
1149 1154 $ echo foo > f2
1150 1155 $ hg add f2
1151 1156 $ hg ci -m '2'
1152 1157
1153 1158 $ echo bar > f2
1154 1159 $ hg commit --amend --config experimetnal.evolution=createmarkers
1155 1160 $ hg log -G
1156 1161 @ 4:b0551702f918 (draft) [tip ] 2
1157 1162 |
1158 1163 o 1:e016b03fd86f (draft) [ ] 1
1159 1164 |
1160 1165 o 0:a78f55e5508c (draft) [ ] 0
1161 1166
1162 1167 $ hg log -G --hidden
1163 1168 @ 4:b0551702f918 (draft) [tip ] 2
1164 1169 |
1165 | x 3:f27abbcc1f77 (draft) [ ] temporary amend commit for e008cf283490
1170 | x 3:f27abbcc1f77 (draft *obsolete*) [ ] temporary amend commit for e008cf283490
1166 1171 | |
1167 | x 2:e008cf283490 (draft) [ ] 2
1172 | x 2:e008cf283490 (draft *obsolete*) [ ] 2
1168 1173 |/
1169 1174 o 1:e016b03fd86f (draft) [ ] 1
1170 1175 |
1171 1176 o 0:a78f55e5508c (draft) [ ] 0
1172 1177
1173 1178
1174 1179 $ hg strip -r 1 --config extensions.strip=
1175 1180 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1176 1181 saved backup bundle to $TESTTMP/tmpe/issue4845/.hg/strip-backup/e016b03fd86f-c41c6bcc-backup.hg (glob)
1177 1182 $ hg log -G
1178 1183 @ 0:a78f55e5508c (draft) [tip ] 0
1179 1184
1180 1185 $ hg log -G --hidden
1181 1186 @ 0:a78f55e5508c (draft) [tip ] 0
1182 1187
1183 1188
1184 1189 $ hg pull .hg/strip-backup/*
1185 1190 pulling from .hg/strip-backup/e016b03fd86f-c41c6bcc-backup.hg
1186 1191 searching for changes
1187 1192 adding changesets
1188 1193 adding manifests
1189 1194 adding file changes
1190 1195 added 2 changesets with 2 changes to 2 files
1191 1196 (run 'hg update' to get a working copy)
1192 1197 $ hg log -G
1193 1198 o 2:b0551702f918 (draft) [tip ] 2
1194 1199 |
1195 1200 o 1:e016b03fd86f (draft) [ ] 1
1196 1201 |
1197 1202 @ 0:a78f55e5508c (draft) [ ] 0
1198 1203
1199 1204 $ hg log -G --hidden
1200 1205 o 2:b0551702f918 (draft) [tip ] 2
1201 1206 |
1202 1207 o 1:e016b03fd86f (draft) [ ] 1
1203 1208 |
1204 1209 @ 0:a78f55e5508c (draft) [ ] 0
1205 1210
1206 1211 Test that 'hg debugobsolete --index --rev' can show indices of obsmarkers when
1207 1212 only a subset of those are displayed (because of --rev option)
1208 1213 $ hg init doindexrev
1209 1214 $ cd doindexrev
1210 1215 $ echo a > a
1211 1216 $ hg ci -Am a
1212 1217 adding a
1213 1218 $ hg ci --amend -m aa
1214 1219 $ echo b > b
1215 1220 $ hg ci -Am b
1216 1221 adding b
1217 1222 $ hg ci --amend -m bb
1218 1223 $ echo c > c
1219 1224 $ hg ci -Am c
1220 1225 adding c
1221 1226 $ hg ci --amend -m cc
1222 1227 $ echo d > d
1223 1228 $ hg ci -Am d
1224 1229 adding d
1225 1230 $ hg ci --amend -m dd
1226 1231 $ hg debugobsolete --index --rev "3+7"
1227 1232 1 6fdef60fcbabbd3d50e9b9cbc2a240724b91a5e1 d27fb9b066076fd921277a4b9e8b9cb48c95bc6a 0 \(.*\) {'user': 'test'} (re)
1228 1233 3 4715cf767440ed891755448016c2b8cf70760c30 7ae79c5d60f049c7b0dd02f5f25b9d60aaf7b36d 0 \(.*\) {'user': 'test'} (re)
1229 1234 $ hg debugobsolete --index --rev "3+7" -Tjson
1230 1235 [
1231 1236 {
1232 1237 "date": *, (glob)
1233 1238 "flag": 0,
1234 1239 "index": 1,
1235 1240 "metadata": {"user": "test"},
1236 1241 "precnode": "6fdef60fcbabbd3d50e9b9cbc2a240724b91a5e1",
1237 1242 "succnodes": ["d27fb9b066076fd921277a4b9e8b9cb48c95bc6a"]
1238 1243 },
1239 1244 {
1240 1245 "date": *, (glob)
1241 1246 "flag": 0,
1242 1247 "index": 3,
1243 1248 "metadata": {"user": "test"},
1244 1249 "precnode": "4715cf767440ed891755448016c2b8cf70760c30",
1245 1250 "succnodes": ["7ae79c5d60f049c7b0dd02f5f25b9d60aaf7b36d"]
1246 1251 }
1247 1252 ]
1248 1253
1249 1254 Test the --delete option of debugobsolete command
1250 1255 $ hg debugobsolete --index
1251 1256 0 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b f9bd49731b0b175e42992a3c8fa6c678b2bc11f1 0 \(.*\) {'user': 'test'} (re)
1252 1257 1 6fdef60fcbabbd3d50e9b9cbc2a240724b91a5e1 d27fb9b066076fd921277a4b9e8b9cb48c95bc6a 0 \(.*\) {'user': 'test'} (re)
1253 1258 2 1ab51af8f9b41ef8c7f6f3312d4706d870b1fb74 29346082e4a9e27042b62d2da0e2de211c027621 0 \(.*\) {'user': 'test'} (re)
1254 1259 3 4715cf767440ed891755448016c2b8cf70760c30 7ae79c5d60f049c7b0dd02f5f25b9d60aaf7b36d 0 \(.*\) {'user': 'test'} (re)
1255 1260 $ hg debugobsolete --delete 1 --delete 3
1256 1261 deleted 2 obsolescence markers
1257 1262 $ hg debugobsolete
1258 1263 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b f9bd49731b0b175e42992a3c8fa6c678b2bc11f1 0 \(.*\) {'user': 'test'} (re)
1259 1264 1ab51af8f9b41ef8c7f6f3312d4706d870b1fb74 29346082e4a9e27042b62d2da0e2de211c027621 0 \(.*\) {'user': 'test'} (re)
1260 1265 $ cd ..
1261 1266
General Comments 0
You need to be logged in to leave comments. Login now