comparison hgext/obsolete.py @ 448:96c896f0180b

obsolete: some more movement
author Pierre-Yves David <pierre-yves.david@ens-lyon.org>
date Tue, 07 Aug 2012 21:39:55 +0200
parents fa85e7205e0b
children 4f23f224afb4
comparison
equal deleted inserted replaced
447:fa85e7205e0b 448:96c896f0180b
340 @cachefor('extinct') 340 @cachefor('extinct')
341 def _computeextinctset(repo): 341 def _computeextinctset(repo):
342 """the set of obsolete parent without non obsolete descendant""" 342 """the set of obsolete parent without non obsolete descendant"""
343 return set(repo.revs('obsolete() - obsolete()::unstable()')) 343 return set(repo.revs('obsolete() - obsolete()::unstable()'))
344 344
345 @eh.wrapfunction(obsolete.obsstore, '__init__')
346 def _initobsstorecache(orig, obsstore, *args, **kwargs):
347 """add a caches attributes to obsstore"""
348 obsstore.caches = {}
349 return orig(obsstore, *args, **kwargs)
350
351 def getobscache(repo, name):
352 if not repo.obsstore:
353 return ()
354 if name not in repo.obsstore.caches:
355 repo.obsstore.caches[name] = computecache[name](repo)
356 return repo.obsstore.caches[name]
357
358
359 ### cache clean up
360 def clearobscaches(repo):
361 #if 'obsstore' in vars(repo):
362 # should work great but cache invalidation act strange
363 repo.obsstore.caches.clear()
364
365 @eh.wrapfunction(localrepo.localrepository, 'updatebranchcache')
366 @eh.wrapfunction(phases, 'advanceboundary')
367 def wrapclearcache(orig, repo, *args, **kwargs):
368 try:
369 return orig(repo, *args, **kwargs)
370 finally:
371 clearobscaches(repo)
372
373 @eh.wrapfunction(obsolete.obsstore, 'add')
374 def clearonadd(orig, obsstore, *args, **kwargs):
375 try:
376 return orig(obsstore, *args, **kwargs)
377 finally:
378 obsstore.caches.clear()
379
380 ### cache user
381
382 @eh.addattr(context.changectx, 'unstable')
383 def unstable(ctx):
384 """is the changeset unstable (have obsolete ancestor)"""
385 if ctx.node() is None:
386 return False
387 return ctx.rev() in getobscache(ctx._repo, 'unstable')
388
389
390 @eh.addattr(context.changectx, 'extinct')
391 def extinct(ctx):
392 """is the changeset extinct by other"""
393 if ctx.node() is None:
394 return False
395 return ctx.rev() in getobscache(ctx._repo, 'extinct')
396
397 @eh.revset('obsolete')
398 def revsetobsolete(repo, subset, x):
399 """``obsolete()``
400 Changeset is obsolete.
401 """
402 args = revset.getargs(x, 0, 0, 'obsolete takes no argument')
403 obsoletes = getobscache(repo, 'obsolete')
404 return [r for r in subset if r in obsoletes]
405
406 @eh.revset('unstable')
407 def revsetunstable(repo, subset, x):
408 """``unstable()``
409 Unstable changesets are non-obsolete with obsolete ancestors.
410 """
411 args = revset.getargs(x, 0, 0, 'unstable takes no arguments')
412 unstables = getobscache(repo, 'unstable')
413 return [r for r in subset if r in unstables]
414
415 @eh.revset('extinct')
416 def revsetextinct(repo, subset, x):
417 """``extinct()``
418 Obsolete changesets with obsolete descendants only.
419 """
420 args = revset.getargs(x, 0, 0, 'extinct takes no arguments')
421 extincts = getobscache(repo, 'extinct')
422 return [r for r in subset if r in extincts]
423
424 #####################################################################
425 ### Complete troubles computation logic ###
426 #####################################################################
427
345 @cachefor('latecomer') 428 @cachefor('latecomer')
346 def _computelatecomerset(repo): 429 def _computelatecomerset(repo):
347 """the set of rev trying to obsolete public revision""" 430 """the set of rev trying to obsolete public revision"""
348 query = 'allsuccessors(public()) - obsolete() - public()' 431 query = 'allsuccessors(public()) - obsolete() - public()'
349 return set(repo.revs(query)) 432 return set(repo.revs(query))
366 conflicting.add(ctx.rev()) 449 conflicting.add(ctx.rev())
367 break 450 break
368 toprocess.update(obsstore.successors.get(prec, ())) 451 toprocess.update(obsstore.successors.get(prec, ()))
369 return conflicting 452 return conflicting
370 453
371 @eh.wrapfunction(obsolete.obsstore, '__init__')
372 def _initobsstorecache(orig, obsstore, *args, **kwargs):
373 """add a caches attributes to obsstore"""
374 obsstore.caches = {}
375 return orig(obsstore, *args, **kwargs)
376
377 def getobscache(repo, name):
378 if not repo.obsstore:
379 return ()
380 if name not in repo.obsstore.caches:
381 repo.obsstore.caches[name] = computecache[name](repo)
382 return repo.obsstore.caches[name]
383
384
385 ### cache clean up
386 def clearobscaches(repo):
387 #if 'obsstore' in vars(repo):
388 # should work great but cache invalidation act strange
389 repo.obsstore.caches.clear()
390
391 @eh.wrapfunction(localrepo.localrepository, 'updatebranchcache')
392 @eh.wrapfunction(phases, 'advanceboundary')
393 def wrapclearcache(orig, repo, *args, **kwargs):
394 try:
395 return orig(repo, *args, **kwargs)
396 finally:
397 clearobscaches(repo)
398
399 @eh.wrapfunction(obsolete.obsstore, 'add')
400 def clearonadd(orig, obsstore, *args, **kwargs):
401 try:
402 return orig(obsstore, *args, **kwargs)
403 finally:
404 obsstore.caches.clear()
405
406 ### cache user
407
408 @eh.addattr(context.changectx, 'unstable')
409 def unstable(ctx):
410 """is the changeset unstable (have obsolete ancestor)"""
411 if ctx.node() is None:
412 return False
413 return ctx.rev() in getobscache(ctx._repo, 'unstable')
414
415
416 @eh.addattr(context.changectx, 'extinct')
417 def extinct(ctx):
418 """is the changeset extinct by other"""
419 if ctx.node() is None:
420 return False
421 return ctx.rev() in getobscache(ctx._repo, 'extinct')
422
423 @eh.revset('obsolete')
424 def revsetobsolete(repo, subset, x):
425 """``obsolete()``
426 Changeset is obsolete.
427 """
428 args = revset.getargs(x, 0, 0, 'obsolete takes no argument')
429 obsoletes = getobscache(repo, 'obsolete')
430 return [r for r in subset if r in obsoletes]
431
432 @eh.revset('unstable')
433 def revsetunstable(repo, subset, x):
434 """``unstable()``
435 Unstable changesets are non-obsolete with obsolete ancestors.
436 """
437 args = revset.getargs(x, 0, 0, 'unstable takes no arguments')
438 unstables = getobscache(repo, 'unstable')
439 return [r for r in subset if r in unstables]
440
441 @eh.revset('extinct')
442 def revsetextinct(repo, subset, x):
443 """``extinct()``
444 Obsolete changesets with obsolete descendants only.
445 """
446 args = revset.getargs(x, 0, 0, 'extinct takes no arguments')
447 extincts = getobscache(repo, 'extinct')
448 return [r for r in subset if r in extincts]
449
450 #####################################################################
451 ### Complete troubles computation logic ###
452 #####################################################################
453
454 @eh.addattr(context.changectx, 'latecomer') 454 @eh.addattr(context.changectx, 'latecomer')
455 def latecomer(ctx): 455 def latecomer(ctx):
456 """is the changeset latecomer (Try to succeed to public change)""" 456 """is the changeset latecomer (Try to succeed to public change)"""
457 if ctx.node() is None: 457 if ctx.node() is None:
458 return False 458 return False
462 def conflicting(ctx): 462 def conflicting(ctx):
463 """is the changeset conflicting (Try to succeed to public change)""" 463 """is the changeset conflicting (Try to succeed to public change)"""
464 if ctx.node() is None: 464 if ctx.node() is None:
465 return False 465 return False
466 return ctx.rev() in getobscache(ctx._repo, 'conflicting') 466 return ctx.rev() in getobscache(ctx._repo, 'conflicting')
467
468 ### Discovery wrapping
469
470 @eh.wrapfunction(discovery, 'checkheads')
471 def wrapcheckheads(orig, repo, remote, outgoing, *args, **kwargs):
472 """wrap mercurial.discovery.checkheads
473
474 * prevent unstability to be pushed
475 * patch remote to ignore obsolete heads on remote
476 """
477 # do not push instability
478 for h in outgoing.missingheads:
479 # Checking heads is enough, obsolete descendants are either
480 # obsolete or unstable.
481 ctx = repo[h]
482 if ctx.latecomer():
483 raise util.Abort(_("push includes a latecomer changeset: %s!")
484 % ctx)
485 if ctx.conflicting():
486 raise util.Abort(_("push includes a conflicting changeset: %s!")
487 % ctx)
488 return orig(repo, remote, outgoing, *args, **kwargs)
467 489
468 490
469 ##################################################################### 491 #####################################################################
470 ### Additional Utilities ### 492 ### Additional Utilities ###
471 ##################################################################### 493 #####################################################################
705 ##################################################################### 727 #####################################################################
706 ### Various trouble warning ### 728 ### Various trouble warning ###
707 ##################################################################### 729 #####################################################################
708 730
709 731
710 ### Discovery wrapping
711
712 @eh.wrapfunction(discovery, 'checkheads')
713 def wrapcheckheads(orig, repo, remote, outgoing, *args, **kwargs):
714 """wrap mercurial.discovery.checkheads
715
716 * prevent unstability to be pushed
717 * patch remote to ignore obsolete heads on remote
718 """
719 # do not push instability
720 for h in outgoing.missingheads:
721 # Checking heads is enough, obsolete descendants are either
722 # obsolete or unstable.
723 ctx = repo[h]
724 if ctx.latecomer():
725 raise util.Abort(_("push includes a latecomer changeset: %s!")
726 % ctx)
727 if ctx.conflicting():
728 raise util.Abort(_("push includes a conflicting changeset: %s!")
729 % ctx)
730 return orig(repo, remote, outgoing, *args, **kwargs)
731 732
732 @eh.wrapcommand("update") 733 @eh.wrapcommand("update")
733 @eh.wrapcommand("pull") 734 @eh.wrapcommand("pull")
734 def wrapmayobsoletewc(origfn, ui, repo, *args, **opts): 735 def wrapmayobsoletewc(origfn, ui, repo, *args, **opts):
735 res = origfn(ui, repo, *args, **opts) 736 res = origfn(ui, repo, *args, **opts)