21
21
import bzrlib.errors
22
22
import bzrlib.errors as errors
23
from bzrlib.graph import node_distances, select_farthest, all_descendants
23
from bzrlib.graph import node_distances, select_farthest, all_descendants, Graph
24
24
from bzrlib.osutils import contains_whitespace
25
25
from bzrlib.progress import DummyProgress
232
232
pb=DummyProgress()):
233
233
if None in (revision_a, revision_b):
235
# trivial optimisation
236
if revision_a == revision_b:
237
240
pb.update('Picking ancestor', 1, 3)
238
root, ancestors, descendants, common = \
239
combined_graph(revision_a,
241
graph = revision_source.get_revision_graph_with_ghosts(
242
[revision_a, revision_b])
243
# convert to a NULL_REVISION based graph.
244
ancestors = graph.get_ancestors()
245
descendants = graph.get_descendants()
246
common = set(graph.get_ancestry(revision_a)).intersection(
247
set(graph.get_ancestry(revision_b)))
248
descendants[NULL_REVISION] = {}
249
ancestors[NULL_REVISION] = []
250
for root in graph.roots:
251
descendants[NULL_REVISION][root] = 1
252
ancestors[root].append(NULL_REVISION)
253
if len(graph.roots) == 0:
254
# no reachable roots - not handled yet.
255
raise bzrlib.errors.NoCommonAncestor(revision_a, revision_b)
257
common.add(NULL_REVISION)
242
258
except bzrlib.errors.NoCommonRoot:
243
259
raise bzrlib.errors.NoCommonAncestor(revision_a, revision_b)
279
295
def get_revision_graph(self, revision_id):
296
# we could probe incrementally until the pending
297
# ghosts list stop growing, but its cheaper for now
298
# to just ask for the complete graph for each repository.
300
for source in self._revision_sources:
301
ghost_graph = source.get_revision_graph_with_ghosts()
302
graphs.append(ghost_graph)
305
if not revision_id in graph.get_ancestors():
307
if absent == len(graphs):
308
raise errors.NoSuchRevision(self._revision_sources[0], revision_id)
312
pending = set([revision_id])
313
def find_parents(node_id):
314
"""find the parents for node_id."""
316
ancestors = graph.get_ancestors()
318
return ancestors[node_id]
321
raise errors.NoSuchRevision(self._revision_sources[0], node_id)
323
# all the graphs should have identical parent lists
324
node_id = pending.pop()
326
result[node_id] = find_parents(node_id)
327
for parent_node in result[node_id]:
328
if not parent_node in result:
329
pending.add(parent_node)
330
except errors.NoSuchRevision:
335
def get_revision_graph_with_ghosts(self, revision_ids):
336
# query all the sources for their entire graphs
337
# and then build a combined graph for just
281
340
for source in self._revision_sources:
341
ghost_graph = source.get_revision_graph_with_ghosts()
342
graphs.append(ghost_graph.get_ancestors())
343
for revision_id in revision_ids:
346
if not revision_id in graph:
348
if absent == len(graphs):
349
raise errors.NoSuchRevision(self._revision_sources[0],
354
pending = set(revision_ids)
356
def find_parents(node_id):
357
"""find the parents for node_id."""
360
return graph[node_id]
363
raise errors.NoSuchRevision(self._revision_sources[0], node_id)
365
# all the graphs should have identical parent lists
366
node_id = pending.pop()
283
result.update(source.get_revision_graph(revision_id))
284
except (errors.WeaveRevisionNotPresent, errors.NoSuchRevision), e:
368
parents = find_parents(node_id)
369
for parent_node in parents:
371
if (parent_node not in pending and
372
parent_node not in done):
374
pending.add(parent_node)
375
result.add_node(node_id, parents)
377
except errors.NoSuchRevision:
379
result.add_ghost(node_id)
290
383
def lock_read(self):
291
384
for source in self._revision_sources: