[PATCH 02 of 11] scmutil: add filecache, a smart property-like decorator that compares stat info

Idan Kamara idankk86 at gmail.com
Sat Jul 16 14:34:33 UTC 2011


# HG changeset patch
# User Idan Kamara <idankk86 at gmail.com>
# Date 1310227619 -10800
# Node ID b99305dd59279aec962e23da2a362e0d8b785965
# Parent  d36f5aec2f9e4214fafe048bccd0bb47ac5f9c16
scmutil: add filecache, a smart property-like decorator that compares stat info

The idea is being able to associate a file with a property, and watch
that file stat info for modifications when we decide it's important for it to
be up-to-date. Once it changes, we recreate the object.

As a consequence, localrepo.invalidate() will become much less expensive in the
case where nothing changed on-disk.

diff -r d36f5aec2f9e -r b99305dd5927 mercurial/scmutil.py
--- a/mercurial/scmutil.py	Sat Jul 16 15:30:43 2011 +0300
+++ b/mercurial/scmutil.py	Sat Jul 09 19:06:59 2011 +0300
@@ -709,3 +709,41 @@
         raise error.RequirementError(_("unknown repository format: "
             "requires features '%s' (upgrade Mercurial)") % "', '".join(missings))
     return requirements
+
+class filecache(object):
+    '''A property like decorator that tracks a file under .hg/ for updates.
+
+    Records stat info when called in _invalidatecache.
+
+    On subsequent calls, compares old stat info with new info, and recreates
+    the object when needed, updating the new stat info in _invalidatecache.'''
+    def __init__(self, path, instore=False):
+        self.path = path
+        self.instore = instore
+
+    def __call__(self, func):
+        self.func = func
+        self.name = func.__name__
+        return self
+
+    def __get__(self, obj, type=None):
+        path = self.instore and obj.sjoin(self.path) or obj.join(self.path)
+
+        if self.name in obj._invalidatecache:
+            cacheentry = obj._invalidatecache[self.name]
+            stat = util.stat(path)
+
+            if stat != cacheentry[1]:
+                cacheentry[1] = stat
+                result = cacheentry[0] = self.func(obj)
+            else:
+                result = cacheentry[0]
+        else:
+            # stat -before- reading so our cache doesn't lie if someone
+            # modifies between the time we read+stat it
+            stat = util.stat(path)
+            result = self.func(obj)
+            obj._invalidatecache[self.name] = [result, stat, path]
+
+        setattr(obj, self.name, result)
+        return result



More information about the Mercurial-devel mailing list