|
@@ -370,6 +370,46 @@ def _find_shallow(store, heads, depth):
|
|
|
return shallow, not_shallow
|
|
|
|
|
|
|
|
|
+def _want_satisfied(store, haves, want, earliest):
|
|
|
+ o = store[want]
|
|
|
+ pending = collections.deque([o])
|
|
|
+ while pending:
|
|
|
+ commit = pending.popleft()
|
|
|
+ if commit.id in haves:
|
|
|
+ return True
|
|
|
+ if commit.type_name != "commit":
|
|
|
+ # non-commit wants are assumed to be satisfied
|
|
|
+ continue
|
|
|
+ for parent in commit.parents:
|
|
|
+ parent_obj = store[parent]
|
|
|
+ # TODO: handle parents with later commit times than children
|
|
|
+ if parent_obj.commit_time >= earliest:
|
|
|
+ pending.append(parent_obj)
|
|
|
+ return False
|
|
|
+
|
|
|
+
|
|
|
+def _all_wants_satisfied(store, haves, wants):
|
|
|
+ """Check whether all the current wants are satisfied by a set of haves.
|
|
|
+
|
|
|
+ :param store: Object store to retrieve objects from
|
|
|
+ :param haves: A set of commits we know the client has.
|
|
|
+ :param wants: A set of commits the client wants
|
|
|
+ :note: Wants are specified with set_wants rather than passed in since
|
|
|
+ in the current interface they are determined outside this class.
|
|
|
+ """
|
|
|
+ haves = set(haves)
|
|
|
+ if haves:
|
|
|
+ earliest = min([store[h].commit_time for h in haves])
|
|
|
+ else:
|
|
|
+ earliest = 0
|
|
|
+ unsatisfied_wants = set()
|
|
|
+ for want in wants:
|
|
|
+ if not _want_satisfied(store, haves, want, earliest):
|
|
|
+ return False
|
|
|
+
|
|
|
+ return True
|
|
|
+
|
|
|
+
|
|
|
class ProtocolGraphWalker(object):
|
|
|
"""A graph walker that knows the git protocol.
|
|
|
|
|
@@ -533,34 +573,6 @@ class ProtocolGraphWalker(object):
|
|
|
def set_wants(self, wants):
|
|
|
self._wants = wants
|
|
|
|
|
|
- def _is_satisfied(self, haves, want, earliest):
|
|
|
- """Check whether a want is satisfied by a set of haves.
|
|
|
-
|
|
|
- A want, typically a branch tip, is "satisfied" only if there exists a
|
|
|
- path back from that want to one of the haves.
|
|
|
-
|
|
|
- :param haves: A set of commits we know the client has.
|
|
|
- :param want: The want to check satisfaction for.
|
|
|
- :param earliest: A timestamp beyond which the search for haves will be
|
|
|
- terminated, presumably because we're searching too far down the
|
|
|
- wrong branch.
|
|
|
- """
|
|
|
- o = self.store[want]
|
|
|
- pending = collections.deque([o])
|
|
|
- while pending:
|
|
|
- commit = pending.popleft()
|
|
|
- if commit.id in haves:
|
|
|
- return True
|
|
|
- if commit.type_name != "commit":
|
|
|
- # non-commit wants are assumed to be satisfied
|
|
|
- continue
|
|
|
- for parent in commit.parents:
|
|
|
- parent_obj = self.store[parent]
|
|
|
- # TODO: handle parents with later commit times than children
|
|
|
- if parent_obj.commit_time >= earliest:
|
|
|
- pending.append(parent_obj)
|
|
|
- return False
|
|
|
-
|
|
|
def all_wants_satisfied(self, haves):
|
|
|
"""Check whether all the current wants are satisfied by a set of haves.
|
|
|
|
|
@@ -568,15 +580,7 @@ class ProtocolGraphWalker(object):
|
|
|
:note: Wants are specified with set_wants rather than passed in since
|
|
|
in the current interface they are determined outside this class.
|
|
|
"""
|
|
|
- haves = set(haves)
|
|
|
- if haves:
|
|
|
- earliest = min([self.store[h].commit_time for h in haves])
|
|
|
- else:
|
|
|
- earliest = 0
|
|
|
- for want in self._wants:
|
|
|
- if not self._is_satisfied(haves, want, earliest):
|
|
|
- return False
|
|
|
- return True
|
|
|
+ return _all_wants_satisfied(self.store, haves, self._wants)
|
|
|
|
|
|
def set_ack_type(self, ack_type):
|
|
|
impl_classes = {
|