# HG changeset patch # User Pierre-Yves David # Date 1349719340 -7200 # Node ID 98c867ac13307b865eaf361a31ef7b3b84b7e73c # Parent 848c428bb5ee511c12358de3cc04a6189601384e clfilter: add a propertycache that must be unfiltered Some of the localrepo property caches must be computed unfiltered and stored globally. Some others 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 checking for cached values on unfiltered repos. 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 -r 848c428bb5ee -r 98c867ac1330 mercurial/localrepo.py --- a/mercurial/localrepo.py Mon Oct 08 18:11:56 2012 +0200 +++ b/mercurial/localrepo.py Mon Oct 08 20:02:20 2012 +0200 @@ -23,6 +23,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 """ + return name in vars(repo.unfiltered()) + def unfilteredmeth(orig): """decorate method that always need to be run on unfiltered version""" def wrapper(repo, *args, **kwargs): @@ -304,7 +321,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 @@ -492,7 +509,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 caches.''' @@ -879,11 +896,11 @@ return data - @propertycache + @unfilteredpropertycache def _encodefilterpats(self): return self._loadfilter('encode') - @propertycache + @unfilteredpropertycache def _decodefilterpats(self): return self._loadfilter('decode') @@ -1049,13 +1066,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 @@ -1070,7 +1084,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: try: delattr(self.dirstate, k) @@ -1127,7 +1141,7 @@ def unlock(): self.store.write() - if '_phasecache' in vars(self): + if hasunfilteredcache(self, '_phasecache'): self._phasecache.write() for k, ce in self._filecache.items(): if k == 'dirstate': diff -r 848c428bb5ee -r 98c867ac1330 mercurial/util.py --- a/mercurial/util.py Mon Oct 08 18:11:56 2012 +0200 +++ b/mercurial/util.py Mon Oct 08 20:02:20 2012 +0200 @@ -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,