171
188
self._known_heads[heads_key] = heads
192
"""Return the nodes in topological order.
194
All parents must occur before all children.
196
for node in self._nodes.itervalues():
197
if node.gdfo is None:
198
raise errors.GraphCycleError(self._nodes)
199
pending = self._find_tails()
200
pending_pop = pending.pop
201
pending_append = pending.append
204
topo_order_append = topo_order.append
206
num_seen_parents = dict.fromkeys(self._nodes, 0)
209
if node.parent_keys is not None:
210
# We don't include ghost parents
211
topo_order_append(node.key)
212
for child_key in node.child_keys:
213
child_node = self._nodes[child_key]
214
seen_parents = num_seen_parents[child_key] + 1
215
if seen_parents == len(child_node.parent_keys):
216
# All parents have been processed, enqueue this child
217
pending_append(child_node)
218
# This has been queued up, stop tracking it
219
del num_seen_parents[child_key]
221
num_seen_parents[child_key] = seen_parents
222
# We started from the parents, so we don't need to do anymore work
226
"""Return a reverse topological ordering which is 'stable'.
228
There are a few constraints:
229
1) Reverse topological (all children before all parents)
231
3) 'stable' sorting, so that we get the same result, independent of
232
machine, or extra data.
233
To do this, we use the same basic algorithm as topo_sort, but when we
234
aren't sure what node to access next, we sort them lexicographically.
236
tips = self._find_tips()
237
# Split the tips based on prefix
240
if node.key.__class__ is str or len(node.key) == 1:
244
prefix_tips.setdefault(prefix, []).append(node)
246
num_seen_children = dict.fromkeys(self._nodes, 0)
249
for prefix in sorted(prefix_tips):
250
pending = sorted(prefix_tips[prefix], key=lambda n:n.key,
254
if node.parent_keys is None:
255
# Ghost node, skip it
257
result.append(node.key)
258
for parent_key in sorted(node.parent_keys, reverse=True):
259
parent_node = self._nodes[parent_key]
260
seen_children = num_seen_children[parent_key] + 1
261
if seen_children == len(parent_node.child_keys):
262
# All children have been processed, enqueue this parent
263
pending.append(parent_node)
264
# This has been queued up, stop tracking it
265
del num_seen_children[parent_key]
267
num_seen_children[parent_key] = seen_children
270
def merge_sort(self, tip_key):
271
"""Compute the merge sorted graph output."""
272
from bzrlib import tsort
273
as_parent_map = dict((node.key, node.parent_keys)
274
for node in self._nodes.itervalues()
275
if node.parent_keys is not None)
276
# We intentionally always generate revnos and never force the
278
# Strip the sequence_number that merge_sort generates
279
return [_MergeSortNode(key, merge_depth, revno, end_of_merge)
280
for _, key, merge_depth, revno, end_of_merge
281
in tsort.merge_sort(as_parent_map, tip_key,
282
mainline_revisions=None,
283
generate_revno=True)]
285
def get_parent_keys(self, key):
286
"""Get the parents for a key
288
Returns a list containg the parents keys. If the key is a ghost,
289
None is returned. A KeyError will be raised if the key is not in
292
:param keys: Key to check (eg revision_id)
293
:return: A list of parents
295
return self._nodes[key].parent_keys
297
def get_child_keys(self, key):
298
"""Get the children for a key
300
Returns a list containg the children keys. A KeyError will be raised
301
if the key is not in the graph.
303
:param keys: Key to check (eg revision_id)
304
:return: A list of children
306
return self._nodes[key].child_keys