Browse Source

Merge upstream

John Carr 16 năm trước cách đây
mục cha
commit
6008e9e1a3

+ 13 - 15
dulwich/objects.py

@@ -56,10 +56,6 @@ def sha_to_hex(sha):
 class ShaFile(object):
   """A git SHA file."""
 
-  def _update_contents(self):
-    """Update the _contents from the _text"""
-    self._contents = [ord(c) for c in self._text]
-
   @classmethod
   def _parse_legacy_object(cls, map):
     """Parse a legacy object, creating it and setting object._text"""
@@ -85,7 +81,6 @@ class ShaFile(object):
     assert text[0] == "\0", "Size not followed by null"
     text = text[1:]
     object._text = text
-    object._update_contents()
     return object
 
   def as_raw_string(self):
@@ -107,7 +102,6 @@ class ShaFile(object):
       used += 1
     raw = map[used:]
     object._text = _decompress(raw)
-    object._update_contents()
     return object
 
   @classmethod
@@ -148,16 +142,11 @@ class ShaFile(object):
     obj = real_class()
     obj._num_type = type
     obj._text = string
-    obj._update_contents()
     obj._parse_text()
     return obj
 
   def _header(self):
-    return "%s %lu\0" % (self._type, len(self._contents))
-
-  def contents(self):
-    """The raw bytes of this object"""
-    return self._contents
+    return "%s %lu\0" % (self._type, len(self._text))
 
   def crc32(self):
     return zlib.crc32(self._text)
@@ -169,6 +158,10 @@ class ShaFile(object):
     ressha.update(self._text)
     return ressha
 
+  @property
+  def id(self):
+      return self.sha().hexdigest()
+
   def __eq__(self, other):
     """Return true id the sha of the two objects match.
 
@@ -183,7 +176,8 @@ class Blob(ShaFile):
 
   _type = blob_id
 
-  def text(self):
+  @property
+  def data(self):
     """The text contained within the blob object."""
     return self._text
 
@@ -199,7 +193,6 @@ class Blob(ShaFile):
     """Create a blob from a string."""
     shafile = cls()
     shafile._text = string
-    shafile._update_contents()
     return shafile
 
 
@@ -220,7 +213,6 @@ class Tag(ShaFile):
     """Create a blob from a string."""
     shafile = cls()
     shafile._text = string
-    shafile._update_contents()
     return shafile
 
 
@@ -344,26 +336,32 @@ class Commit(ShaFile):
     # XXX: There can be an encoding field.
     self._message = text[count:]
 
+  @property
   def tree(self):
     """Returns the tree that is the state of this commit"""
     return self._tree
 
+  @property
   def parents(self):
     """Return a list of parents of this commit."""
     return self._parents
 
+  @property
   def author(self):
     """Returns the name of the author of the commit"""
     return self._author
 
+  @property
   def committer(self):
     """Returns the name of the committer of the commit"""
     return self._committer
 
+  @property
   def message(self):
     """Returns the commit message"""
     return self._message
 
+  @property
   def commit_time(self):
     """Returns the timestamp of the commit.
     

+ 41 - 25
dulwich/pack.py

@@ -149,6 +149,7 @@ def resolve_object(offset, type, 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)
 
+
 class PackIndex(object):
   """An index in to a packfile.
 
@@ -170,7 +171,6 @@ class PackIndex(object):
     it whenever required.
     """
     self._filename = filename
-    assert os.path.exists(filename), "%s is not a pack index" % filename
     # Take the size now, so it can be checked each time we map the file to
     # ensure that it hasn't changed.
     self._size = os.path.getsize(filename)
@@ -479,10 +479,14 @@ class SHA1Writer(object):
         self.sha1.update(data)
         self.f.write(data)
 
-    def close(self):
+    def write_sha(self):
         sha = self.sha1.digest()
         assert len(sha) == 20
         self.f.write(sha)
+        return sha
+
+    def close(self):
+        sha = self.write_sha()
         self.f.close()
         return sha
 
