dulwich-users team mailing list archive
-
dulwich-users team
-
Mailing list archive
-
Message #00632
[PATCH 34/34] walk: Propagate excluded out-of-order commits.
From: Dave Borowitz <dborowitz@xxxxxxxxxx>
Change-Id: Ic600c657e50712b464c5b16604850491e15cf845
---
dulwich/tests/test_walk.py | 14 ++++++++++++++
dulwich/walk.py | 17 +++++++++++++++++
2 files changed, 31 insertions(+), 0 deletions(-)
diff --git a/dulwich/tests/test_walk.py b/dulwich/tests/test_walk.py
index 67d07f7..90e7553 100644
--- a/dulwich/tests/test_walk.py
+++ b/dulwich/tests/test_walk.py
@@ -395,3 +395,17 @@ class WalkerTest(TestCase):
times=[2, 1, 3, 4, 5])
self.assertWalkYields([c5, c4, c3, c1, c2], [c5.id])
self.assertWalkYields([c5, c4, c3, c2, c1], [c5.id], order=ORDER_TOPO)
+
+ def test_out_of_order_with_exclude(self):
+ # Create the following graph:
+ # c1-------x2---m6
+ # \ /
+ # \-y3--y4-/--y5
+ # Due to skew, y5 is the oldest commit.
+ c1, x2, y3, y4, y5, m6 = cs = self.make_commits(
+ [[1], [2, 1], [3, 1], [4, 3], [5, 4], [6, 2, 4]],
+ times=[2, 3, 4, 5, 1, 6])
+ self.assertWalkYields([m6, y4, y3, x2, c1], [m6.id])
+ # Ensure that c1..y4 get excluded even though they're popped from the
+ # priority queue long before y5.
+ self.assertWalkYields([m6, x2], [m6.id], exclude=[y5.id])
diff --git a/dulwich/walk.py b/dulwich/walk.py
index 6bea788..e4f2b75 100644
--- a/dulwich/walk.py
+++ b/dulwich/walk.py
@@ -29,6 +29,9 @@ import heapq
import itertools
import os
+from dulwich._compat import (
+ all,
+ )
from dulwich.diff_tree import (
RENAME_CHANGE_TYPES,
tree_changes,
@@ -148,6 +151,18 @@ class _CommitTimeQueue(object):
is_excluded = sha in self._excluded
if is_excluded:
self._exclude_parents(commit)
+ if self._pq and all(c.id in self._excluded
+ for _, c in self._pq):
+ _, n = self._pq[0]
+ if n.commit_time >= self._last.commit_time:
+ # If the next commit is newer than the last one, we need
+ # to keep walking in case its parents (which we may not
+ # have seen yet) are excluded. This gives the excluded
+ # set a chance to "catch up" while the commit is still
+ # in the Walker's output queue.
+ reset_extra_commits = True
+ else:
+ reset_extra_commits = False
if (self._min_time is not None and
commit.commit_time < self._min_time):
@@ -262,6 +277,8 @@ class Walker(object):
return False
if self.until is not None and commit.commit_time > self.until:
return False
+ if commit.id in self.excluded:
+ return False
if self.paths is None:
return True
--
1.7.3.1
References