128
135
# Update known_parent_gdfos for a key we couldn't process
129
136
known_parent_gdfos[child_key] = known_gdfo
138
def add_node(self, key, parent_keys):
139
"""Add a new node to the graph.
141
If this fills in a ghost, then the gdfos of all children will be
144
:param key: The node being added. If this is a duplicate, this is a
146
:param parent_keys: The parents of the given node.
147
:return: None (should we return if this was a ghost, etc?)
152
if node.parent_keys is None:
153
node.parent_keys = parent_keys
154
# A ghost is being added, we can no-longer trust the heads
156
self._known_heads.clear()
158
# Make sure we compare a list to a list, as tuple != list.
159
parent_keys = list(parent_keys)
160
existing_parent_keys = list(node.parent_keys)
161
if parent_keys == existing_parent_keys:
162
return # Identical content
164
raise ValueError('Parent key mismatch, existing node %s'
165
' has parents of %s not %s'
166
% (key, existing_parent_keys, parent_keys))
168
node = _KnownGraphNode(key, parent_keys)
171
for parent_key in parent_keys:
173
parent_node = nodes[parent_key]
175
parent_node = _KnownGraphNode(parent_key, None)
176
# Ghosts and roots have gdfo 1
178
nodes[parent_key] = parent_node
179
if parent_gdfo < parent_node.gdfo:
180
parent_gdfo = parent_node.gdfo
181
parent_node.child_keys.append(key)
182
node.gdfo = parent_gdfo + 1
183
# Now fill the gdfo to all children
184
# Note that this loop is slightly inefficient, in that we may visit the
185
# same child (and its decendents) more than once, however, it is
186
# 'efficient' in that we only walk to nodes that would be updated,
187
# rather than all nodes
188
# We use a deque rather than a simple list stack, to go for BFD rather
189
# than DFD. So that if a longer path is possible, we walk it before we
190
# get to the final child
191
pending = deque([node])
193
node = pending.popleft()
194
next_gdfo = node.gdfo + 1
195
for child_key in node.child_keys:
196
child = nodes[child_key]
197
if child.gdfo < next_gdfo:
198
# This child is being updated, we need to check its
200
child.gdfo = next_gdfo
201
pending.append(child)
131
203
def heads(self, keys):
132
204
"""Return the heads from amongst keys.
218
290
# We started from the parents, so we don't need to do anymore work
219
291
return topo_order
294
"""Return a reverse topological ordering which is 'stable'.
296
There are a few constraints:
297
1) Reverse topological (all children before all parents)
299
3) 'stable' sorting, so that we get the same result, independent of
300
machine, or extra data.
301
To do this, we use the same basic algorithm as topo_sort, but when we
302
aren't sure what node to access next, we sort them lexicographically.
304
tips = self._find_tips()
305
# Split the tips based on prefix
308
if node.key.__class__ is str or len(node.key) == 1:
312
prefix_tips.setdefault(prefix, []).append(node)
314
num_seen_children = dict.fromkeys(self._nodes, 0)
317
for prefix in sorted(prefix_tips):
318
pending = sorted(prefix_tips[prefix], key=lambda n:n.key,
322
if node.parent_keys is None:
323
# Ghost node, skip it
325
result.append(node.key)
326
for parent_key in sorted(node.parent_keys, reverse=True):
327
parent_node = self._nodes[parent_key]
328
seen_children = num_seen_children[parent_key] + 1
329
if seen_children == len(parent_node.child_keys):
330
# All children have been processed, enqueue this parent
331
pending.append(parent_node)
332
# This has been queued up, stop tracking it
333
del num_seen_children[parent_key]
335
num_seen_children[parent_key] = seen_children
221
338
def merge_sort(self, tip_key):
222
339
"""Compute the merge sorted graph output."""
223
340
from bzrlib import tsort
232
349
in tsort.merge_sort(as_parent_map, tip_key,
233
350
mainline_revisions=None,
234
351
generate_revno=True)]
353
def get_parent_keys(self, key):
354
"""Get the parents for a key
356
Returns a list containg the parents keys. If the key is a ghost,
357
None is returned. A KeyError will be raised if the key is not in
360
:param keys: Key to check (eg revision_id)
361
:return: A list of parents
363
return self._nodes[key].parent_keys
365
def get_child_keys(self, key):
366
"""Get the children for a key
368
Returns a list containg the children keys. A KeyError will be raised
369
if the key is not in the graph.
371
:param keys: Key to check (eg revision_id)
372
:return: A list of children
374
return self._nodes[key].child_keys