diff -r 362e65fc6146 -r 38fbcc760ec6 hgext/evolve.py --- a/hgext/evolve.py Tue Sep 11 11:45:00 2012 +0200 +++ b/hgext/evolve.py Tue Sep 11 12:19:13 2012 +0200 @@ -298,6 +298,8 @@ ### 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 @@ -321,58 +323,65 @@ #: function take a single "repo" argument. #: #: Use the `cachefor` decorator to register new cache function -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 +try: + cachefuncs = obsolete.cachefuncs + cachefor = obsolete.cachefor + getobscache = obsolete.getobscache + clearobscaches = obsolete.clearobscaches +except AttributeError: + cachefuncs = {} -@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)) + 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('unstable') -def _computeunstableset(repo): - """the set of non obsolete revisions with obsolete parents""" - return set(repo.revs('(obsolete()::) - obsolete()')) + @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('suspended') -def _computesuspendedset(repo): - """the set of obsolete parents with non obsolete descendants""" - return set(repo.revs('obsolete() and obsolete()::unstable()')) + @cachefor('unstable') + def _computeunstableset(repo): + """the set of non obsolete revisions with obsolete parents""" + return set(repo.revs('(obsolete()::) - obsolete()')) -@cachefor('extinct') -def _computeextinctset(repo): - """the set of obsolete parents without non obsolete descendants""" - return set(repo.revs('obsolete() - obsolete()::unstable()')) + @cachefor('suspended') + def _computesuspendedset(repo): + """the set of obsolete parents with non obsolete descendants""" + return set(repo.revs('obsolete() and 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) + @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 set + def getobscache(repo, name): + """Return the set of revision that belong to the 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] + 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 # @@ -384,85 +393,85 @@ # - strip is used a repo -def clearobscaches(repo): - """Remove all obsolescence related cache from 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. + 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() + (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(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() + @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, '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') + @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('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('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] + @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] ##################################################################### ### Complete troubles computation logic ###