← Back to team overview

dulwich-users team mailing list archive

[PATCH 25/33] pack: Fix a buffering issue with PackStreamReader; add tests.

 

From: Dave Borowitz <dborowitz@xxxxxxxxxx>

Change-Id: I2695ce332114e213239efaa00bd46b423a670d5c
---
 dulwich/pack.py            |    7 ++++++
 dulwich/tests/test_pack.py |   48 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+), 0 deletions(-)

diff --git a/dulwich/pack.py b/dulwich/pack.py
index 6c1cb29..0a3ce6c 100644
--- a/dulwich/pack.py
+++ b/dulwich/pack.py
@@ -747,6 +747,13 @@ class PackStreamReader(object):
             buf.seek(0)
             self._rbuf = buf
 
+        if self._buf_len() < 20:
+            # If the read buffer is full, then the last read() got the whole
+            # trailer off the wire. If not, it means there is still some of the
+            # trailer to read. We need to read() all 20 bytes; N come from the
+            # read buffer and (20 - N) come from the wire.
+            self.read(20)
+
         pack_sha = ''.join(self._trailer)
         if pack_sha != self.sha.digest():
             raise ChecksumMismatch(sha_to_hex(pack_sha), self.sha.hexdigest())
diff --git a/dulwich/tests/test_pack.py b/dulwich/tests/test_pack.py
index 99ab899..6b735ce 100644
--- a/dulwich/tests/test_pack.py
+++ b/dulwich/tests/test_pack.py
@@ -49,6 +49,7 @@ from dulwich.objects import (
 from dulwich.pack import (
     OFS_DELTA,
     REF_DELTA,
+    DELTA_TYPES,
     MemoryPackIndex,
     Pack,
     PackData,
@@ -66,6 +67,7 @@ from dulwich.pack import (
     write_pack,
     unpack_object,
     compute_file_sha,
+    PackStreamReader,
     DeltaChainIterator,
     )
 from dulwich.tests import (
@@ -655,6 +657,52 @@ class DeltifyTests(TestCase):
             list(deltify_pack_objects([(b1, ""), (b2, "")])))
 
 
+class TestPackStreamReader(TestCase):
+
+    def test_read_objects_emtpy(self):
+        f = StringIO()
+        build_pack(f, [])
+        reader = PackStreamReader(f.read)
+        self.assertEqual(0, len(list(reader.read_objects())))
+
+    def test_read_objects(self):
+        f = StringIO()
+        entries = build_pack(f, [
+          (Blob.type_num, 'blob'),
+          (OFS_DELTA, (0, 'blob1')),
+          ])
+        reader = PackStreamReader(f.read)
+        objects = list(reader.read_objects(compute_crc32=True))
+        self.assertEqual(2, len(objects))
+
+        blob, delta = objects
+        bofs, btype, buncomp, blen, bcrc = blob
+        dofs, dtype, duncomp, dlen, dcrc = delta
+
+        self.assertEqual(entries[0][0], bofs)
+        self.assertEqual(Blob.type_num, btype)
+        self.assertEqual('blob', ''.join(buncomp))
+        self.assertEqual(dofs - bofs, blen)
+        self.assertEqual(entries[0][4], bcrc)
+
+        self.assertEqual(entries[1][0], dofs)
+        self.assertEqual(OFS_DELTA, dtype)
+        delta_ofs, delta_chunks = duncomp
+        self.assertEqual(dofs - bofs, delta_ofs)
+        self.assertEqual(create_delta('blob', 'blob1'), ''.join(delta_chunks))
+        self.assertEqual(len(f.getvalue()) - 20 - dofs, dlen)
+        self.assertEqual(entries[1][4], dcrc)
+
+    def test_read_objects_buffered(self):
+        f = StringIO()
+        build_pack(f, [
+          (Blob.type_num, 'blob'),
+          (OFS_DELTA, (0, 'blob1')),
+          ])
+        reader = PackStreamReader(f.read, zlib_bufsize=4)
+        self.assertEqual(2, len(list(reader.read_objects())))
+
+
 class TestPackIterator(DeltaChainIterator):
 
     _compute_crc32 = True
-- 
1.7.3.1



References