135
132
# Update known_parent_gdfos for a key we couldn't process
136
133
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)
203
135
def heads(self, keys):
204
136
"""Return the heads from amongst keys.
349
281
in tsort.merge_sort(as_parent_map, tip_key,
350
282
mainline_revisions=None,
351
283
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