ソースを参照

Fix dulwich.porcelain.show on commits with Python3. Fixes #532

Jelmer Vernooij 7 年 前
コミット
b9643bc4e0
4 ファイル変更75 行追加3 行削除
  1. 3 0
      NEWS
  2. 0 1
      dulwich/patch.py
  3. 13 2
      dulwich/porcelain.py
  4. 59 0
      dulwich/tests/test_porcelain.py

+ 3 - 0
NEWS

@@ -31,6 +31,9 @@
   * Handle race condition when mtime doesn't change between writes/reads.
     (Jelmer Vernooij, #541)
 
+  * Fix ``dulwich.porcelain.show`` on commits with Python 3.
+    (Jelmer Vernooij, #532)
+
  IMPROVEMENTS
 
   * Add basic support for reading ignore files in ``dulwich.ignore``.

+ 0 - 1
dulwich/patch.py

@@ -236,7 +236,6 @@ def write_blob_diff(f, old_file, new_file):
                  old_path, new_path))
 
 
-# TODO(jelmer): Support writing unicode, rather than bytes.
 def write_tree_diff(f, store, old_tree, new_tree, diff_binary=False):
     """Write tree diff.
 

+ 13 - 2
dulwich/porcelain.py

@@ -56,6 +56,7 @@ from contextlib import (
     closing,
     contextmanager,
 )
+from io import BytesIO
 import os
 import posixpath
 import stat
@@ -470,9 +471,19 @@ def show_commit(repo, commit, decode, outstream=sys.stdout):
     :param outstream: Stream to write to
     """
     print_commit(commit, decode=decode, outstream=outstream)
-    parent_commit = repo[commit.parents[0]]
+    if commit.parents:
+        parent_commit = repo[commit.parents[0]]
+        base_tree = parent_commit.tree
+    else:
+        base_tree = None
+    diffstream = BytesIO()
     write_tree_diff(
-        outstream, repo.object_store, parent_commit.tree, commit.tree)
+        diffstream,
+        repo.object_store, base_tree, commit.tree)
+    diffstream.seek(0)
+    outstream.write(
+        diffstream.getvalue().decode(
+                commit.encoding or DEFAULT_ENCODING, 'replace'))
 
 
 def show_tree(repo, tree, decode, outstream=sys.stdout):

+ 59 - 0
dulwich/tests/test_porcelain.py

@@ -45,6 +45,7 @@ from dulwich.tests import (
     )
 from dulwich.tests.utils import (
     build_commit_graph,
+    make_commit,
     make_object,
     )
 
@@ -376,6 +377,64 @@ class ShowTests(PorcelainTestCase):
         porcelain.show(self.repo.path, objects=[b.id], outstream=outstream)
         self.assertEqual(outstream.getvalue(), "The Foo\n")
 
+    def test_commit_no_parent(self):
+        a = Blob.from_string(b"The Foo\n")
+        ta = Tree()
+        ta.add(b"somename", 0o100644, a.id)
+        ca = make_commit(tree=ta.id)
+        self.repo.object_store.add_objects([(a, None), (ta, None), (ca, None)])
+        outstream = StringIO()
+        porcelain.show(self.repo.path, objects=[ca.id], outstream=outstream)
+        self.assertEqual(outstream.getvalue(), """\
+--------------------------------------------------
+commit: 344da06c1bb85901270b3e8875c988a027ec087d
+Author: Test Author <test@nodomain.com>
+Committer: Test Committer <test@nodomain.com>
+Date:   Fri Jan 01 2010 00:00:00 +0000
+
+Test message.
+
+diff --git /dev/null b/somename
+new mode 100644
+index 0000000..ea5c7bf 100644
+--- /dev/null
++++ b/somename
+@@ -1,0 +1,1 @@
++The Foo
+""")
+
+    def test_commit_with_change(self):
+        a = Blob.from_string(b"The Foo\n")
+        ta = Tree()
+        ta.add(b"somename", 0o100644, a.id)
+        ca = make_commit(tree=ta.id)
+        b = Blob.from_string(b"The Bar\n")
+        tb = Tree()
+        tb.add(b"somename", 0o100644, a.id)
+        cb = make_commit(tree=tb.id)
+        self.repo.object_store.add_objects(
+            [(a, None), (b, None), (ta, None), (tb, None),
+             (ca, None), (cb, None)])
+        outstream = StringIO()
+        porcelain.show(self.repo.path, objects=[cb.id], outstream=outstream)
+        self.assertEqual(outstream.getvalue(), """\
+--------------------------------------------------
+commit: 344da06c1bb85901270b3e8875c988a027ec087d
+Author: Test Author <test@nodomain.com>
+Committer: Test Committer <test@nodomain.com>
+Date:   Fri Jan 01 2010 00:00:00 +0000
+
+Test message.
+
+diff --git /dev/null b/somename
+new mode 100644
+index 0000000..ea5c7bf 100644
+--- /dev/null
++++ b/somename
+@@ -1,0 +1,1 @@
++The Foo
+""")
+
 
 class SymbolicRefTests(PorcelainTestCase):