1
# Copyright (C) 2005, 2008 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
11
# GNU General Public License for more details.
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
from bzrlib.tsort import topo_sort
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
18
def max_distance(node, ancestors, distances, root_descendants):
22
"""Calculate the max distance to an ancestor.
19
"""Calculate the max distance to an ancestor.
23
20
Return None if not all possible ancestors have known distances"""
25
22
if node in distances:
38
35
best = distances[ancestor] + 1
42
39
def node_distances(graph, ancestors, start, root_descendants=None):
43
40
"""Produce a list of nodes, sorted by distance from a start node.
44
41
This is an algorithm devised by Aaron Bentley, because applying Dijkstra
62
59
line_descendants = graph[line]
63
assert line not in line_descendants, "%s refers to itself" % line
64
60
for descendant in line_descendants:
65
61
distance = max_distance(descendant, ancestors, distances,
126
122
def add_node(self, node_id, parent_ids):
127
123
"""Add node_id to the graph with parent_ids as its parents."""
124
if len(parent_ids) == 0:
129
125
self.roots.add(node_id)
130
126
self._graph_ancestors[node_id] = list(parent_ids)
131
127
self._ensure_descendant(node_id)
132
128
for parent in parent_ids:
133
129
self._ensure_descendant(parent)
134
130
self._graph_descendants[parent][node_id] = 1
136
132
def _ensure_descendant(self, node_id):
137
133
"""Ensure that a descendant lookup for node_id will work."""
138
134
if not node_id in self._graph_descendants:
142
138
"""Return a dictionary of graph node:ancestor_list entries."""
143
139
return dict(self._graph_ancestors.items())
145
def get_ancestry(self, node_id):
141
def get_ancestry(self, node_id, topo_sorted=True):
146
142
"""Return the inclusive ancestors of node_id in topological order."""
147
143
# maybe optimise this ?
144
from bzrlib.tsort import topo_sort
149
146
pending = set([node_id])
150
147
while len(pending):