[PATCH 19 of 27 clfilter V2] clfilter: distinct propertycache that must be unfiltered from the other

Pierre-Yves David pierre-yves.david at ens-lyon.org
Mon Oct 8 16:38:10 CDT 2012

# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at logilab.fr>
# Date 1349719340 -7200
# Node ID 73f596129126bb5a6ffdde2394720d0ea5aae798
# Parent  03436368065761325d3009f7ef996508af8388e2
clfilter: distinct propertycache that must be unfiltered from the other

Some of the localrepo property cache must be computed unfiltered and store
globably. Some other must see the filtered version and store data relative to
the current filtering.

This changeset introduces two classes `unfilteredpropertycache` and
`filteredpropertycache` for this purpose. A new function `hasunfilteredcache` is
introduced for unambiguous check for cached value on unfiltered repo.

A few tweaks are made to the property cache class to allow overriding the way the
computed value is stored on the object.

Some logic relative to _tagcaches is cleaned up in the process.

diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -34,6 +34,23 @@
     def join(self, obj, fname):
         return obj.sjoin(fname)
+class unfilteredpropertycache(propertycache):
+    """propertycache that apply to unfiltered repo only"""
+    def __get__(self, repo, type=None):
+        return super(unfilteredpropertycache, self).__get__(repo.unfiltered())
+class filteredpropertycache(propertycache):
+    """propertycache that must take filtering in account"""
+    def cachevalue(self, obj, value):
+        object.__setattr__(obj, self.name, value)
+def hasunfilteredcache(repo, name):
+    """check if an repo and a unfilteredproperty cached value for <name>"""
+    return name in vars(repo.unfiltered())
 def unfilteredmeth(orig):
     def wrapper(repo, *args, **kwargs):
         return orig(repo.unfiltered(), *args, **kwargs)
@@ -317,7 +334,7 @@
             self.ui.warn(msg % len(list(store)))
         return store
-    @propertycache
+    @unfilteredpropertycache
     def hiddenrevs(self):
         """hiddenrevs: revs that should be hidden by command and tools
@@ -513,7 +530,7 @@
         self.tags() # instantiate the cache
         self._tag(names, node, message, local, user, date)
-    @propertycache
+    @filteredpropertycache
     def _tagscache(self):
         '''Returns a tagscache object that contains various tags related
@@ -900,11 +917,11 @@
         return data
-    @propertycache
+    @unfilteredpropertycache
     def _encodefilterpats(self):
         return self._loadfilter('encode')
-    @propertycache
+    @unfilteredpropertycache
     def _decodefilterpats(self):
         return self._loadfilter('decode')
@@ -1070,13 +1087,10 @@
         return 0
     def invalidatecaches(self):
-        def delcache(name):
-            try:
-                delattr(self, name)
-            except AttributeError:
-                pass
-        delcache('_tagscache')
+        if '_tagscache' in vars(self):
+            # can't use delattr on proxy
+            del self.__dict__['_tagscache']
         self.unfiltered()._branchcache = None # in UTF-8
         self.unfiltered()._branchcachetip = None
@@ -1091,7 +1105,7 @@
         rereads the dirstate. Use dirstate.invalidate() if you want to
         explicitly read the dirstate again (i.e. restoring it to a previous
         known good state).'''
-        if 'dirstate' in self.__dict__:
+        if hasunfilteredcache(self, 'dirstate'):
             for k in self.dirstate._filecache:
                     delattr(self.dirstate, k)
@@ -1148,7 +1162,7 @@
         def unlock():
-            if '_phasecache' in vars(self):
+            if hasunfilteredcache(self, '_phasecache'):
             for k, ce in self._filecache.items():
                 if k == 'dirstate':
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -244,9 +244,12 @@
         self.name = func.__name__
     def __get__(self, obj, type=None):
         result = self.func(obj)
-        setattr(obj, self.name, result)
+        self.cachevalue(obj, result)
         return result
+    def cachevalue(self, obj, value):
+        setattr(obj, self.name, value)
 def pipefilter(s, cmd):
     '''filter string S through command CMD, returning its output'''
     p = subprocess.Popen(cmd, shell=True, close_fds=closefds,

More information about the Mercurial-devel mailing list