@@ -524,24 +528,27 @@ def write_pack_object(f, type, object):
     return f.tell()
 
 
-def write_pack(filename, objects):
-    entries, data_sum = write_pack_data(filename + ".pack", objects)
+def write_pack(filename, objects, num_objects):
+    f = open(filename + ".pack", 'w')
+    try:
+        entries, data_sum = write_pack_data(f, objects, num_objects)
+    except:
+        f.close()
     write_pack_index_v2(filename + ".idx", entries, data_sum)
 
 
-def write_pack_data(filename, objects):
+def write_pack_data(f, objects, num_objects):
     """Write a new pack file.
 
     :param filename: The filename of the new pack file.
     :param objects: List of objects to write.
     :return: List with (name, offset, crc32 checksum) entries, pack checksum
     """
-    f = open(filename, 'w')
     entries = []
     f = SHA1Writer(f)
     f.write("PACK")               # Pack header
     f.write(struct.pack(">L", 2)) # Pack version
-    f.write(struct.pack(">L", len(objects))) # Number of objects in pack
+    f.write(struct.pack(">L", num_objects)) # Number of objects in pack
     for o in objects:
         sha1 = o.sha().digest()
         crc32 = o.crc32()
@@ -549,7 +556,7 @@ def write_pack_data(filename, objects):
         t, o = o.as_raw_string()
         offset = write_pack_object(f, t, o)
         entries.append((sha1, offset, crc32))
-    return entries, f.close()
+    return entries, f.write_sha()
 
 
 def write_pack_index_v1(filename, entries, pack_checksum):
@@ -674,54 +681,61 @@ class Pack(object):
 
     def __init__(self, basename):
         self._basename = basename
-        self._idx = PackIndex(basename + ".idx")
         self._data = None
+        self._idx = None
 
-    def _get_data(self):
+    @property
+    def data(self):
         if self._data is None:
             self._data = PackData(self._basename + ".pack")
-            assert len(self._idx) == len(self._data)
-            assert self._idx.get_stored_checksums()[0] == self._data.get_stored_checksum()
+            assert len(self.idx) == len(self._data)
+            assert self.idx.get_stored_checksums()[0] == self._data.get_stored_checksum()
         return self._data
 
+    @property
+    def idx(self):
+        if self._idx is None:
+            self._idx = PackIndex(self._basename + ".idx")
+        return self._idx
+
     def close(self):
         if self._data is not None:
             self._data.close()
-        self._idx.close()
+        self.idx.close()
 
     def __eq__(self, other):
-        return type(self) == type(other) and self._idx == other._idx
+        return type(self) == type(other) and self.idx == other.idx
 
     def __len__(self):
         """Number of entries in this pack."""
-        return len(self._idx)
+        return len(self.idx)
 
     def __repr__(self):
         return "Pack(%r)" % self._basename
 
     def __iter__(self):
         """Iterate over all the sha1s of the objects in this pack."""
-        return iter(self._idx)
+        return iter(self.idx)
 
     def check(self):
-        return self._idx.check() and self._get_data().check()
+        return self.idx.check() and self.data.check()
 
     def get_stored_checksum(self):
-        return self._get_data().get_stored_checksum()
+        return self.data.get_stored_checksum()
 
     def __contains__(self, sha1):
         """Check whether this pack contains a particular SHA1."""
-        return (self._idx.object_index(sha1) is not None)
+        return (self.idx.object_index(sha1) is not None)
 
     def _get_text(self, sha1):
-        offset = self._idx.object_index(sha1)
+        offset = self.idx.object_index(sha1)
         if offset is None:
             raise KeyError(sha1)
 
-        type, obj = self._get_data().get_object_at(offset)
+        type, obj = self.data.get_object_at(offset)
         assert isinstance(offset, int)
         return resolve_object(offset, type, obj, self._get_text, 
-            self._get_data().get_object_at)
+            self.data.get_object_at)
 
     def __getitem__(self, sha1):
         """Retrieve the specified SHA1."""
