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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
from bzrlib.tsort import topo_sort
18
21
def max_distance(node, ancestors, distances, root_descendants):
19
"""Calculate the max distance to an ancestor.
22
"""Calculate the max distance to an ancestor.
20
23
Return None if not all possible ancestors have known distances"""
22
25
if node in distances:
35
38
best = distances[ancestor] + 1
39
42
def node_distances(graph, ancestors, start, root_descendants=None):
40
43
"""Produce a list of nodes, sorted by distance from a start node.
41
44
This is an algorithm devised by Aaron Bentley, because applying Dijkstra
59
62
line_descendants = graph[line]
63
assert line not in line_descendants, "%s refers to itself" % line
60
64
for descendant in line_descendants:
61
65
distance = max_distance(descendant, ancestors, distances,
122
126
def add_node(self, node_id, parent_ids):
123
127
"""Add node_id to the graph with parent_ids as its parents."""
124
if len(parent_ids) == 0:
125
129
self.roots.add(node_id)
126
130
self._graph_ancestors[node_id] = list(parent_ids)
127
131
self._ensure_descendant(node_id)
128
132
for parent in parent_ids:
129
133
self._ensure_descendant(parent)
130
134
self._graph_descendants[parent][node_id] = 1
132
136
def _ensure_descendant(self, node_id):
133
137
"""Ensure that a descendant lookup for node_id will work."""
134
138
if not node_id in self._graph_descendants:
138
142
"""Return a dictionary of graph node:ancestor_list entries."""
139
143
return dict(self._graph_ancestors.items())
141
def get_ancestry(self, node_id, topo_sorted=True):
145
def get_ancestry(self, node_id):
142
146
"""Return the inclusive ancestors of node_id in topological order."""
143
147
# maybe optimise this ?
144
from bzrlib.tsort import topo_sort
146
149
pending = set([node_id])
147
150
while len(pending):