Переглянути джерело

Add extra base class for DiskObjectStore.

Jelmer Vernooij 15 роки тому
батько
коміт
634b2cd1f0
1 змінених файлів з 81 додано та 66 видалено
  1. 81 66
      dulwich/object_store.py

+ 81 - 66
dulwich/object_store.py

@@ -237,21 +237,10 @@ class BaseObjectStore(object):
         return self.iter_shas(self.find_missing_objects(have, want))
 
 
-class DiskObjectStore(BaseObjectStore):
-    """Git-style object store that exists on disk."""
-
-    def __init__(self, path):
-        """Open an object store.
+class PackBasedObjectStore(BaseObjectStore):
 
-        :param path: Path of the object store.
-        """
-        self.path = path
+    def __init__(self):
         self._pack_cache = None
-        self.pack_dir = os.path.join(self.path, PACKDIR)
-
-    def contains_loose(self, sha):
-        """Check if a particular object is present by SHA1 and is loose."""
-        return self._get_shafile(sha) is not None
 
     def contains_packed(self, sha):
         """Check if a particular object is present by SHA1 and is packed."""
@@ -260,10 +249,15 @@ class DiskObjectStore(BaseObjectStore):
                 return True
         return False
 
-    def __iter__(self):
-        """Iterate over the SHAs that are present in this store."""
-        iterables = self.packs + [self._iter_shafile_shas()]
-        return itertools.chain(*iterables)
+    def _load_packs(self):
+        raise NotImplementedError(self._load_packs)
+
+    def _add_known_pack(self, pack):
+        """Add a newly appeared pack to the cache by path.
+
+        """
+        if self._pack_cache is not None:
+            self._pack_cache.append(pack)
 
     @property
     def packs(self):
@@ -272,6 +266,72 @@ class DiskObjectStore(BaseObjectStore):
             self._pack_cache = self._load_packs()
         return self._pack_cache
 
+    def _iter_loose_objects(self):
+        raise NotImplementedError(self._iter_loose_objects)
+
+    def _get_loose_object(self, sha):
+        raise NotImplementedError(self._get_loose_object)
+
+    def __iter__(self):
+        """Iterate over the SHAs that are present in this store."""
+        iterables = self.packs + [self._iter_loose_objects()]
+        return itertools.chain(*iterables)
+
+    def contains_loose(self, sha):
+        """Check if a particular object is present by SHA1 and is loose."""
+        return self._get_loose_object(sha) is not None
+
+    def get_raw(self, name):
+        """Obtain the raw text for an object.
+        
+        :param name: sha for the object.
+        :return: tuple with object type and object contents.
+        """
+        if len(name) == 40:
+            sha = hex_to_sha(name)
+            hexsha = name
+        elif len(name) == 20:
+            sha = name
+            hexsha = None
+        else:
+            raise AssertionError
+        for pack in self.packs:
+            try:
+                return pack.get_raw(sha)
+            except KeyError:
+                pass
+        if hexsha is None: 
+            hexsha = sha_to_hex(name)
+        ret = self._get_loose_object(hexsha)
+        if ret is not None:
+            return ret.type, ret.as_raw_string()
+        raise KeyError(hexsha)
+
+    def add_objects(self, objects):
+        """Add a set of objects to this object store.
+
+        :param objects: Iterable over objects, should support __len__.
+        """
+        if len(objects) == 0:
+            # Don't bother writing an empty pack file
+            return
+        f, commit = self.add_pack()
+        write_pack_data(f, objects, len(objects))
+        commit()
+
+
+class DiskObjectStore(PackBasedObjectStore):
+    """Git-style object store that exists on disk."""
+
+    def __init__(self, path):
+        """Open an object store.
+
+        :param path: Path of the object store.
+        """
+        super(DiskObjectStore, self).__init__()
+        self.path = path
+        self.pack_dir = os.path.join(self.path, PACKDIR)
+
     def _load_packs(self):
         if not os.path.exists(self.pack_dir):
             return []
@@ -285,58 +345,25 @@ class DiskObjectStore(BaseObjectStore):
         suffix_len = len(".pack")
         return [Pack(f[:-suffix_len]) for _, f in pack_files]
 
-    def _add_known_pack(self, path):
-        """Add a newly appeared pack to the cache by path.
-
-        """
-        if self._pack_cache is not None:
-            self._pack_cache.append(Pack(path))
-
     def _get_shafile_path(self, sha):
         dir = sha[:2]
         file = sha[2:]
         # Check from object dir
         return os.path.join(self.path, dir, file)
 
-    def _iter_shafile_shas(self):
+    def _iter_loose_objects(self):
         for base in os.listdir(self.path):
             if len(base) != 2:
                 continue
             for rest in os.listdir(os.path.join(self.path, base)):
                 yield base+rest
 
-    def _get_shafile(self, sha):
+    def _get_loose_object(self, sha):
         path = self._get_shafile_path(sha)
         if os.path.exists(path):
           return ShaFile.from_file(path)
         return None
 
-    def get_raw(self, name):
-        """Obtain the raw text for an object.
-        
-        :param name: sha for the object.
-        :return: tuple with object type and object contents.
-        """
-        if len(name) == 40:
-            sha = hex_to_sha(name)
-            hexsha = name
-        elif len(name) == 20:
-            sha = name
-            hexsha = None
-        else:
-            raise AssertionError
-        for pack in self.packs:
-            try:
-                return pack.get_raw(sha)
-            except KeyError:
-                pass
-        if hexsha is None: 
-            hexsha = sha_to_hex(name)
-        ret = self._get_shafile(hexsha)
-        if ret is not None:
-            return ret.type, ret.as_raw_string()
-        raise KeyError(hexsha)
-
     def move_in_thin_pack(self, path):
         """Move a specific file containing a pack into the pack directory.
 
@@ -362,7 +389,7 @@ class DiskObjectStore(BaseObjectStore):
         newbasename = os.path.join(self.pack_dir, "pack-%s" % pack_sha)
         os.rename(temppath+".pack", newbasename+".pack")
         os.rename(temppath+".idx", newbasename+".idx")
-        self._add_known_pack(newbasename)
+        self._add_known_pack(Pack(newbasename))
 
     def move_in_pack(self, path):
         """Move a specific file containing a pack into the pack directory.
@@ -379,7 +406,7 @@ class DiskObjectStore(BaseObjectStore):
         write_pack_index_v2(basename+".idx", entries, p.get_stored_checksum())
         p.close()
         os.rename(path, basename + ".pack")
-        self._add_known_pack(basename)
+        self._add_known_pack(Pack(basename))
 
     def add_thin_pack(self):
         """Add a new thin pack to this object store.
@@ -428,18 +455,6 @@ class DiskObjectStore(BaseObjectStore):
         finally:
             f.close()
 
-    def add_objects(self, objects):
-        """Add a set of objects to this object store.
-
-        :param objects: Iterable over objects, should support __len__.
-        """
-        if len(objects) == 0:
-            # Don't bother writing an empty pack file
-            return
-        f, commit = self.add_pack()
-        write_pack_data(f, objects, len(objects))
-        commit()
-
 
 class MemoryObjectStore(BaseObjectStore):
     """Object store that keeps all objects in memory."""