71
71
class RemoteBzrDir(BzrDir, _RpcHelper):
72
72
"""Control directory on a remote server, accessed via bzr:// or similar."""
74
def __init__(self, transport, _client=None):
74
def __init__(self, transport, format, _client=None):
75
75
"""Construct a RemoteBzrDir.
77
77
:param _client: Private parameter for testing. Disables probing and the
78
78
use of a real bzrdir.
80
BzrDir.__init__(self, transport, RemoteBzrDirFormat())
80
BzrDir.__init__(self, transport, format)
81
81
# this object holds a delegated bzrdir that uses file-level operations
82
82
# to talk to the other side
83
83
self._real_bzrdir = None
113
113
return self._real_bzrdir.cloning_metadir(stacked)
115
115
def create_repository(self, shared=False):
117
self._real_bzrdir.create_repository(shared=shared)
118
return self.open_repository()
116
# as per meta1 formats - just delegate to the format object which may
118
result = self._format.repository_format.initialize(self, shared)
119
if not isinstance(result, RemoteRepository):
120
return self.open_repository()
120
124
def destroy_repository(self):
121
125
"""See BzrDir.destroy_repository"""
123
127
self._real_bzrdir.destroy_repository()
125
129
def create_branch(self):
127
real_branch = self._real_bzrdir.create_branch()
128
return RemoteBranch(self, self.find_repository(), real_branch)
130
# as per meta1 formats - just delegate to the format object which may
132
real_branch = self._format.get_branch_format().initialize(self)
133
if not isinstance(real_branch, RemoteBranch):
134
return RemoteBranch(self, self.find_repository(), real_branch)
130
138
def destroy_branch(self):
131
139
"""See BzrDir.destroy_branch"""
262
270
_matchingbzrdir = RemoteBzrDirFormat()
273
repository.RepositoryFormat.__init__(self)
274
self._custom_format = None
264
276
def initialize(self, a_bzrdir, shared=False):
277
if self._custom_format:
278
# This returns a custom instance - e.g. a pack repo, not a remote
280
return self._custom_format.initialize(a_bzrdir, shared=shared)
265
281
if not isinstance(a_bzrdir, RemoteBzrDir):
266
282
prior_repo = self._creating_bzrdir.open_repository()
267
283
prior_repo._ensure_real()
268
284
return prior_repo._real_repository._format.initialize(
269
285
a_bzrdir, shared=shared)
270
return a_bzrdir.create_repository(shared=shared)
286
# delegate to a real object at this point (remoteBzrDir delegate to the
287
# repository format which would lead to infinite recursion).
288
a_bzrdir._ensure_real()
289
result = a_bzrdir._real_bzrdir.create_repository(shared=shared)
290
if not isinstance(result, RemoteRepository):
291
return self.open(a_bzrdir)
272
295
def open(self, a_bzrdir):
273
296
if not isinstance(a_bzrdir, RemoteBzrDir):
1261
1284
return a_bzrdir.open_branch()
1263
1286
def initialize(self, a_bzrdir):
1264
return a_bzrdir.create_branch()
1287
# Delegate to a _real object here - the RemoteBzrDir format now
1288
# supports delegating to parameterised branch formats and as such
1289
# this RemoteBranchFormat method is only called when no specific format
1291
if not isinstance(a_bzrdir, RemoteBzrDir):
1292
result = a_bzrdir.create_branch()
1294
a_bzrdir._ensure_real()
1295
result = a_bzrdir._real_bzrdir.create_branch()
1296
if not isinstance(result, RemoteBranch):
1297
result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result)
1266
1300
def supports_tags(self):
1267
1301
# Remote branches might support tags, but we won't know until we
1581
1615
def _set_last_revision_descendant(self, revision_id, other_branch,
1582
1616
allow_diverged=False, allow_overwrite_descendant=False):
1617
# This performs additional work to meet the hook contract; while its
1618
# undesirable, we have to synthesise the revno to call the hook, and
1619
# not calling the hook is worse as it means changes can't be prevented.
1620
# Having calculated this though, we can't just call into
1621
# set_last_revision_info as a simple call, because there is a set_rh
1622
# hook that some folk may still be using.
1623
old_revno, old_revid = self.last_revision_info()
1624
history = self._lefthand_history(revision_id)
1625
self._run_pre_change_branch_tip_hooks(len(history), revision_id)
1583
1626
err_context = {'other_branch': other_branch}
1584
1627
response = self._call('Branch.set_last_revision_ex',
1585
1628
self._remote_path(), self._lock_token, self._repo_lock_token,
1590
1633
raise errors.UnexpectedSmartServerResponse(response)
1591
1634
new_revno, new_revision_id = response[1:]
1592
1635
self._last_revision_info_cache = new_revno, new_revision_id
1636
self._run_post_change_branch_tip_hooks(old_revno, old_revid)
1593
1637
if self._real_branch is not None:
1594
1638
cache = new_revno, new_revision_id
1595
1639
self._real_branch._last_revision_info_cache = cache
1597
1641
def _set_last_revision(self, revision_id):
1642
old_revno, old_revid = self.last_revision_info()
1643
# This performs additional work to meet the hook contract; while its
1644
# undesirable, we have to synthesise the revno to call the hook, and
1645
# not calling the hook is worse as it means changes can't be prevented.
1646
# Having calculated this though, we can't just call into
1647
# set_last_revision_info as a simple call, because there is a set_rh
1648
# hook that some folk may still be using.
1649
history = self._lefthand_history(revision_id)
1650
self._run_pre_change_branch_tip_hooks(len(history), revision_id)
1598
1651
self._clear_cached_state()
1599
1652
response = self._call('Branch.set_last_revision',
1600
1653
self._remote_path(), self._lock_token, self._repo_lock_token,
1602
1655
if response != ('ok',):
1603
1656
raise errors.UnexpectedSmartServerResponse(response)
1657
self._run_post_change_branch_tip_hooks(old_revno, old_revid)
1605
1659
@needs_write_lock
1606
1660
def set_revision_history(self, rev_history):
1613
1667
rev_id = rev_history[-1]
1614
1668
self._set_last_revision(rev_id)
1669
for hook in branch.Branch.hooks['set_rh']:
1670
hook(self, rev_history)
1615
1671
self._cache_revision_history(rev_history)
1617
1673
def get_parent(self):
1618
1674
self._ensure_real()
1619
1675
return self._real_branch.get_parent()
1677
def _get_parent_location(self):
1678
# Used by tests, when checking normalisation of given vs stored paths.
1680
return self._real_branch._get_parent_location()
1621
1682
def set_parent(self, url):
1622
1683
self._ensure_real()
1623
1684
return self._real_branch.set_parent(url)
1686
def _set_parent_location(self, url):
1687
# Used by tests, to poke bad urls into branch configurations
1689
self.set_parent(url)
1692
return self._real_branch._set_parent_location(url)
1625
1694
def set_stacked_on_url(self, stacked_location):
1626
1695
"""Set the URL this branch is stacked against.
1679
1748
@needs_write_lock
1680
1749
def set_last_revision_info(self, revno, revision_id):
1750
# XXX: These should be returned by the set_last_revision_info verb
1751
old_revno, old_revid = self.last_revision_info()
1752
self._run_pre_change_branch_tip_hooks(revno, revision_id)
1681
1753
revision_id = ensure_null(revision_id)
1683
1755
response = self._call('Branch.set_last_revision_info',
1692
1764
if response == ('ok',):
1693
1765
self._clear_cached_state()
1694
1766
self._last_revision_info_cache = revno, revision_id
1767
self._run_post_change_branch_tip_hooks(old_revno, old_revid)
1695
1768
# Update the _real_branch's cache too.
1696
1769
if self._real_branch is not None:
1697
1770
cache = self._last_revision_info_cache
1704
1777
other_branch=None):
1705
1778
medium = self._client._medium
1706
1779
if not medium._is_remote_before((1, 6)):
1780
# Use a smart method for 1.6 and above servers
1708
1782
self._set_last_revision_descendant(revision_id, other_branch,
1709
1783
allow_diverged=True, allow_overwrite_descendant=True)
1711
1785
except errors.UnknownSmartMethod:
1712
1786
medium._remember_remote_is_before((1, 6))
1713
1787
self._clear_cached_state_of_remote_branch_only()
1715
self._real_branch.generate_revision_history(
1716
revision_id, last_rev=last_rev, other_branch=other_branch)
1788
self.set_revision_history(self._lefthand_history(revision_id,
1789
last_rev=last_rev,other_branch=other_branch))
1719
1792
def tags(self):