@@ -729,14 +743,16 @@ class Pack(object):
         return ShaFile.from_raw_string(type, uncomp)
 
     def iterobjects(self):
-        for offset, type, obj in self._get_data().iterobjects():
+        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, 
-                self._get_data().get_object_at))
+                self.data.get_object_at))
 
 
 def load_packs(path):
+    if not os.path.exists(path):
+        return
     for name in os.listdir(path):
         if name.endswith(".pack"):
-            yield Pack(os.path.join(path, name.rstrip(".pack")))
+            yield Pack(os.path.join(path, name[:-len(".pack")]))

+ 3 - 3
dulwich/repo.py

@@ -138,7 +138,7 @@ class Repo(object):
   def commit(self, sha):
     return self._get_object(sha, Commit)
 
-  def get_tree(self, sha):
+  def tree(self, sha):
     return self._get_object(sha, Tree)
 
   def get_blob(self, sha):
@@ -168,11 +168,11 @@ class Repo(object):
         continue
       i = 0
       for known_commit in history:
-        if known_commit.commit_time() > commit.commit_time():
+        if known_commit.commit_time > commit.commit_time:
           break
         i += 1
       history.insert(i, commit)
-      parents = commit.parents()
+      parents = commit.parents
       pending_commits += parents
     history.reverse()
     return history

+ 22 - 22
dulwich/tests/test_objects.py

@@ -48,25 +48,25 @@ class BlobReadTests(unittest.TestCase):
 
   def test_decompress_simple_blob(self):
     b = self.get_blob(a_sha)
-    self.assertEqual(b.text(), 'test 1\n')
+    self.assertEqual(b.data, 'test 1\n')
     self.assertEqual(b.sha().hexdigest(), a_sha)
 
   def test_parse_empty_blob_object(self):
     sha = 'e69de29bb2d1d6434b8b29ae775ad8c2e48c5391'
     b = self.get_blob(sha)
-    self.assertEqual(b.text(), '')
+    self.assertEqual(b.data, '')
     self.assertEqual(b.sha().hexdigest(), sha)
 
   def test_create_blob_from_string(self):
     string = 'test 2\n'
     b = Blob.from_string(string)
-    self.assertEqual(b.text(), string)
+    self.assertEqual(b.data, string)
     self.assertEqual(b.sha().hexdigest(), b_sha)
 
   def test_parse_legacy_blob(self):
     string = 'test 3\n'
     b = self.get_blob(c_sha)
-    self.assertEqual(b.text(), string)
+    self.assertEqual(b.data, string)
     self.assertEqual(b.sha().hexdigest(), c_sha)
 
   def test_eq(self):
@@ -82,37 +82,37 @@ class BlobReadTests(unittest.TestCase):
   def test_read_commit_from_file(self):
     sha = '60dacdc733de308bb77bb76ce0fb0f9b44c9769e'
     c = self.commit(sha)
-    self.assertEqual(c.tree(), tree_sha)
-    self.assertEqual(c.parents(), ['0d89f20333fbb1d2f3a94da77f4981373d8f4310'])
-    self.assertEqual(c.author(),
+    self.assertEqual(c.tree, tree_sha)
+    self.assertEqual(c.parents, ['0d89f20333fbb1d2f3a94da77f4981373d8f4310'])
+    self.assertEqual(c.author,
         'James Westby <jw+debian@jameswestby.net>')
-    self.assertEqual(c.committer(),
+    self.assertEqual(c.committer,
         'James Westby <jw+debian@jameswestby.net>')
-    self.assertEqual(c.commit_time(), 1174759230)
-    self.assertEqual(c.message(), 'Test commit\n')
+    self.assertEqual(c.commit_time, 1174759230)
+    self.assertEqual(c.message, 'Test commit\n')
 
   def test_read_commit_no_parents(self):
     sha = '0d89f20333fbb1d2f3a94da77f4981373d8f4310'
     c = self.commit(sha)
-    self.assertEqual(c.tree(), '90182552c4a85a45ec2a835cadc3451bebdfe870')
-    self.assertEqual(c.parents(), [])
-    self.assertEqual(c.author(),
+    self.assertEqual(c.tree, '90182552c4a85a45ec2a835cadc3451bebdfe870')
+    self.assertEqual(c.parents, [])
+    self.assertEqual(c.author,
         'James Westby <jw+debian@jameswestby.net>')
-    self.assertEqual(c.committer(),
+    self.assertEqual(c.committer,
         'James Westby <jw+debian@jameswestby.net>')
-    self.assertEqual(c.commit_time(), 1174758034)
-    self.assertEqual(c.message(), 'Test commit\n')
+    self.assertEqual(c.commit_time, 1174758034)
+    self.assertEqual(c.message, 'Test commit\n')
 
   def test_read_commit_two_parents(self):
     sha = '5dac377bdded4c9aeb8dff595f0faeebcc8498cc'
     c = self.commit(sha)
-    self.assertEqual(c.tree(), 'd80c186a03f423a81b39df39dc87fd269736ca86')
-    self.assertEqual(c.parents(), ['ab64bbdcc51b170d21588e5c5d391ee5c0c96dfd',
+    self.assertEqual(c.tree, 'd80c186a03f423a81b39df39dc87fd269736ca86')
+    self.assertEqual(c.parents, ['ab64bbdcc51b170d21588e5c5d391ee5c0c96dfd',
                                    '4cffe90e0a41ad3f5190079d7c8f036bde29cbe6'])
-    self.assertEqual(c.author(),
+    self.assertEqual(c.author,
         'James Westby <jw+debian@jameswestby.net>')
-    self.assertEqual(c.committer(),
+    self.assertEqual(c.committer,
         'James Westby <jw+debian@jameswestby.net>')
-    self.assertEqual(c.commit_time(), 1174773719)
-    self.assertEqual(c.message(), 'Merge ../b\n')
+    self.assertEqual(c.commit_time, 1174773719)
+    self.assertEqual(c.message, 'Merge ../b\n')
 

+ 7 - 1
dulwich/tests/test_pack.py

@@ -162,9 +162,15 @@ class TestPack(PackTests):
 
     def test_copy(self):
         p = self.get_pack(pack1_sha)
-        write_pack("testcopy", list(p.iterobjects()))
+        write_pack("testcopy", p.iterobjects(), len(p))
         self.assertEquals(p, Pack("testcopy"))
 
+    def test_commit_obj(self):
+        p = self.get_pack(pack1_sha)
+        commit = p[commit_sha]
+        self.assertEquals("James Westby <jw+debian@jameswestby.net>", commit.author)
+        self.assertEquals([], commit.parents)
+
 
 class TestHexToSha(unittest.TestCase):
 

+ 6 - 6
dulwich/tests/test_repository.py

@@ -65,21 +65,21 @@ class RepositoryTests(unittest.TestCase):
     self.assertRaises(errors.NotCommitError,
                       r.commit, '4f2e6529203aa6d44b5af6e3292c837ceda003f9')
 
-  def test_get_tree(self):
+  def test_tree(self):
     r = self.open_repo('a')
     commit = r.commit(r.head())
-    tree = r.get_tree(commit.tree())
+    tree = r.tree(commit.tree)
     self.assertEqual(tree._type, 'tree')
-    self.assertEqual(tree.sha().hexdigest(), commit.tree())
+    self.assertEqual(tree.sha().hexdigest(), commit.tree)
 
-  def test_get_tree_not_tree(self):
+  def test_tree_not_tree(self):
     r = self.open_repo('a')
-    self.assertRaises(errors.NotTreeError, r.get_tree, r.head())
+    self.assertRaises(errors.NotTreeError, r.tree, r.head())
 
   def test_get_blob(self):
     r = self.open_repo('a')
     commit = r.commit(r.head())
-    tree = r.get_tree(commit.tree())
+    tree = r.tree(commit.tree())
     blob_sha = tree.entries()[0][2]
     blob = r.get_blob(blob_sha)
     self.assertEqual(blob._type, 'blob')