Combine manifest dict and flags dict into a single object
authorMatt Mackall <mpm@selenic.com>
Wed, 09 Aug 2006 14:53:03 -0500
changeset 2835 a9f5d4149123
parent 2834 35af2e56f15a
child 2836 e78cad1f6b1f
Combine manifest dict and flags dict into a single object This gets rid of the need to track two objects and might save memory. This might be faster implemented as a subclassed dict with auxiliary functions to access a sparse flags dict.
mercurial/manifest.py
--- a/mercurial/manifest.py	Wed Jul 19 19:11:50 2006 -0500
+++ b/mercurial/manifest.py	Wed Aug 09 14:53:03 2006 -0500
@@ -10,26 +10,39 @@
 from demandload import *
 demandload(globals(), "array bisect struct")
 
-class manifestflags(dict):
+class manifestdict(dict):
     def __init__(self, mapping={}):
         dict.__init__(self, mapping)
     def __getitem__(self, f):
-        raise "oops"
+        return self.node(f)
+    def get(self, f, default=None):
+        try:
+            return dict.__getitem__(self, f)[:20]
+        except KeyError:
+            return default
+    def __setitem__(self, f, node):
+        fl = self.flags(f)
+        dict.__setitem__(self, f, node + fl)
+    def node(self, f):
+        return dict.__getitem__(self, f)[:20]
     def flags(self, f):
-        return dict.__getitem__(self, f)
+        return dict.get(self, f, "")[20:]
     def execf(self, f):
         "test for executable in manifest flags"
-        return "x" in self.get(f, "")
+        return "x" in self.flags(f)
     def linkf(self, f):
         "test for symlink in manifest flags"
-        return "l" in self.get(f, "")
+        return "l" in self.flags(f)
+    def rawset(self, f, node, flags):
+        dict.__setitem__(self, f, node + flags)
     def set(self, f, execf=False, linkf=False):
+        n = dict.get(self, f, nullid)[:20]
         fl = ""
         if execf: fl = "x"
         if linkf: fl = "l"
-        self[f] = fl
+        dict.__setitem__(self, f, n + fl)
     def copy(self):
-        return manifestflags(dict.copy(self))
+        return manifestdict(dict.copy(self))
 
 class manifest(revlog):
     def __init__(self, opener, defversion=REVLOGV0):
@@ -39,26 +52,21 @@
                         defversion)
 
     def read(self, node):
-        if node == nullid: return {} # don't upset local cache
+        if node == nullid: return manifestdict() # don't upset local cache
         if self.mapcache and self.mapcache[0] == node:
             return self.mapcache[1]
         text = self.revision(node)
-        map = {}
-        flag = manifestflags()
         self.listcache = array.array('c', text)
         lines = text.splitlines(1)
+        mapping = manifestdict()
         for l in lines:
             (f, n) = l.split('\0')
-            map[f] = bin(n[:40])
-            flag[f] = n[40:-1]
-        self.mapcache = (node, map, flag)
-        return map
+            mapping.rawset(f, bin(n[:40]), n[40:-1])
+        self.mapcache = (node, mapping)
+        return mapping
 
     def readflags(self, node):
-        if node == nullid: return manifestflags() # don't upset local cache
-        if not self.mapcache or self.mapcache[0] != node:
-            self.read(node)
-        return self.mapcache[2]
+        return self.read(node)
 
     def diff(self, a, b):
         return mdiff.textdiff(str(a), str(b))
@@ -107,7 +115,7 @@
         '''look up entry for a single file efficiently.
         return (node, flag) pair if found, (None, None) if not.'''
         if self.mapcache and node == self.mapcache[0]:
-            return self.mapcache[1].get(f), self.mapcache[2].get(f)
+            return self.mapcache[1].get(f), self.mapcache[1].flags(f)
         text = self.revision(node)
         start, end = self._search(text, f)
         if start == end:
@@ -201,6 +209,6 @@
 
         n = self.addrevision(buffer(self.listcache), transaction, link, p1,  \
                              p2, cachedelta)
-        self.mapcache = (n, map, flags)
+        self.mapcache = (n, map)
 
         return n