diff mercurial/context.py @ 17469:fb72eec7efd8

obsolete: introduce caches for all meaningful sets This changeset introduces caches on the `obsstore` that keeps track of sets of revisions meaningful for obsolescence related logics. For now they are: - obsolete: changesets used as precursors (and not public), - extinct: obsolete changesets with osbolete descendants only, - unstable: non obsolete changesets with obsolete ancestors. The cache is accessed using the `getobscache(repo, '<set-name>')` function which builds the cache on demand. The `clearobscaches(repo)` function takes care of clearing the caches if any. Caches are cleared when one of these events happens: - a new marker is added, - a new changeset is added, - some changesets are made public, - some public changesets are demoted to draft or secret. Declaration of more sets is made easy because we will have to handle at least two other "troubles" (latecomer and conflicting). Caches are now used by revset and changectx. It is usually not much more expensive to compute the whole set than to check the property of a few elements. The performance boost is welcome in case we apply obsolescence logic on a lot of revisions. This makes the feature usable!
author Pierre-Yves David <pierre-yves.david@logilab.fr>
date Tue, 28 Aug 2012 20:52:04 +0200
parents 57c6c24b9bc4
children 3a524b647897
line wrap: on
line diff
--- a/mercurial/context.py	Mon Aug 27 09:37:49 2012 -0700
+++ b/mercurial/context.py	Tue Aug 28 20:52:04 2012 +0200
@@ -11,6 +11,7 @@
 import copies
 import match as matchmod
 import os, errno, stat
+import obsolete as obsmod
 
 propertycache = util.propertycache
 
@@ -232,38 +233,15 @@
 
     def obsolete(self):
         """True if the changeset is obsolete"""
-        return (self.node() in self._repo.obsstore.precursors
-                and self.phase() > phases.public)
+        return self.rev() in obsmod.getobscache(self._repo, 'obsolete')
 
     def extinct(self):
         """True if the changeset is extinct"""
-        # We should just compute a cache and check against it.
-        # See revset implementation for details.
-        #
-        # But this naive implementation does not require cache
-        if self.phase() <= phases.public:
-            return False
-        if not self.obsolete():
-            return False
-        for desc in self.descendants():
-            if not desc.obsolete():
-                return False
-        return True
+        return self.rev() in obsmod.getobscache(self._repo, 'extinct')
 
     def unstable(self):
         """True if the changeset is not obsolete but it's ancestor are"""
-        # We should just compute /(obsolete()::) - obsolete()/
-        # and keep it in a cache.
-        #
-        # But this naive implementation does not require cache
-        if self.phase() <= phases.public:
-            return False
-        if self.obsolete():
-            return False
-        for anc in self.ancestors():
-            if anc.obsolete():
-                return True
-        return False
+        return self.rev() in obsmod.getobscache(self._repo, 'unstable')
 
     def _fileinfo(self, path):
         if '_manifest' in self.__dict__: