mercurial/scmutil.py
changeset 40424 7caf632e30c3
parent 40423 597bb5a6867f
child 40635 acd17caa699a
equal deleted inserted replaced
40423:597bb5a6867f 40424:7caf632e30c3
  1247 
  1247 
  1248     On first access, the files defined as arguments are stat()ed and the
  1248     On first access, the files defined as arguments are stat()ed and the
  1249     results cached. The decorated function is called. The results are stashed
  1249     results cached. The decorated function is called. The results are stashed
  1250     away in a ``_filecache`` dict on the object whose method is decorated.
  1250     away in a ``_filecache`` dict on the object whose method is decorated.
  1251 
  1251 
  1252     On subsequent access, the cached result is returned.
  1252     On subsequent access, the cached result is used as it is set to the
  1253 
  1253     instance dictionary.
  1254     On external property set operations, stat() calls are performed and the new
  1254 
  1255     value is cached.
  1255     On external property set/delete operations, the caller must update the
  1256 
  1256     corresponding _filecache entry appropriately. Use __class__.<attr>.set()
  1257     On property delete operations, cached data is removed.
  1257     instead of directly setting <attr>.
  1258 
  1258 
  1259     When using the property API, cached data is always returned, if available:
  1259     When using the property API, the cached data is always used if available.
  1260     no stat() is performed to check if the file has changed and if the function
  1260     No stat() is performed to check if the file has changed.
  1261     needs to be called to reflect file changes.
       
  1262 
  1261 
  1263     Others can muck about with the state of the ``_filecache`` dict. e.g. they
  1262     Others can muck about with the state of the ``_filecache`` dict. e.g. they
  1264     can populate an entry before the property's getter is called. In this case,
  1263     can populate an entry before the property's getter is called. In this case,
  1265     entries in ``_filecache`` will be used during property operations,
  1264     entries in ``_filecache`` will be used during property operations,
  1266     if available. If the underlying file changes, it is up to external callers
  1265     if available. If the underlying file changes, it is up to external callers
  1289 
  1288 
  1290     def __get__(self, obj, type=None):
  1289     def __get__(self, obj, type=None):
  1291         # if accessed on the class, return the descriptor itself.
  1290         # if accessed on the class, return the descriptor itself.
  1292         if obj is None:
  1291         if obj is None:
  1293             return self
  1292             return self
  1294         # do we need to check if the file changed?
  1293 
  1295         try:
  1294         assert self.sname not in obj.__dict__
  1296             return obj.__dict__[self.sname]
       
  1297         except KeyError:
       
  1298             pass
       
  1299 
  1295 
  1300         entry = obj._filecache.get(self.name)
  1296         entry = obj._filecache.get(self.name)
  1301 
  1297 
  1302         if entry:
  1298         if entry:
  1303             if entry.changed():
  1299             if entry.changed():
  1313             obj._filecache[self.name] = entry
  1309             obj._filecache[self.name] = entry
  1314 
  1310 
  1315         obj.__dict__[self.sname] = entry.obj
  1311         obj.__dict__[self.sname] = entry.obj
  1316         return entry.obj
  1312         return entry.obj
  1317 
  1313 
  1318     def __set__(self, obj, value):
  1314     # don't implement __set__(), which would make __dict__ lookup as slow as
       
  1315     # function call.
       
  1316 
       
  1317     def set(self, obj, value):
  1319         if self.name not in obj._filecache:
  1318         if self.name not in obj._filecache:
  1320             # we add an entry for the missing value because X in __dict__
  1319             # we add an entry for the missing value because X in __dict__
  1321             # implies X in _filecache
  1320             # implies X in _filecache
  1322             paths = [self.join(obj, path) for path in self.paths]
  1321             paths = [self.join(obj, path) for path in self.paths]
  1323             ce = filecacheentry(paths, False)
  1322             ce = filecacheentry(paths, False)
  1325         else:
  1324         else:
  1326             ce = obj._filecache[self.name]
  1325             ce = obj._filecache[self.name]
  1327 
  1326 
  1328         ce.obj = value # update cached copy
  1327         ce.obj = value # update cached copy
  1329         obj.__dict__[self.sname] = value # update copy returned by obj.x
  1328         obj.__dict__[self.sname] = value # update copy returned by obj.x
  1330 
       
  1331     def __delete__(self, obj):
       
  1332         try:
       
  1333             del obj.__dict__[self.sname]
       
  1334         except KeyError:
       
  1335             raise AttributeError(self.sname)
       
  1336 
  1329 
  1337 def extdatasource(repo, source):
  1330 def extdatasource(repo, source):
  1338     """Gather a map of rev -> value dict from the specified source
  1331     """Gather a map of rev -> value dict from the specified source
  1339 
  1332 
  1340     A source spec is treated as a URL, with a special case shell: type
  1333     A source spec is treated as a URL, with a special case shell: type