Browse Source

walk: Add option for rename detection.

Change-Id: I639a30a9ff602ffb029b8feff9e841a1fdb62cfe
Dave Borowitz 13 năm trước cách đây
mục cha
commit
a2986bab31
2 tập tin đã thay đổi với 35 bổ sung10 xóa
  1. 18 0
      dulwich/tests/test_walk.py
  2. 17 10
      dulwich/walk.py

+ 18 - 0
dulwich/tests/test_walk.py

@@ -21,7 +21,9 @@
 from dulwich.diff_tree import (
 from dulwich.diff_tree import (
     CHANGE_ADD,
     CHANGE_ADD,
     CHANGE_MODIFY,
     CHANGE_MODIFY,
+    CHANGE_RENAME,
     TreeChange,
     TreeChange,
+    RenameDetector,
     )
     )
 from dulwich.object_store import (
 from dulwich.object_store import (
     MemoryObjectStore,
     MemoryObjectStore,
@@ -221,3 +223,19 @@ class WalkerTest(TestCase):
                  4: [('a', blob_a1)]})  # Non-conflicting
                  4: [('a', blob_a1)]})  # Non-conflicting
         self.assertWalkYields([m3, y2, x1], [m3.id], paths=['a'])
         self.assertWalkYields([m3, y2, x1], [m3.id], paths=['a'])
         self.assertWalkYields([y2, x1], [m4.id], paths=['a'])
         self.assertWalkYields([y2, x1], [m4.id], paths=['a'])
+
+    def test_changes_with_renames(self):
+        blob = make_object(Blob, data='blob')
+        c1, c2 = self.make_linear_commits(
+          2, trees={1: [('a', blob)], 2: [('b', blob)]})
+        entry_a = ('a', F, blob.id)
+        entry_b = ('b', F, blob.id)
+        changes_without_renames = [TreeChange.delete(entry_a),
+                                   TreeChange.add(entry_b)]
+        changes_with_renames = [TreeChange(CHANGE_RENAME, entry_a, entry_b)]
+        self.assertWalkYields(
+          [TestWalkEntry(c2, changes_without_renames)], [c2.id], max_entries=1)
+        detector = RenameDetector(self.store)
+        self.assertWalkYields(
+          [TestWalkEntry(c2, changes_with_renames)], [c2.id], max_entries=1,
+          rename_detector=detector)

+ 17 - 10
dulwich/walk.py

@@ -33,10 +33,11 @@ ORDER_DATE = 'date'
 class WalkEntry(object):
 class WalkEntry(object):
     """Object encapsulating a single result from a walk."""
     """Object encapsulating a single result from a walk."""
 
 
-    def __init__(self, store, commit):
+    def __init__(self, store, commit, rename_detector):
         self.commit = commit
         self.commit = commit
         self._store = store
         self._store = store
         self._changes = None
         self._changes = None
+        self._rename_detector = rename_detector
 
 
     def changes(self):
     def changes(self):
         """Get the tree changes for this entry.
         """Get the tree changes for this entry.
@@ -49,15 +50,17 @@ class WalkEntry(object):
         if self._changes is None:
         if self._changes is None:
             commit = self.commit
             commit = self.commit
             if not commit.parents:
             if not commit.parents:
-                changes = list(tree_changes(self._store, None, commit.tree))
+                changes_func = tree_changes
+                parent = None
             elif len(commit.parents) == 1:
             elif len(commit.parents) == 1:
-                ptree = self._store[commit.parents[0]].tree
-                changes = list(tree_changes(self._store, ptree, commit.tree))
+                changes_func = tree_changes
+                parent = self._store[commit.parents[0]].tree
             else:
             else:
-                ptrees = [self._store[p].tree for p in commit.parents]
-                changes = list(tree_changes_for_merge(self._store, ptrees,
-                                                      commit.tree))
-            self._changes = changes
+                changes_func = tree_changes_for_merge
+                parent = [self._store[p].tree for p in commit.parents]
+            self._changes = list(changes_func(
+              self._store, parent, commit.tree,
+              rename_detector=self._rename_detector))
         return self._changes
         return self._changes
 
 
     def __repr__(self):
     def __repr__(self):
@@ -73,7 +76,8 @@ class Walker(object):
     """
     """
 
 
     def __init__(self, store, include, exclude=None, order=ORDER_DATE,
     def __init__(self, store, include, exclude=None, order=ORDER_DATE,
-                 reverse=False, max_entries=None, paths=None):
+                 reverse=False, max_entries=None, paths=None,
+                 rename_detector=None):
         """Constructor.
         """Constructor.
 
 
         :param store: ObjectStore instance for looking up objects.
         :param store: ObjectStore instance for looking up objects.
@@ -88,6 +92,8 @@ class Walker(object):
         :param max_entries: The maximum number of entries to yield, or None for
         :param max_entries: The maximum number of entries to yield, or None for
             no limit.
             no limit.
         :param paths: Iterable of file or subtree paths to show entries for.
         :param paths: Iterable of file or subtree paths to show entries for.
+        :param rename_detector: diff.RenameDetector object for detecting
+            renames.
         """
         """
         self._store = store
         self._store = store
 
 
@@ -97,6 +103,7 @@ class Walker(object):
         self._reverse = reverse
         self._reverse = reverse
         self._max_entries = max_entries
         self._max_entries = max_entries
         self._num_entries = 0
         self._num_entries = 0
+        self._rename_detector = rename_detector
 
 
         exclude = exclude or []
         exclude = exclude or []
         self._excluded = set(exclude)
         self._excluded = set(exclude)
@@ -156,7 +163,7 @@ class Walker(object):
         :return: A WalkEntry object, or None if no entry should be returned for
         :return: A WalkEntry object, or None if no entry should be returned for
             this commit (e.g. if it doesn't match any requested  paths).
             this commit (e.g. if it doesn't match any requested  paths).
         """
         """
-        entry = WalkEntry(self._store, commit)
+        entry = WalkEntry(self._store, commit, self._rename_detector)
         if self._paths is None:
         if self._paths is None:
             return entry
             return entry