2
0
Эх сурвалжийг харах

Add add_pack and add_thin_pack methods to MemoryObjectStore.

Closes #97.

Signed-off-by: Jelmer Vernooij <jelmer@samba.org>

Conflicts:
	NEWS
David Bennett 11 жил өмнө
parent
commit
1b63e1e19b

+ 3 - 0
NEWS

@@ -22,6 +22,9 @@
   * Support thin packs in Pack.iterobjects() and Pack.get_raw().
   * Support thin packs in Pack.iterobjects() and Pack.get_raw().
     (William Grant)
     (William Grant)
 
 
+  * Add `MemoryObjectStore.add_pack` and `MemoryObjectStore.add_thin_pack` methods.
+    (David Bennett)
+
 0.9.0	2013-05-31
 0.9.0	2013-05-31
 
 
  BUG FIXES
  BUG FIXES

+ 61 - 0
dulwich/object_store.py

@@ -21,6 +21,7 @@
 """Git object store interfaces and implementation."""
 """Git object store interfaces and implementation."""
 
 
 
 
+from cStringIO import StringIO
 import errno
 import errno
 import itertools
 import itertools
 import os
 import os
@@ -50,6 +51,7 @@ from dulwich.objects import (
 from dulwich.pack import (
 from dulwich.pack import (
     Pack,
     Pack,
     PackData,
     PackData,
+    PackInflater,
     iter_sha1,
     iter_sha1,
     write_pack_header,
     write_pack_header,
     write_pack_index_v2,
     write_pack_index_v2,
@@ -725,6 +727,65 @@ class MemoryObjectStore(BaseObjectStore):
         for obj, path in objects:
         for obj, path in objects:
             self._data[obj.id] = obj
             self._data[obj.id] = obj
 
 
+    def add_pack(self):
+        """Add a new pack to this object store.
+
+        Because this object store doesn't support packs, we extract and add the
+        individual objects.
+
+        :return: Fileobject to write to and a commit function to
+            call when the pack is finished.
+        """
+        f = StringIO()
+        def commit():
+            p = PackData.from_file(StringIO(f.getvalue()), f.tell())
+            f.close()
+            for obj in PackInflater.for_pack_data(p):
+                self._data[obj.id] = obj
+        return f, commit
+
+    def _complete_thin_pack(self, f, indexer):
+        """Complete a thin pack by adding external references.
+
+        :param f: Open file object for the pack.
+        :param indexer: A PackIndexer for indexing the pack.
+        """
+        entries = list(indexer)
+
+        # Update the header with the new number of objects.
+        f.seek(0)
+        write_pack_header(f, len(entries) + len(indexer.ext_refs()))
+
+        # Rescan the rest of the pack, computing the SHA with the new header.
+        new_sha = compute_file_sha(f, end_ofs=-20)
+
+        # Complete the pack.
+        for ext_sha in indexer.ext_refs():
+            assert len(ext_sha) == 20
+            type_num, data = self.get_raw(ext_sha)
+            write_pack_object(f, type_num, data, sha=new_sha)
+        pack_sha = new_sha.digest()
+        f.write(pack_sha)
+
+    def add_thin_pack(self, read_all, read_some):
+        """Add a new thin pack to this object store.
+
+        Thin packs are packs that contain deltas with parents that exist outside
+        the pack. Because this object store doesn't support packs, we extract
+        and add the individual objects.
+
+        :param read_all: Read function that blocks until the number of requested
+            bytes are read.
+        :param read_some: Read function that returns at least one byte, but may
+            not return the number of bytes requested.
+        """
+        f, commit = self.add_pack()
+        indexer = PackIndexer(f, resolve_ext_ref=self.get_raw)
+        copier = PackStreamCopier(read_all, read_some, f, delta_iter=indexer)
+        copier.verify()
+        self._complete_thin_pack(f, indexer)
+        commit()
+
 
 
 class ObjectImporter(object):
 class ObjectImporter(object):
     """Interface for importing objects."""
     """Interface for importing objects."""

+ 21 - 0
dulwich/tests/test_object_store.py

@@ -195,6 +195,27 @@ class MemoryObjectStoreTests(ObjectStoreTests, TestCase):
         TestCase.setUp(self)
         TestCase.setUp(self)
         self.store = MemoryObjectStore()
         self.store = MemoryObjectStore()
 
 
+    def test_add_pack(self):
+        o = MemoryObjectStore()
+        f, commit = o.add_pack()
+        b = make_object(Blob, data="more yummy data")
+        write_pack_objects(f, [(b, None)])
+        commit()
+
+    def test_add_thin_pack(self):
+        o = MemoryObjectStore()
+        blob = make_object(Blob, data='yummy data')
+        o.add_object(blob)
+
+        f = StringIO()
+        entries = build_pack(f, [
+          (REF_DELTA, (blob.id, 'more yummy data')),
+          ], store=o)
+        o.add_thin_pack(f.read, None)
+        packed_blob_sha = sha_to_hex(entries[0][3])
+        self.assertEqual((Blob.type_num, 'more yummy data'),
+                         o.get_raw(packed_blob_sha))
+
 
 
 class PackBasedObjectStoreTests(ObjectStoreTests):
 class PackBasedObjectStoreTests(ObjectStoreTests):