42
42
from bzrlib.pack import ContainerPushParser
43
43
from bzrlib.smart import client, vfs
44
44
from bzrlib.revision import ensure_null, NULL_REVISION
45
from bzrlib.trace import mutter, note, warning
45
from bzrlib.trace import mutter, mutter_callsite, note, warning
47
47
# Note: RemoteBzrDirFormat is in bzrdir.py
258
258
'Does not support nested trees', target_format)
261
class RemoteGraph(object):
263
def __init__(self, real_graph, remote_repo):
264
self._real_graph = real_graph
265
self._remote_repo = remote_repo
267
def heads(self, keys):
268
client = self._remote_repo._client
269
path = self._remote_repo.bzrdir._path_for_remote_call(client)
270
return set(client.call('Repository.graph_heads', path, *keys))
272
def find_lca(self, *revisions):
273
return self._real_graph.find_lca(*revisions)
275
def find_difference(self, left_revision, right_revision):
276
return self._real_graph.find_difference(left_revision, right_revision)
278
def find_unique_ancestors(self, unique_revision, common_revisions):
279
return self._real_graph.find_unique_ancestors(
280
unique_revision, common_revisions)
282
def find_unique_lca(self, left_revision, right_revision,
284
return self._real_graph.find_unique_lca(
285
left_revision, right_revision, count_steps=count_steps)
287
def get_parents(self, revisions):
288
return self._real_graph.get_parents(revisions)
290
def get_parent_map(self, revisions):
291
return self._real_graph.get_parent_map(revisions)
293
def is_ancestor(self, candidate_ancestor, candidate_descendant):
294
return self._real_graph.is_ancestor(
295
candidate_ancestor, candidate_descendant)
297
def iter_ancestry(self, revision_ids):
298
return self._real_graph.iter_ancestry(revision_ids)
300
def iter_topo_order(self, revisions):
301
return self._real_graph.iter_topo_order(revisions)
303
def _make_breadth_first_searcher(self, revisions):
304
return self._real_graph._make_breadth_first_searcher(revisions)
261
307
class RemoteRepository(object):
262
308
"""Repository accessed over rpc.
433
479
self.bzrdir.transport.base):
434
480
parents_provider = graph._StackedParentsProvider(
435
481
[parents_provider, other_repository._make_parents_provider()])
436
return graph.Graph(parents_provider)
482
real_graph = graph.Graph(parents_provider)
483
return RemoteGraph(real_graph, self)
438
485
def gather_stats(self, revid=None, committers=None):
439
486
"""See Repository.gather_stats()."""
810
857
def get_parent_map(self, keys):
811
858
"""See bzrlib.Graph.get_parent_map()."""
859
# mutter_callsite(None, "get_parent_map called with %d keys", len(keys))
860
# import pdb;pdb.set_trace()
812
861
# Hack to build up the caching logic.
813
862
ancestry = self._parents_map
814
863
if ancestry is None:
826
875
ancestry.update(parent_map)
827
876
present_keys = [k for k in keys if k in ancestry]
828
if 'hpss' in debug.debug_flags:
877
if 'hpss' in debug.debug_flags and False:
829
878
if self._requested_parents is not None and len(ancestry) != 0:
830
879
self._requested_parents.update(present_keys)
831
880
mutter('Current RemoteRepository graph hit rate: %d%%',
1281
1331
if self._lock_mode == 'r':
1282
1332
self._real_branch.lock_read()
1334
def _clear_cached_state(self):
1335
super(RemoteBranch, self)._clear_cached_state()
1336
self._last_revision_info_cache = None
1285
1339
def control_files(self):
1286
1340
# Defer actually creating RemoteBranchLockableFiles until its needed,
1435
1489
def last_revision_info(self):
1436
1490
"""See Branch.last_revision_info()."""
1491
if self._last_revision_info_cache is None:
1492
self._last_revision_info_cache = self._last_revision_info()
1493
return self._last_revision_info_cache
1495
def _last_revision_info(self):
1437
1496
path = self.bzrdir._path_for_remote_call(self._client)
1438
1497
response = self._client.call('Branch.last_revision_info', path)
1439
1498
if response[0] != 'ok':
1516
def _set_last_revision(self, revision_id):
1517
path = self.bzrdir._path_for_remote_call(self._client)
1518
self._clear_cached_state()
1520
response = self._client.call('Branch.set_last_revision',
1521
path, self._lock_token, self._repo_lock_token, revision_id)
1522
except errors.ErrorFromSmartServer, err:
1523
if err.error_verb == 'NoSuchRevision':
1524
raise NoSuchRevision(self, revision_id)
1526
if response != ('ok',):
1527
raise errors.UnexpectedSmartServerResponse(response)
1457
1529
@needs_write_lock
1458
1530
def set_revision_history(self, rev_history):
1459
1531
# Send just the tip revision of the history; the server will generate
1460
1532
# the full history from that. If the revision doesn't exist in this
1461
1533
# branch, NoSuchRevision will be raised.
1462
path = self.bzrdir._path_for_remote_call(self._client)
1463
1534
if rev_history == []:
1464
1535
rev_id = 'null:'
1466
1537
rev_id = rev_history[-1]
1467
self._clear_cached_state()
1469
response = self._client.call('Branch.set_last_revision',
1470
path, self._lock_token, self._repo_lock_token, rev_id)
1471
except errors.ErrorFromSmartServer, err:
1472
if err.error_verb == 'NoSuchRevision':
1473
raise NoSuchRevision(self, rev_id)
1475
if response != ('ok',):
1476
raise errors.UnexpectedSmartServerResponse(response)
1538
self._set_last_revision(rev_id)
1477
1539
self._cache_revision_history(rev_history)
1479
1541
def get_parent(self):
1528
1590
except errors.UnknownSmartMethod:
1529
1591
self._ensure_real()
1530
1592
self._clear_cached_state()
1531
return self._real_branch.set_last_revision_info(revno, revision_id)
1593
self._real_branch.set_last_revision_info(revno, revision_id)
1594
self._last_revision_info_cache = revno, revision_id
1532
1596
except errors.ErrorFromSmartServer, err:
1533
1597
if err.error_verb == 'NoSuchRevision':
1534
1598
raise NoSuchRevision(self, err.error_args[0])
1536
1600
if response == ('ok',):
1537
1601
self._clear_cached_state()
1602
self._last_revision_info_cache = revno, revision_id
1539
1604
raise errors.UnexpectedSmartServerResponse(response)
1541
1606
def generate_revision_history(self, revision_id, last_rev=None,
1542
1607
other_branch=None):
1544
return self._real_branch.generate_revision_history(
1545
revision_id, last_rev=last_rev, other_branch=other_branch)
1608
# self._ensure_real()
1609
# return self._real_branch.generate_revision_history(
1610
# revision_id, last_rev=last_rev, other_branch=other_branch)
1611
self._set_last_revision(revision_id)
1613
if last_rev is None and other_branch is None:
1614
self._set_last_revision(revision_id)
1617
return self._real_branch.generate_revision_history(
1618
revision_id, last_rev=last_rev, other_branch=other_branch)
1548
1621
def tags(self):
1554
1627
return self._real_branch.set_push_location(location)
1556
1629
def update_revisions(self, other, stop_revision=None, overwrite=False):
1630
mutter('RemoteBranch.update_revisions(%r, %s, %r)',
1631
other, stop_revision, overwrite)
1634
return self._real_branch.update_revisions(
1635
other, stop_revision=stop_revision, overwrite=True)
1636
from bzrlib import revision as _mod_revision
1639
other_last_revno, other_last_revision = other.last_revision_info()
1640
if stop_revision is None:
1641
stop_revision = other_last_revision
1642
if _mod_revision.is_null(stop_revision):
1643
# if there are no commits, we're done.
1645
# whats the current last revision, before we fetch [and change it
1647
last_rev = _mod_revision.ensure_null(self.last_revision())
1648
# we fetch here so that we don't process data twice in the common
1649
# case of having something to pull, and so that the check for
1650
# already merged can operate on the just fetched graph, which will
1651
# be cached in memory.
1652
mutter('about to fetch %s from %r', stop_revision, other)
1653
self.fetch(other, stop_revision)
1654
# Check to see if one is an ancestor of the other
1655
heads = self.repository.get_graph().heads([stop_revision,
1657
if heads == set([last_rev]):
1658
# The current revision is a decendent of the target,
1661
elif heads == set([stop_revision, last_rev]):
1662
# These branches have diverged
1663
raise errors.DivergedBranches(self, other)
1664
elif heads != set([stop_revision]):
1665
raise AssertionError("invalid heads: %r" % heads)
1666
if other_last_revision == stop_revision:
1667
self.set_last_revision_info(other_last_revno,
1668
other_last_revision)
1670
self._set_last_revision(stop_revision)
1671
# # TODO: jam 2007-11-29 Is there a way to determine the
1672
# # revno without searching all of history??
1673
# self.generate_revision_history(stop_revision,
1674
# last_rev=last_rev, other_branch=other)
1557
1680
self._ensure_real()
1558
1681
return self._real_branch.update_revisions(
1559
1682
other, stop_revision=stop_revision, overwrite=overwrite)