Browse Source

Fix crc32 overflow error in struct, raise KeyError if referenced objects can't be found rather than looping forever.

Jelmer Vernooij 16 years ago
parent
commit
e9ae5dfc6d
2 changed files with 25 additions and 13 deletions
  1. 3 4
      dulwich/client.py
  2. 22 9
      dulwich/pack.py

+ 3 - 4
dulwich/client.py

@@ -37,10 +37,9 @@ class SimpleFetchGraphWalker(object):
     def ack(self, ref):
     def ack(self, ref):
         if ref in self.heads:
         if ref in self.heads:
             self.heads.remove(ref)
             self.heads.remove(ref)
-        if not ref in self.parents:
-            return
-        for p in self.parents[ref]:
-            self.ack(p)
+        if ref in self.parents:
+            for p in self.parents[ref]:
+                self.ack(p)
 
 
     def next(self):
     def next(self):
         if self.heads:
         if self.heads:

+ 22 - 9
dulwich/pack.py

@@ -152,7 +152,7 @@ def resolve_object(offset, type, obj, get_ref, get_offset):
      (basename, delta) = obj
      (basename, delta) = obj
      assert isinstance(basename, str) and len(basename) == 20
      assert isinstance(basename, str) and len(basename) == 20
      assert isinstance(delta, str)
      assert isinstance(delta, str)
-     type, base_obj= get_ref(basename)
+     type, base_obj = get_ref(basename)
      assert isinstance(type, int)
      assert isinstance(type, int)
   type, base_text = resolve_object(offset, type, base_obj, get_ref, get_offset)
   type, base_text = resolve_object(offset, type, base_obj, get_ref, get_offset)
   return type, apply_delta(base_text, delta)
   return type, apply_delta(base_text, delta)
@@ -403,22 +403,35 @@ class PackData(object):
 
 
   def iterentries(self):
   def iterentries(self):
     found = {}
     found = {}
-    postponed = list(self.iterobjects())
-    while postponed:
-      (offset, type, obj) = postponed.pop(0)
+    at = {}
+    postponed = defaultdict(list)
+    class Postpone(Exception):
+        """Raised to postpone delta resolving."""
+        
+    def get_ref_text(sha):
+        if sha in found:
+            return found[sha]
+        raise Postpone, (sha, )
+    todo = list(self.iterobjects())
+    while todo:
+      (offset, type, obj) = todo.pop(0)
+      at[offset] = (type, obj)
       assert isinstance(offset, int)
       assert isinstance(offset, int)
       assert isinstance(type, int)
       assert isinstance(type, int)
       assert isinstance(obj, tuple) or isinstance(obj, str)
       assert isinstance(obj, tuple) or isinstance(obj, str)
       try:
       try:
-        type, obj = resolve_object(offset, type, obj, found.__getitem__, 
-            self.get_object_at)
-      except KeyError:
-        postponed.append((offset, type, obj))
+        type, obj = resolve_object(offset, type, obj, get_ref_delta,
+            at.__getitem__)
+      except Postpone, (sha, ):
+        postponed[sha].append((offset, type, obj))
       else:
       else:
         shafile = ShaFile.from_raw_string(type, obj)
         shafile = ShaFile.from_raw_string(type, obj)
         sha = shafile.sha().digest()
         sha = shafile.sha().digest()
         found[sha] = (type, obj)
         found[sha] = (type, obj)
         yield sha, offset, shafile.crc32()
         yield sha, offset, shafile.crc32()
+        todo += postponed.get(sha, [])
+    if postponed:
+        raise KeyError([sha_to_hex(h) for h in postponed.keys()])
 
 
   def sorted_entries(self):
   def sorted_entries(self):
     ret = list(self.iterentries())
     ret = list(self.iterentries())
@@ -683,7 +696,7 @@ def write_pack_index_v2(filename, entries, pack_checksum):
     for (name, offset, entry_checksum) in entries:
     for (name, offset, entry_checksum) in entries:
         f.write(name)
         f.write(name)
     for (name, offset, entry_checksum) in entries:
     for (name, offset, entry_checksum) in entries:
-        f.write(struct.pack(">L", entry_checksum))
+        f.write(struct.pack(">l", entry_checksum))
     for (name, offset, entry_checksum) in entries:
     for (name, offset, entry_checksum) in entries:
         # FIXME: handle if MSBit is set in offset
         # FIXME: handle if MSBit is set in offset
         f.write(struct.pack(">L", offset))
         f.write(struct.pack(">L", offset))