Browse Source

Add change_type_same flag to tree_changes.

Jelmer Vernooij 7 years ago
parent
commit
36edbb5640
4 changed files with 24 additions and 4 deletions
  1. 3 0
      NEWS
  2. 6 2
      dulwich/diff_tree.py
  3. 5 2
      dulwich/object_store.py
  4. 10 0
      dulwich/tests/test_diff_tree.py

+ 3 - 0
NEWS

@@ -20,6 +20,9 @@
 
   * Add ability to use password and keyfile ssh options with SSHVendor. (Filipp Kucheryavy)
 
+  * Add ``change_type_same`` flag to ``tree_changes``.
+    (Jelmer Vernooij)
+
  API CHANGES
 
   * ``GitClient.send_pack`` now accepts a ``generate_pack_data``

+ 6 - 2
dulwich/diff_tree.py

@@ -160,7 +160,8 @@ def _skip_tree(entry, include_trees):
 
 
 def tree_changes(store, tree1_id, tree2_id, want_unchanged=False,
-                 rename_detector=None, include_trees=False):
+                 rename_detector=None, include_trees=False,
+                 change_type_same=False):
     """Find the differences between the contents of two trees.
 
     :param store: An ObjectStore for looking up objects.
@@ -170,6 +171,8 @@ def tree_changes(store, tree1_id, tree2_id, want_unchanged=False,
         as well.
     :param include_trees: Whether to include trees
     :param rename_detector: RenameDetector object for detecting renames.
+    :param change_type_same: Whether to report change types in the same
+        entry or as delete+add.
     :return: Iterator over TreeChange instances for each change between the
         source and target tree.
     """
@@ -194,7 +197,8 @@ def tree_changes(store, tree1_id, tree2_id, want_unchanged=False,
         entry2 = _skip_tree(entry2, include_trees)
 
         if entry1 != _NULL_ENTRY and entry2 != _NULL_ENTRY:
-            if stat.S_IFMT(entry1.mode) != stat.S_IFMT(entry2.mode):
+            if (stat.S_IFMT(entry1.mode) != stat.S_IFMT(entry2.mode)
+                    and not change_type_same):
                 # File type changed: report as delete/add.
                 yield TreeChange.delete(entry1)
                 entry1 = _NULL_ENTRY

+ 5 - 2
dulwich/object_store.py

@@ -155,19 +155,22 @@ class BaseObjectStore(object):
             return commit()
 
     def tree_changes(self, source, target, want_unchanged=False,
-                     include_trees=False):
+                     include_trees=False, change_type_same=False):
         """Find the differences between the contents of two trees
 
         :param source: SHA1 of the source tree
         :param target: SHA1 of the target tree
         :param want_unchanged: Whether unchanged files should be reported
         :param include_trees: Whether to include trees
+        :param change_type_same: Whether to report files changing
+            type in the same entry.
         :return: Iterator over tuples with
             (oldpath, newpath), (oldmode, newmode), (oldsha, newsha)
         """
         for change in tree_changes(self, source, target,
                                    want_unchanged=want_unchanged,
-                                   include_trees=include_trees):
+                                   include_trees=include_trees,
+                                   change_type_same=change_type_same):
             yield ((change.old.path, change.new.path),
                    (change.old.mode, change.new.mode),
                    (change.old.sha, change.new.sha))

+ 10 - 0
dulwich/tests/test_diff_tree.py

@@ -220,6 +220,16 @@ class TreeChangesTest(DiffTestCase):
              TreeChange.add((b'a', 0o120000, blob_a2.id))],
             tree1, tree2)
 
+    def test_tree_changes_change_type_same(self):
+        blob_a1 = make_object(Blob, data=b'a')
+        blob_a2 = make_object(Blob, data=b'/foo/bar')
+        tree1 = self.commit_tree([(b'a', blob_a1, 0o100644)])
+        tree2 = self.commit_tree([(b'a', blob_a2, 0o120000)])
+        self.assertChangesEqual(
+            [TreeChange(CHANGE_MODIFY, (b'a', 0o100644, blob_a1.id),
+                        (b'a', 0o120000, blob_a2.id))],
+            tree1, tree2, change_type_same=True)
+
     def test_tree_changes_to_tree(self):
         blob_a = make_object(Blob, data=b'a')
         blob_x = make_object(Blob, data=b'x')