154
153
r = BzrDir.open_from_transport(t.clone('stackable')).open_repository()
155
154
self.assertTrue(r._format.supports_external_lookups)
157
def test_remote_branch_set_append_revisions_only(self):
158
# Make a format 1.9 branch, which supports append_revisions_only
159
branch = self.make_branch('branch', format='1.9')
160
config = branch.get_config()
161
branch.set_append_revisions_only(True)
163
'True', config.get_user_option('append_revisions_only'))
164
branch.set_append_revisions_only(False)
166
'False', config.get_user_option('append_revisions_only'))
168
def test_remote_branch_set_append_revisions_only_upgrade_reqd(self):
169
branch = self.make_branch('branch', format='knit')
170
config = branch.get_config()
172
errors.UpgradeRequired, branch.set_append_revisions_only, True)
175
157
class FakeProtocol(object):
176
158
"""Lookalike SmartClientRequestProtocolOne allowing body reading tests."""
763
741
self.assertEqual(network_name, repo._format.network_name())
766
class TestBzrDirFormatInitializeEx(TestRemote):
768
def test_success(self):
769
"""Simple test for typical successful call."""
770
fmt = bzrdir.RemoteBzrDirFormat()
771
default_format_name = BzrDirFormat.get_default_format().network_name()
772
transport = self.get_transport()
773
client = FakeClient(transport.base)
774
client.add_expected_call(
775
'BzrDirFormat.initialize_ex_1.16',
776
(default_format_name, 'path', 'False', 'False', 'False', '',
777
'', '', '', 'False'),
779
('.', 'no', 'no', 'yes', 'repo fmt', 'repo bzrdir fmt',
780
'bzrdir fmt', 'False', '', '', 'repo lock token'))
781
# XXX: It would be better to call fmt.initialize_on_transport_ex, but
782
# it's currently hard to test that without supplying a real remote
783
# transport connected to a real server.
784
result = fmt._initialize_on_transport_ex_rpc(client, 'path',
785
transport, False, False, False, None, None, None, None, False)
786
self.assertFinished(client)
788
def test_error(self):
789
"""Error responses are translated, e.g. 'PermissionDenied' raises the
790
corresponding error from the client.
792
fmt = bzrdir.RemoteBzrDirFormat()
793
default_format_name = BzrDirFormat.get_default_format().network_name()
794
transport = self.get_transport()
795
client = FakeClient(transport.base)
796
client.add_expected_call(
797
'BzrDirFormat.initialize_ex_1.16',
798
(default_format_name, 'path', 'False', 'False', 'False', '',
799
'', '', '', 'False'),
801
('PermissionDenied', 'path', 'extra info'))
802
# XXX: It would be better to call fmt.initialize_on_transport_ex, but
803
# it's currently hard to test that without supplying a real remote
804
# transport connected to a real server.
805
err = self.assertRaises(errors.PermissionDenied,
806
fmt._initialize_on_transport_ex_rpc, client, 'path', transport,
807
False, False, False, None, None, None, None, False)
808
self.assertEqual('path', err.path)
809
self.assertEqual(': extra info', err.extra)
810
self.assertFinished(client)
812
def test_error_from_real_server(self):
813
"""Integration test for error translation."""
814
transport = self.make_smart_server('foo')
815
transport = transport.clone('no-such-path')
816
fmt = bzrdir.RemoteBzrDirFormat()
817
err = self.assertRaises(errors.NoSuchFile,
818
fmt.initialize_on_transport_ex, transport, create_prefix=False)
821
744
class OldSmartClient(object):
822
745
"""A fake smart client for test_old_version that just returns a version one
823
746
response to the 'hello' (query version) command.
2040
1963
self.assertEqual(('AnUnexpectedError',), e.error_tuple)
2043
class TestRepositoryGetRevIdForRevno(TestRemoteRepository):
2046
repo, client = self.setup_fake_client_and_repository('quack')
2047
client.add_expected_call(
2048
'Repository.get_rev_id_for_revno', ('quack/', 5, (42, 'rev-foo')),
2049
'success', ('ok', 'rev-five'))
2050
result = repo.get_rev_id_for_revno(5, (42, 'rev-foo'))
2051
self.assertEqual((True, 'rev-five'), result)
2052
self.assertFinished(client)
2054
def test_history_incomplete(self):
2055
repo, client = self.setup_fake_client_and_repository('quack')
2056
client.add_expected_call(
2057
'Repository.get_rev_id_for_revno', ('quack/', 5, (42, 'rev-foo')),
2058
'success', ('history-incomplete', 10, 'rev-ten'))
2059
result = repo.get_rev_id_for_revno(5, (42, 'rev-foo'))
2060
self.assertEqual((False, (10, 'rev-ten')), result)
2061
self.assertFinished(client)
2063
def test_history_incomplete_with_fallback(self):
2064
"""A 'history-incomplete' response causes the fallback repository to be
2065
queried too, if one is set.
2067
# Make a repo with a fallback repo, both using a FakeClient.
2068
format = remote.response_tuple_to_repo_format(
2069
('yes', 'no', 'yes', 'fake-network-name'))
2070
repo, client = self.setup_fake_client_and_repository('quack')
2071
repo._format = format
2072
fallback_repo, ignored = self.setup_fake_client_and_repository(
2074
fallback_repo._client = client
2075
repo.add_fallback_repository(fallback_repo)
2076
# First the client should ask the primary repo
2077
client.add_expected_call(
2078
'Repository.get_rev_id_for_revno', ('quack/', 1, (42, 'rev-foo')),
2079
'success', ('history-incomplete', 2, 'rev-two'))
2080
# Then it should ask the fallback, using revno/revid from the
2081
# history-incomplete response as the known revno/revid.
2082
client.add_expected_call(
2083
'Repository.get_rev_id_for_revno',('fallback/', 1, (2, 'rev-two')),
2084
'success', ('ok', 'rev-one'))
2085
result = repo.get_rev_id_for_revno(1, (42, 'rev-foo'))
2086
self.assertEqual((True, 'rev-one'), result)
2087
self.assertFinished(client)
2089
def test_nosuchrevision(self):
2090
# 'nosuchrevision' is returned when the known-revid is not found in the
2091
# remote repo. The client translates that response to NoSuchRevision.
2092
repo, client = self.setup_fake_client_and_repository('quack')
2093
client.add_expected_call(
2094
'Repository.get_rev_id_for_revno', ('quack/', 5, (42, 'rev-foo')),
2095
'error', ('nosuchrevision', 'rev-foo'))
2097
errors.NoSuchRevision,
2098
repo.get_rev_id_for_revno, 5, (42, 'rev-foo'))
2099
self.assertFinished(client)
2102
1966
class TestRepositoryIsShared(TestRemoteRepository):
2104
1968
def test_is_shared(self):
2679
2543
result.append(content.key[-1])
2682
def get_ordered_revs(self, format, order, branch_factory=None):
2546
def get_ordered_revs(self, format, order):
2683
2547
"""Get a list of the revisions in a stream to format format.
2685
2549
:param format: The format of the target.
2686
2550
:param order: the order that target should have requested.
2687
:param branch_factory: A callable to create a trunk and stacked branch
2688
to fetch from. If none, self.prepare_stacked_remote_branch is used.
2689
2551
:result: The revision ids in the stream, in the order seen,
2690
2552
the topological order of revisions in the source.
2720
2580
# from the server, then one from the backing branch.
2721
2581
self.assertLength(2, self.hpss_calls)
2723
def test_stacked_on_stacked_get_stream_unordered(self):
2724
# Repository._get_source.get_stream() from a stacked repository which
2725
# is itself stacked yields the full data from all three sources.
2726
def make_stacked_stacked():
2727
_, stacked = self.prepare_stacked_remote_branch()
2728
tree = stacked.bzrdir.sprout('tree3', stacked=True
2729
).open_workingtree()
2730
tree.commit('more local changes are better')
2731
branch = Branch.open(self.get_url('tree3'))
2734
rev_ord, expected_revs = self.get_ordered_revs('1.9', 'unordered',
2735
branch_factory=make_stacked_stacked)
2736
self.assertEqual(set(expected_revs), set(rev_ord))
2737
# Getting unordered results should have made a streaming data request
2738
# from the server, and one from each backing repo
2739
self.assertLength(3, self.hpss_calls)
2741
2583
def test_stacked_get_stream_topological(self):
2742
2584
# Repository._get_source.get_stream() from a stacked repository with
2743
2585
# topological sorting yields the full data from both stacked and
2758
2600
# from the backing branch, and one from the stacked on branch.
2759
2601
self.assertLength(2, self.hpss_calls)
2761
def test_stacked_pull_more_than_stacking_has_bug_360791(self):
2762
# When pulling some fixed amount of content that is more than the
2763
# source has (because some is coming from a fallback branch, no error
2764
# should be received. This was reported as bug 360791.
2765
# Need three branches: a trunk, a stacked branch, and a preexisting
2766
# branch pulling content from stacked and trunk.
2767
self.setup_smart_server_with_call_log()
2768
trunk = self.make_branch_and_tree('trunk', format="1.9-rich-root")
2769
r1 = trunk.commit('start')
2770
stacked_branch = trunk.branch.create_clone_on_transport(
2771
self.get_transport('stacked'), stacked_on=trunk.branch.base)
2772
local = self.make_branch('local', format='1.9-rich-root')
2773
local.repository.fetch(stacked_branch.repository,
2774
stacked_branch.last_revision())
2777
2604
class TestRemoteBranchEffort(tests.TestCaseWithTransport):