Browse Source

Update NEWS, provide way to force diffing of binary files.

Jelmer Vernooij 12 years ago
parent
commit
b0cffe5c58
3 changed files with 45 additions and 5 deletions
  1. 3 0
      NEWS
  2. 14 5
      dulwich/patch.py
  3. 28 0
      dulwich/tests/test_patch.py

+ 3 - 0
NEWS

@@ -7,6 +7,9 @@
   * Use indentation consistent with C Git in config files.
     (#1031356, Curt Moore, Jelmer Vernooij)
 
+  * Recognize and skip binary files in diff function.
+    (Takeshi Kanemoto)
+
  FEATURES
 
   * Add support for mergetags. (milki, #963525)

+ 14 - 5
dulwich/patch.py

@@ -107,18 +107,24 @@ def unified_diff(a, b, fromfile='', tofile='', n=3):
 
 
 def is_binary(content):
-    """See if the first few bytes contains any null characters."""
+    """See if the first few bytes contain any null characters.
+
+    :param content: Bytestring to check for binary content
+    """
     return '\0' in content[:FIRST_FEW_BYTES]
 
 
 def write_object_diff(f, store, (old_path, old_mode, old_id),
-                                (new_path, new_mode, new_id)):
+                                (new_path, new_mode, new_id),
+                                diff_binary=False):
     """Write the diff for an object.
 
     :param f: File-like object to write to
     :param store: Store to retrieve objects from, if necessary
     :param (old_path, old_mode, old_hexsha): Old file
     :param (new_path, new_mode, new_hexsha): New file
+    :param diff_binary: Whether to diff files even if they
+        are considered binary files by is_binary().
 
     :note: the tuple elements should be None for nonexistant files
     """
@@ -164,7 +170,7 @@ def write_object_diff(f, store, (old_path, old_mode, old_id),
     f.write("\n")
     old_content = content(old_mode, old_id)
     new_content = content(new_mode, new_id)
-    if is_binary(old_content) or is_binary(new_content):
+    if not diff_binary and (is_binary(old_content) or is_binary(new_content)):
         f.write("Binary files %s and %s differ\n" % (old_path, new_path))
     else:
         f.writelines(unified_diff(lines(old_content), lines(new_content),
@@ -217,17 +223,20 @@ def write_blob_diff(f, (old_path, old_mode, old_blob),
         old_path, new_path))
 
 
-def write_tree_diff(f, store, old_tree, new_tree):
+def write_tree_diff(f, store, old_tree, new_tree, diff_binary=False):
     """Write tree diff.
 
     :param f: File-like object to write to.
     :param old_tree: Old tree id
     :param new_tree: New tree id
+    :param diff_binary: Whether to diff files even if they
+        are considered binary files by is_binary().
     """
     changes = store.tree_changes(old_tree, new_tree)
     for (oldpath, newpath), (oldmode, newmode), (oldsha, newsha) in changes:
         write_object_diff(f, store, (oldpath, oldmode, oldsha),
-                                    (newpath, newmode, newsha))
+                                    (newpath, newmode, newsha),
+                                    diff_binary=diff_binary)
 
 
 def git_am_patch_split(f):

+ 28 - 0
dulwich/tests/test_patch.py

@@ -369,6 +369,34 @@ class DiffTests(TestCase):
             '-same'
             ], f.getvalue().splitlines())
 
+    def test_object_diff_bin_blob_force(self):
+        f = StringIO()
+        # Prepare two slightly different PNG headers
+        b1 = Blob.from_string(
+            "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52"
+            "\x00\x00\x01\xd5\x00\x00\x00\x9f\x08\x04\x00\x00\x00\x05\x04\x8b")
+        b2 = Blob.from_string(
+            "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52"
+            "\x00\x00\x01\xd5\x00\x00\x00\x9f\x08\x03\x00\x00\x00\x98\xd3\xb3")
+        store = MemoryObjectStore()
+        store.add_objects([(b1, None), (b2, None)])
+        write_object_diff(f, store, ('foo.png', 0644, b1.id),
+                                    ('bar.png', 0644, b2.id), diff_binary=True)
+        self.assertEqual([
+            'diff --git a/foo.png b/bar.png',
+            'index f73e47d..06364b7 644',
+            '--- a/foo.png',
+            '+++ b/bar.png',
+            '@@ -1,4 +1,4 @@',
+            ' \x89PNG',
+            ' \x1a',
+            ' \x00\x00\x00',
+            '-IHDR\x00\x00\x01\xd5\x00\x00\x00\x9f\x08\x04\x00\x00\x00\x05\x04\x8b',
+            '\\ No newline at end of file',
+            '+IHDR\x00\x00\x01\xd5\x00\x00\x00\x9f\x08\x03\x00\x00\x00\x98\xd3\xb3',
+            '\\ No newline at end of file'
+            ], f.getvalue().splitlines())
+
     def test_object_diff_bin_blob(self):
         f = StringIO()
         # Prepare two slightly different PNG headers