Преглед изворни кода

Resolve deltas using other packs.

Jelmer Vernooij пре 16 година
родитељ
комит
f18c916ad8
3 измењених фајлова са 44 додато и 19 уклоњено
  1. 7 5
      dulwich/pack.py
  2. 36 12
      dulwich/repo.py
  3. 1 2
      dulwich/tests/test_repository.py

+ 7 - 5
dulwich/pack.py

@@ -684,7 +684,7 @@ def write_pack_index_v2(filename, entries, pack_checksum):
     """
     f = open(filename, 'w')
     f = SHA1Writer(f)
-    f.write('\377tOc')
+    f.write('\377tOc') # Magic!
     f.write(struct.pack(">L", 2))
     fan_out_table = defaultdict(lambda: 0)
     for (name, offset, entry_checksum) in entries:
@@ -761,26 +761,28 @@ class Pack(object):
         """Check whether this pack contains a particular SHA1."""
         return (self.idx.object_index(sha1) is not None)
 
-    def _get_text(self, sha1):
+    def get_raw(self, sha1, resolve_ref=None):
+        if resolve_ref is None:
+            resolve_ref = self.get_raw
         offset = self.idx.object_index(sha1)
         if offset is None:
             raise KeyError(sha1)
 
         type, obj = self.data.get_object_at(offset)
         assert isinstance(offset, int)
-        return resolve_object(offset, type, obj, self._get_text, 
+        return resolve_object(offset, type, obj, resolve_ref,
             self.data.get_object_at)
 
     def __getitem__(self, sha1):
         """Retrieve the specified SHA1."""
-        type, uncomp = self._get_text(sha1)
+        type, uncomp = self.get_raw(sha1)
         return ShaFile.from_raw_string(type, uncomp)
 
     def iterobjects(self):
         for offset, type, obj in self.data.iterobjects():
             assert isinstance(offset, int)
             yield ShaFile.from_raw_string(
-                    *resolve_object(offset, type, obj, self._get_text, 
+                    *resolve_object(offset, type, obj, self.get_raw, 
                 self.data.get_object_at))
 
 

+ 36 - 12
dulwich/repo.py

@@ -20,7 +20,7 @@
 import os
 
 from commit import Commit
-from errors import MissingCommitError
+from errors import MissingCommitError, NotBlobError, NotTreeError, NotCommitError
 from objects import (ShaFile,
                      Commit,
                      Tree,
@@ -120,10 +120,20 @@ class Repo(object):
     return self.ref('HEAD')
 
   def _get_object(self, sha, cls):
-    return self.object_store.get_object(sha, cls)
+    ret = self.get_object(sha)
+    if ret._type != cls._type:
+        if cls is Commit:
+            raise NotCommitError(ret)
+        elif cls is Blob:
+            raise NotBlobError(ret)
+        elif cls is Tree:
+            raise NotTreeError(ret)
+        else:
+            raise Exception("Type invalid: %r != %r" % (ret._type, cls._type))
+    return ret
 
   def get_object(self, sha):
-    return self._get_object(sha, ShaFile)
+    return self.object_store[sha]
 
   def get_parents(self, sha):
     return self.commit(sha).parents
@@ -154,8 +164,9 @@ class Repo(object):
     history = []
     while pending_commits != []:
       head = pending_commits.pop(0)
-      commit = self.commit(head)
-      if commit is None:
+      try:
+          commit = self.commit(head)
+      except KeyError:
         raise MissingCommitError(head)
       if commit in history:
         continue
@@ -204,20 +215,33 @@ class ObjectStore(object):
             self._packs = list(load_packs(self.pack_dir()))
         return self._packs
 
-    def get_object(self, sha, cls):
-        assert len(sha) == 40, "Incorrect length sha: %s" % str(sha)
+    def _get_shafile(self, sha):
         dir = sha[:2]
         file = sha[2:]
         # Check from object dir
         path = os.path.join(self.path, dir, file)
         if os.path.exists(path):
-          return cls.from_file(path)
-        # Check from packs
+          return ShaFile.from_file(path)
+        return None
+
+    def get_raw(self, sha):
         for pack in self.packs:
             if sha in pack:
-                return pack[sha]
-        # Should this raise instead?
-        return None
+                return pack.get_raw(sha, self.get_raw)
+        # FIXME: Are pack deltas ever against on-disk shafiles ?
+        ret = self._get_shafile(sha)
+        if ret is not None:
+            return ret.as_raw_string()
+        raise KeyError(sha)
+
+    def __getitem__(self, sha):
+        assert len(sha) == 40, "Incorrect length sha: %s" % str(sha)
+        ret = self._get_shafile(sha)
+        if ret is not None:
+            return ret
+        # Check from packs
+        type, uncomp = self.get_raw(sha)
+        return ShaFile.from_raw_string(type, uncomp)
 
     def move_in_pack(self, path):
         p = PackData(path)

+ 1 - 2
dulwich/tests/test_repository.py

@@ -52,8 +52,7 @@ class RepositoryTests(unittest.TestCase):
 
   def test_get_object_non_existant(self):
     r = self.open_repo('a')
-    obj = r.get_object(missing_sha)
-    self.assertEqual(obj, None)
+    self.assertRaises(KeyError, r.get_object, missing_sha)
 
   def test_commit(self):
     r = self.open_repo('a')