Rev 4410: Implement the fix for the python version. in http://bazaar.launchpad.net/~jameinel/bzr/1.16-better_heads
John Arbash Meinel
john at arbash-meinel.com
Fri Jun 12 20:37:41 BST 2009
At http://bazaar.launchpad.net/~jameinel/bzr/1.16-better_heads
------------------------------------------------------------
revno: 4410
revision-id: john at arbash-meinel.com-20090612193730-jwaocmo8a9m4t1jz
parent: john at arbash-meinel.com-20090612180515-t0cwbjsnve094oik
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: 1.16-better_heads
timestamp: Fri 2009-06-12 14:37:30 -0500
message:
Implement the fix for the python version.
The idea is that if while walking we run into a node or its dominator
then we obviously supersede that node.
The other bit to be aware of, is that we shouldn't negate a node when
we walk to its own dominator.
-------------- next part --------------
=== modified file 'bzrlib/_known_graph_py.py'
--- a/bzrlib/_known_graph_py.py 2009-06-11 16:46:17 +0000
+++ b/bzrlib/_known_graph_py.py 2009-06-12 19:37:30 +0000
@@ -186,6 +186,37 @@
child_node.gdfo = next_gdfo
heappush(todo, (next_gdfo, child_node))
+ def _get_dominators_to_keys(self, candidate_nodes):
+ """Get the reverse mapping from dominators => candidate_nodes.
+
+ This might also exclude certain candidate_nodes if it is determined
+ that they share a dominator.
+ """
+ dom_to_key = {}
+ keys_to_remove = []
+ for node in candidate_nodes.values():
+ if node.linear_dominator in dom_to_key:
+ # This node already exists, resolve which node supersedes the
+ # other
+ other_node_key = dom_to_key[node.linear_dominator]
+ other_node = self._nodes[other_node_key]
+ # There should be no way that nodes sharing a dominator could
+ # 'tie' for gdfo
+ assert other_node.gdfo != node.gdfo
+ if other_node.gdfo > node.gdfo:
+ # The other node has this node as an ancestor
+ keys_to_remove.append(node.key)
+ continue
+ else:
+ # Replace the other node, and set this as the new key
+ keys_to_remove.append(other_node.key)
+ dom_to_key[node.linear_dominator] = node.key
+ else:
+ dom_to_key[node.linear_dominator] = node.key
+ for key in keys_to_remove:
+ candidate_nodes.pop(key)
+ return dom_to_key
+
def heads(self, keys):
"""Return the heads from amongst keys.
@@ -217,32 +248,31 @@
return heads
except KeyError:
pass # compute it ourselves
- # We could do a check here to see if all nodes have the same
- # 'linear_dominator'. However, in testing, this only was encountered 1
- # during 'bzr annotate' so it is likely to not be particularly helpful
- dom_key = None
+ dom_to_key = self._get_dominators_to_keys(candidate_nodes)
+ if len(candidate_nodes) < 2:
+ # We shrunk candidate_nodes and determined a new head
+ return frozenset(candidate_nodes)
+ dom_heads_key = None
# Check the linear dominators of these keys, to see if we already
# know the heads answer
- dom_key = frozenset([node.linear_dominator
- for node in candidate_nodes.itervalues()])
- if dom_key in self._known_heads:
- dom_to_node = dict([(node.linear_dominator, key)
- for key, node in candidate_nodes.iteritems()])
+ dom_heads_key = frozenset([node.linear_dominator
+ for node in candidate_nodes.itervalues()])
+ if dom_heads_key in self._known_heads:
# map back into the original keys
- heads = self._known_heads[dom_key]
- heads = frozenset([dom_to_node[key] for key in heads])
+ heads = self._known_heads[dom_heads_key]
+ heads = frozenset([dom_to_key[key] for key in heads])
return heads
- heads = self._heads_from_candidate_nodes(candidate_nodes)
+ heads = self._heads_from_candidate_nodes(candidate_nodes, dom_to_key)
if self.do_cache:
self._known_heads[heads_key] = heads
# Cache the dominator heads
- if dom_key is not None:
+ if dom_heads_key is not None:
dom_heads = frozenset([candidate_nodes[key].linear_dominator
for key in heads])
- self._known_heads[dom_key] = dom_heads
+ self._known_heads[dom_heads_key] = dom_heads
return heads
- def _heads_from_candidate_nodes(self, candidate_nodes):
+ def _heads_from_candidate_nodes(self, candidate_nodes, dom_to_key):
queue = []
to_cleanup = []
to_cleanup_append = to_cleanup.append
@@ -295,6 +325,13 @@
candidate_nodes.pop(parent_key)
if len(candidate_nodes) <= 1:
break
+ if parent_key in dom_to_key:
+ orig_key = dom_to_key[parent_key]
+ if orig_key != node.key:
+ if orig_key in candidate_nodes:
+ candidate_nodes.pop(orig_key)
+ if len(candidate_nodes) <= 1:
+ break
parent_node = nodes[parent_key]
ancestor_of = parent_node.ancestor_of
if ancestor_of is None:
=== modified file 'bzrlib/tests/test__known_graph.py'
--- a/bzrlib/tests/test__known_graph.py 2009-06-12 18:05:15 +0000
+++ b/bzrlib/tests/test__known_graph.py 2009-06-12 19:37:30 +0000
@@ -229,3 +229,4 @@
self.assertEqual(set(['w']), graph.heads(['w', 's']))
self.assertEqual(set(['z']), graph.heads(['w', 's', 'z']))
self.assertEqual(set(['w', 'q']), graph.heads(['w', 's', 'q']))
+ self.assertEqual(set(['z']), graph.heads(['s', 'z']))
More information about the bazaar-commits
mailing list