comparison mercurial/localrepo.py @ 18013:98c867ac1330

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.
author Pierre-Yves David <pierre-yves.david@logilab.fr>
date Mon, 08 Oct 2012 20:02:20 +0200
parents 67c874d14c2c
children a39fe76c4c65
comparison
equal deleted inserted replaced
18012:848c428bb5ee 18013:98c867ac1330
20 20
21 class storecache(filecache): 21 class storecache(filecache):
22 """filecache for files in the store""" 22 """filecache for files in the store"""
23 def join(self, obj, fname): 23 def join(self, obj, fname):
24 return obj.sjoin(fname) 24 return obj.sjoin(fname)
25
26 class unfilteredpropertycache(propertycache):
27 """propertycache that apply to unfiltered repo only"""
28
29 def __get__(self, repo, type=None):
30 return super(unfilteredpropertycache, self).__get__(repo.unfiltered())
31
32 class filteredpropertycache(propertycache):
33 """propertycache that must take filtering in account"""
34
35 def cachevalue(self, obj, value):
36 object.__setattr__(obj, self.name, value)
37
38
39 def hasunfilteredcache(repo, name):
40 """check if an repo and a unfilteredproperty cached value for <name>"""
41 return name in vars(repo.unfiltered())
25 42
26 def unfilteredmeth(orig): 43 def unfilteredmeth(orig):
27 """decorate method that always need to be run on unfiltered version""" 44 """decorate method that always need to be run on unfiltered version"""
28 def wrapper(repo, *args, **kwargs): 45 def wrapper(repo, *args, **kwargs):
29 return orig(repo.unfiltered(), *args, **kwargs) 46 return orig(repo.unfiltered(), *args, **kwargs)
302 # message is rare enough to not be translated 319 # message is rare enough to not be translated
303 msg = 'obsolete feature not enabled but %i markers found!\n' 320 msg = 'obsolete feature not enabled but %i markers found!\n'
304 self.ui.warn(msg % len(list(store))) 321 self.ui.warn(msg % len(list(store)))
305 return store 322 return store
306 323
307 @propertycache 324 @unfilteredpropertycache
308 def hiddenrevs(self): 325 def hiddenrevs(self):
309 """hiddenrevs: revs that should be hidden by command and tools 326 """hiddenrevs: revs that should be hidden by command and tools
310 327
311 This set is carried on the repo to ease initialization and lazy 328 This set is carried on the repo to ease initialization and lazy
312 loading; it'll probably move back to changelog for efficiency and 329 loading; it'll probably move back to changelog for efficiency and
490 '(please commit .hgtags manually)')) 507 '(please commit .hgtags manually)'))
491 508
492 self.tags() # instantiate the cache 509 self.tags() # instantiate the cache
493 self._tag(names, node, message, local, user, date) 510 self._tag(names, node, message, local, user, date)
494 511
495 @propertycache 512 @filteredpropertycache
496 def _tagscache(self): 513 def _tagscache(self):
497 '''Returns a tagscache object that contains various tags related 514 '''Returns a tagscache object that contains various tags related
498 caches.''' 515 caches.'''
499 516
500 # This simplifies its cache management by having one decorated 517 # This simplifies its cache management by having one decorated
877 data = fn(data, cmd, ui=self.ui, repo=self, filename=filename) 894 data = fn(data, cmd, ui=self.ui, repo=self, filename=filename)
878 break 895 break
879 896
880 return data 897 return data
881 898
882 @propertycache 899 @unfilteredpropertycache
883 def _encodefilterpats(self): 900 def _encodefilterpats(self):
884 return self._loadfilter('encode') 901 return self._loadfilter('encode')
885 902
886 @propertycache 903 @unfilteredpropertycache
887 def _decodefilterpats(self): 904 def _decodefilterpats(self):
888 return self._loadfilter('decode') 905 return self._loadfilter('decode')
889 906
890 def adddatafilter(self, name, filter): 907 def adddatafilter(self, name, filter):
891 self._datafilters[name] = filter 908 self._datafilters[name] = filter
1047 # invalidated. 1064 # invalidated.
1048 self.destroyed() 1065 self.destroyed()
1049 return 0 1066 return 0
1050 1067
1051 def invalidatecaches(self): 1068 def invalidatecaches(self):
1052 def delcache(name): 1069
1053 try: 1070 if '_tagscache' in vars(self):
1054 delattr(self, name) 1071 # can't use delattr on proxy
1055 except AttributeError: 1072 del self.__dict__['_tagscache']
1056 pass
1057
1058 delcache('_tagscache')
1059 1073
1060 self.unfiltered()._branchcache = None # in UTF-8 1074 self.unfiltered()._branchcache = None # in UTF-8
1061 self.unfiltered()._branchcachetip = None 1075 self.unfiltered()._branchcachetip = None
1062 obsolete.clearobscaches(self) 1076 obsolete.clearobscaches(self)
1063 1077
1068 1082
1069 This is different to dirstate.invalidate() that it doesn't always 1083 This is different to dirstate.invalidate() that it doesn't always
1070 rereads the dirstate. Use dirstate.invalidate() if you want to 1084 rereads the dirstate. Use dirstate.invalidate() if you want to
1071 explicitly read the dirstate again (i.e. restoring it to a previous 1085 explicitly read the dirstate again (i.e. restoring it to a previous
1072 known good state).''' 1086 known good state).'''
1073 if 'dirstate' in self.__dict__: 1087 if hasunfilteredcache(self, 'dirstate'):
1074 for k in self.dirstate._filecache: 1088 for k in self.dirstate._filecache:
1075 try: 1089 try:
1076 delattr(self.dirstate, k) 1090 delattr(self.dirstate, k)
1077 except AttributeError: 1091 except AttributeError:
1078 pass 1092 pass
1125 l.lock() 1139 l.lock()
1126 return l 1140 return l
1127 1141
1128 def unlock(): 1142 def unlock():
1129 self.store.write() 1143 self.store.write()
1130 if '_phasecache' in vars(self): 1144 if hasunfilteredcache(self, '_phasecache'):
1131 self._phasecache.write() 1145 self._phasecache.write()
1132 for k, ce in self._filecache.items(): 1146 for k, ce in self._filecache.items():
1133 if k == 'dirstate': 1147 if k == 'dirstate':
1134 continue 1148 continue
1135 ce.refresh() 1149 ce.refresh()