Mercurial > evolve
changeset 579:f6063ef211fd
evolve: drop code now in core
The default branch aims compat with the mercurial default branch. we do not need
all those conditional.
author | Pierre-Yves David <pierre-yves.david@logilab.fr> |
---|---|
date | Wed, 10 Oct 2012 15:26:09 +0200 |
parents | 02f34904305f |
children | 95089805c3fc |
files | hgext/evolve.py |
diffstat | 1 files changed, 5 insertions(+), 361 deletions(-) [+] |
line wrap: on
line diff
--- a/hgext/evolve.py Wed Oct 10 15:11:31 2012 +0200 +++ b/hgext/evolve.py Wed Oct 10 15:26:09 2012 +0200 @@ -313,184 +313,10 @@ yield marker -##################################################################### -### Obsolescence Caching Logic ### -##################################################################### - -# IN CORE fb72eec7efd8 - -# Obsolescence related logic can be very slow if we don't have efficient cache. -# -# This section implements a cache mechanism that did not make it into core for -# time reason. It stores meaningful set of revisions related to obsolescence -# (obsolete, unstable, etc.) -# -# Here is: -# -# - Computation of meaningful sets -# - Cache access logic, -# - Cache invalidation logic, -# - revset and ctx using this cache. -# - - -### Computation of meaningful set -# -# Most set can be computed with "simple" revset. - -#: { set name -> function to compute this set } mapping -#: function take a single "repo" argument. -#: -#: Use the `cachefor` decorator to register new cache function -try: - cachefuncs = obsolete.cachefuncs - cachefor = obsolete.cachefor - getobscache = obsolete.getobscache - clearobscaches = obsolete.clearobscaches -except AttributeError: - cachefuncs = {} - - def cachefor(name): - """Decorator to register a function as computing the cache for a set""" - def decorator(func): - assert name not in cachefuncs - cachefuncs[name] = func - return func - return decorator - - @cachefor('obsolete') - def _computeobsoleteset(repo): - """the set of obsolete revisions""" - obs = set() - nm = repo.changelog.nodemap - for prec in repo.obsstore.precursors: - rev = nm.get(prec) - if rev is not None: - obs.add(rev) - return set(repo.revs('%ld - public()', obs)) - - @cachefor('unstable') - def _computeunstableset(repo): - """the set of non obsolete revisions with obsolete parents""" - return set(repo.revs('(obsolete()::) - obsolete()')) - - @cachefor('suspended') - def _computesuspendedset(repo): - """the set of obsolete parents with non obsolete descendants""" - return set(repo.revs('obsolete() and obsolete()::unstable()')) - - @cachefor('extinct') - def _computeextinctset(repo): - """the set of obsolete parents without non obsolete descendants""" - return set(repo.revs('obsolete() - obsolete()::unstable()')) - - @eh.wrapfunction(obsolete.obsstore, '__init__') - def _initobsstorecache(orig, obsstore, *args, **kwargs): - """add a cache attribute to obsstore""" - obsstore.caches = {} - return orig(obsstore, *args, **kwargs) - -### Cache access - - def getobscache(repo, name): - """Return the set of revision that belong to the <name> set - - Such access may compute the set and cache it for future use""" - if not repo.obsstore: - return () - if name not in repo.obsstore.caches: - repo.obsstore.caches[name] = cachefuncs[name](repo) - return repo.obsstore.caches[name] - -### Cache clean up -# -# To be simple we need to invalidate obsolescence cache when: -# -# - new changeset is added: -# - public phase is changed -# - obsolescence marker are added -# - strip is used a repo - - - def clearobscaches(repo): - """Remove all obsolescence related cache from a repo - - This remove all cache in obsstore is the obsstore already exist on the - repo. - - (We could be smarter here)""" - if 'obsstore' in repo._filecache: - repo.obsstore.caches.clear() - - @eh.wrapfunction(localrepo.localrepository, 'addchangegroup') # new changeset - @eh.wrapfunction(phases, 'retractboundary') # phase movement - @eh.wrapfunction(phases, 'advanceboundary') # phase movement - @eh.wrapfunction(localrepo.localrepository, 'destroyed') # strip - def wrapclearcache(orig, repo, *args, **kwargs): - try: - return orig(repo, *args, **kwargs) - finally: - # we are a bit wide here - # we could restrict to: - # advanceboundary + phase==public - # retractboundary + phase==draft - clearobscaches(repo) - - @eh.wrapfunction(obsolete.obsstore, 'add') # new marker - def clearonadd(orig, obsstore, *args, **kwargs): - try: - return orig(obsstore, *args, **kwargs) - finally: - obsstore.caches.clear() - -### Use the case -# Function in core that could benefic from the cache are overwritten by cache using version - -# changectx method - - @eh.addattr(context.changectx, 'unstable') - def unstable(ctx): - """is the changeset unstable (have obsolete ancestor)""" - if ctx.node() is None: - return False - return ctx.rev() in getobscache(ctx._repo, 'unstable') - - - @eh.addattr(context.changectx, 'extinct') - def extinct(ctx): - """is the changeset extinct by other""" - if ctx.node() is None: - return False - return ctx.rev() in getobscache(ctx._repo, 'extinct') - -# revset - - @eh.revset('obsolete') - def revsetobsolete(repo, subset, x): - """``obsolete()`` - Changeset is obsolete. - """ - args = revset.getargs(x, 0, 0, 'obsolete takes no argument') - obsoletes = getobscache(repo, 'obsolete') - return [r for r in subset if r in obsoletes] - - @eh.revset('unstable') - def revsetunstable(repo, subset, x): - """``unstable()`` - Unstable changesets are non-obsolete with obsolete ancestors. - """ - args = revset.getargs(x, 0, 0, 'unstable takes no arguments') - unstables = getobscache(repo, 'unstable') - return [r for r in subset if r in unstables] - - @eh.revset('extinct') - def revsetextinct(repo, subset, x): - """``extinct()`` - Obsolete changesets with obsolete descendants only. - """ - args = revset.getargs(x, 0, 0, 'extinct takes no arguments') - extincts = getobscache(repo, 'extinct') - return [r for r in subset if r in extincts] +cachefuncs = obsolete.cachefuncs +cachefor = obsolete.cachefor +getobscache = obsolete.getobscache +clearobscaches = obsolete.clearobscaches ##################################################################### ### Complete troubles computation logic ### @@ -650,44 +476,7 @@ # - function to travel throught the obsolescence graph # - function to find useful changeset to stabilize -### Marker Create -# NOW IN CORE f85816af6294 -try: - createmarkers = obsolete.createmarkers -except AttributeError: - def createmarkers(repo, relations, metadata=None, flag=0): - """Add obsolete markers between changeset in a repo - - <relations> must be an iterable of (<old>, (<new>, ...)) tuple. - `old` and `news` are changectx. - - Current user and date are used except if specified otherwise in the - metadata attribute. - - /!\ assume the repo have been locked by the user /!\ - """ - # prepare metadata - if metadata is None: - metadata = {} - if 'date' not in metadata: - metadata['date'] = '%i %i' % util.makedate() - if 'user' not in metadata: - metadata['user'] = repo.ui.username() - # check future marker - tr = repo.transaction('add-obsolescence-marker') - try: - for prec, sucs in relations: - if not prec.mutable(): - raise util.Abort("cannot obsolete immutable changeset: %s" % prec) - nprec = prec.node() - nsucs = tuple(s.node() for s in sucs) - if nprec in nsucs: - raise util.Abort("changeset %s cannot obsolete himself" % prec) - repo.obsstore.create(tr, nprec, nsucs, flag, metadata) - clearobscaches(repo) - tr.close() - finally: - tr.release() +createmarkers = obsolete.createmarkers ### Useful alias @@ -841,16 +630,6 @@ # they are subject to changes -if 'hidden' not in revset.symbols: - # in 2.3+ - @eh.revset('hidden') - def revsethidden(repo, subset, x): - """``hidden()`` - Changeset is hidden. - """ - args = revset.getargs(x, 0, 0, 'hidden takes no argument') - return [r for r in subset if r in repo.hiddenrevs] - ### XXX I'm not sure this revset is useful @eh.revset('suspended') def revsetsuspended(repo, subset, x): @@ -1008,134 +787,6 @@ ### Core Other extension compat ### ##################################################################### -# This section make official history rewritter create obsolete marker - - -### commit --amend -# make commit --amend create obsolete marker -# -# The precursor is still strip from the repository. - -# IN CORE 63e45aee46d4 - -if getattr(cmdutil, 'obsolete', None) is None: - @eh.wrapfunction(cmdutil, 'amend') - def wrapcmdutilamend(orig, ui, repo, commitfunc, old, *args, **kwargs): - oldnode = old.node() - new = orig(ui, repo, commitfunc, old, *args, **kwargs) - if new != oldnode: - lock = repo.lock() - try: - tr = repo.transaction('post-amend-obst') - try: - meta = { - 'date': '%i %i' % util.makedate(), - 'user': ui.username(), - } - repo.obsstore.create(tr, oldnode, [new], 0, meta) - tr.close() - clearobscaches(repo) - finally: - tr.release() - finally: - lock.release() - return new - -### rebase -# -# - ignore obsolete changeset -# - create obsolete marker *instead of* striping - -def buildstate(orig, repo, dest, rebaseset, *ags, **kws): - """wrapper for rebase 's buildstate that exclude obsolete changeset""" - - rebaseset = repo.revs('%ld - extinct()', rebaseset) - if not rebaseset: - repo.ui.warn(_('whole rebase set is extinct and ignored.\n')) - return {} - root = min(rebaseset) - if (not getattr(repo, '_rebasekeep', False) - and not repo[root].mutable()): - raise util.Abort(_("can't rebase immutable changeset %s") % repo[root], - hint=_('see hg help phases for details')) - return orig(repo, dest, rebaseset, *ags, **kws) - -def defineparents(orig, repo, rev, target, state, *args, **kwargs): - rebasestate = getattr(repo, '_rebasestate', None) - if rebasestate is not None: - repo._rebasestate = dict(state) - repo._rebasetarget = target - return orig(repo, rev, target, state, *args, **kwargs) - -def concludenode(orig, repo, rev, p1, *args, **kwargs): - """wrapper for rebase 's concludenode that set obsolete relation""" - newrev = orig(repo, rev, p1, *args, **kwargs) - rebasestate = getattr(repo, '_rebasestate', None) - if rebasestate is not None: - if newrev is not None: - nrev = repo[newrev].rev() - else: - nrev = p1 - repo._rebasestate[rev] = nrev - return newrev - -def cmdrebase(orig, ui, repo, *args, **kwargs): - - reallykeep = kwargs.get('keep', False) - kwargs = dict(kwargs) - kwargs['keep'] = True - repo._rebasekeep = reallykeep - - # We want to mark rebased revision as obsolete and set their - # replacements if any. Doing it in concludenode() prevents - # aborting the rebase, and is not called with all relevant - # revisions in --collapse case. Instead, we try to track the - # rebase state structure by sampling/updating it in - # defineparents() and concludenode(). The obsolete markers are - # added from this state after a successful call. - repo._rebasestate = {} - repo._rebasetarget = None - try: - l = repo.lock() - try: - res = orig(ui, repo, *args, **kwargs) - if not reallykeep: - # Filter nullmerge or unrebased entries - repo._rebasestate = dict(p for p in repo._rebasestate.iteritems() - if p[1] >= 0) - if not res and not kwargs.get('abort') and repo._rebasestate: - # Rebased revisions are assumed to be descendants of - # targetrev. If a source revision is mapped to targetrev - # or to another rebased revision, it must have been - # removed. - markers = [] - if kwargs.get('collapse'): - # collapse assume revision disapear because they are all - # in the created revision - newrevs = set(repo._rebasestate.values()) - newrevs.remove(repo._rebasetarget) - if newrevs: - # we create new revision. - # A single one by --collapse design - assert len(newrevs) == 1 - new = tuple(repo[n] for n in newrevs) - else: - # every body died. no new changeset created - new = (repo[repo._rebasetarget],) - for rev, newrev in sorted(repo._rebasestate.items()): - markers.append((repo[rev], new)) - else: - # no collapse assume revision disapear because they are - # contained in parent - for rev, newrev in sorted(repo._rebasestate.items()): - markers.append((repo[rev], (repo[newrev],))) - createmarkers(repo, markers) - return res - finally: - l.release() - finally: - delattr(repo, '_rebasestate') - delattr(repo, '_rebasetarget') @eh.extsetup def _rebasewrapping(ui): @@ -1143,14 +794,7 @@ try: rebase = extensions.find('rebase') if rebase: - incore = getattr(rebase, 'obsolete', None) is not None - if not incore: - extensions.wrapcommand(rebase.cmdtable, "rebase", cmdrebase) extensions.wrapcommand(rebase.cmdtable, 'rebase', warnobserrors) - if not incore: - extensions.wrapfunction(rebase, 'buildstate', buildstate) - extensions.wrapfunction(rebase, 'defineparents', defineparents) - extensions.wrapfunction(rebase, 'concludenode', concludenode) except KeyError: pass # rebase not found