57
53
RemoteRepositoryFormat,
59
from bzrlib.repofmt import groupcompress_repo, knitpack_repo
55
from bzrlib.repofmt import groupcompress_repo, pack_repo
60
56
from bzrlib.revision import NULL_REVISION
61
from bzrlib.smart import medium, request
57
from bzrlib.smart import server, medium
62
58
from bzrlib.smart.client import _SmartClient
63
from bzrlib.smart.repository import (
64
SmartServerRepositoryGetParentMap,
65
SmartServerRepositoryGetStream_1_19,
59
from bzrlib.smart.repository import SmartServerRepositoryGetParentMap
67
60
from bzrlib.tests import (
62
split_suite_by_condition,
70
from bzrlib.tests.scenarios import load_tests_apply_scenarios
66
from bzrlib.transport import get_transport, http
71
67
from bzrlib.transport.memory import MemoryTransport
72
68
from bzrlib.transport.remote import (
74
70
RemoteSSHTransport,
75
71
RemoteTCPTransport,
79
load_tests = load_tests_apply_scenarios
82
class BasicRemoteObjectTests(tests.TestCaseWithTransport):
74
def load_tests(standard_tests, module, loader):
75
to_adapt, result = split_suite_by_condition(
76
standard_tests, condition_isinstance(BasicRemoteObjectTests))
77
smart_server_version_scenarios = [
86
{'transport_server': test_server.SmartTCPServer_for_testing_v2_only}),
79
{'transport_server': server.SmartTCPServer_for_testing_v2_only}),
88
{'transport_server': test_server.SmartTCPServer_for_testing})]
81
{'transport_server': server.SmartTCPServer_for_testing})]
82
return multiply_tests(to_adapt, smart_server_version_scenarios, result)
85
class BasicRemoteObjectTests(tests.TestCaseWithTransport):
92
88
super(BasicRemoteObjectTests, self).setUp()
93
89
self.transport = self.get_transport()
94
90
# make a branch that can be opened over the smart transport
95
91
self.local_wt = BzrDir.create_standalone_workingtree('.')
96
self.addCleanup(self.transport.disconnect)
94
self.transport.disconnect()
95
tests.TestCaseWithTransport.tearDown(self)
98
97
def test_create_remote_bzrdir(self):
99
b = remote.RemoteBzrDir(self.transport, RemoteBzrDirFormat())
98
b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
100
99
self.assertIsInstance(b, BzrDir)
102
101
def test_open_remote_branch(self):
103
102
# open a standalone branch in the working directory
104
b = remote.RemoteBzrDir(self.transport, RemoteBzrDirFormat())
103
b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
105
104
branch = b.open_branch()
106
105
self.assertIsInstance(branch, Branch)
482
468
self.assertFinished(client)
485
class TestBzrDirOpen(TestRemote):
487
def make_fake_client_and_transport(self, path='quack'):
488
transport = MemoryTransport()
489
transport.mkdir(path)
490
transport = transport.clone(path)
491
client = FakeClient(transport.base)
492
return client, transport
494
def test_absent(self):
495
client, transport = self.make_fake_client_and_transport()
496
client.add_expected_call(
497
'BzrDir.open_2.1', ('quack/',), 'success', ('no',))
498
self.assertRaises(errors.NotBranchError, RemoteBzrDir, transport,
499
RemoteBzrDirFormat(), _client=client, _force_probe=True)
500
self.assertFinished(client)
502
def test_present_without_workingtree(self):
503
client, transport = self.make_fake_client_and_transport()
504
client.add_expected_call(
505
'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'no'))
506
bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
507
_client=client, _force_probe=True)
508
self.assertIsInstance(bd, RemoteBzrDir)
509
self.assertFalse(bd.has_workingtree())
510
self.assertRaises(errors.NoWorkingTree, bd.open_workingtree)
511
self.assertFinished(client)
513
def test_present_with_workingtree(self):
514
client, transport = self.make_fake_client_and_transport()
515
client.add_expected_call(
516
'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'yes'))
517
bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
518
_client=client, _force_probe=True)
519
self.assertIsInstance(bd, RemoteBzrDir)
520
self.assertTrue(bd.has_workingtree())
521
self.assertRaises(errors.NotLocalUrl, bd.open_workingtree)
522
self.assertFinished(client)
524
def test_backwards_compat(self):
525
client, transport = self.make_fake_client_and_transport()
526
client.add_expected_call(
527
'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
528
client.add_expected_call(
529
'BzrDir.open', ('quack/',), 'success', ('yes',))
530
bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
531
_client=client, _force_probe=True)
532
self.assertIsInstance(bd, RemoteBzrDir)
533
self.assertFinished(client)
535
def test_backwards_compat_hpss_v2(self):
536
client, transport = self.make_fake_client_and_transport()
537
# Monkey-patch fake client to simulate real-world behaviour with v2
538
# server: upon first RPC call detect the protocol version, and because
539
# the version is 2 also do _remember_remote_is_before((1, 6)) before
540
# continuing with the RPC.
541
orig_check_call = client._check_call
542
def check_call(method, args):
543
client._medium._protocol_version = 2
544
client._medium._remember_remote_is_before((1, 6))
545
client._check_call = orig_check_call
546
client._check_call(method, args)
547
client._check_call = check_call
548
client.add_expected_call(
549
'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
550
client.add_expected_call(
551
'BzrDir.open', ('quack/',), 'success', ('yes',))
552
bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
553
_client=client, _force_probe=True)
554
self.assertIsInstance(bd, RemoteBzrDir)
555
self.assertFinished(client)
558
471
class TestBzrDirOpenBranch(TestRemote):
560
473
def test_backwards_compat(self):
599
512
transport = transport.clone('quack')
600
513
client = FakeClient(transport.base)
601
514
client.add_error_response('nobranch')
602
bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
515
bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
604
517
self.assertRaises(errors.NotBranchError, bzrdir.open_branch)
605
518
self.assertEqual(
606
[('call', 'BzrDir.open_branchV3', ('quack/',))],
519
[('call', 'BzrDir.open_branchV2', ('quack/',))],
609
522
def test__get_tree_branch(self):
610
523
# _get_tree_branch is a form of open_branch, but it should only ask for
611
524
# branch opening, not any other network requests.
613
def open_branch(name=None):
614
527
calls.append("Called")
615
528
return "a-branch"
616
529
transport = MemoryTransport()
617
530
# no requests on the network - catches other api calls being made.
618
531
client = FakeClient(transport.base)
619
bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
532
bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
621
534
# patch the open_branch call to record that it was called.
622
535
bzrdir.open_branch = open_branch
725
638
format = branch._format
726
639
self.assertEqual(network_name, format.network_name())
728
def test_already_open_repo_and_reused_medium(self):
729
"""Bug 726584: create_branch(..., repository=repo) should work
730
regardless of what the smart medium's base URL is.
732
self.transport_server = test_server.SmartTCPServer_for_testing
733
transport = self.get_transport('.')
734
repo = self.make_repository('quack')
735
# Client's medium rooted a transport root (not at the bzrdir)
736
client = FakeClient(transport.base)
737
transport = transport.clone('quack')
738
reference_bzrdir_format = bzrdir.format_registry.get('default')()
739
reference_format = reference_bzrdir_format.get_branch_format()
740
network_name = reference_format.network_name()
741
reference_repo_fmt = reference_bzrdir_format.repository_format
742
reference_repo_name = reference_repo_fmt.network_name()
743
client.add_expected_call(
744
'BzrDir.create_branch', ('extra/quack/', network_name),
745
'success', ('ok', network_name, '', 'no', 'no', 'yes',
746
reference_repo_name))
747
a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
749
branch = a_bzrdir.create_branch(repository=repo)
750
# We should have got a remote branch
751
self.assertIsInstance(branch, remote.RemoteBranch)
752
# its format should have the settings from the response
753
format = branch._format
754
self.assertEqual(network_name, format.network_name())
757
642
class TestBzrDirCreateRepository(TestRemote):
776
661
network_name = reference_format.network_name()
777
662
client.add_expected_call(
778
663
'BzrDir.create_repository', ('quack/',
779
'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
781
'success', ('ok', 'yes', 'yes', 'yes', network_name))
782
a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
664
'Bazaar pack repository format 1 (needs bzr 0.92)\n', 'False'),
665
'success', ('ok', 'no', 'no', 'no', network_name))
666
a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
784
668
repo = a_bzrdir.create_repository()
785
669
# We should have got a remote repository
786
670
self.assertIsInstance(repo, remote.RemoteRepository)
787
671
# its format should have the settings from the response
788
672
format = repo._format
789
self.assertTrue(format.rich_root_data)
790
self.assertTrue(format.supports_tree_reference)
791
self.assertTrue(format.supports_external_lookups)
673
self.assertFalse(format.rich_root_data)
674
self.assertFalse(format.supports_tree_reference)
675
self.assertFalse(format.supports_external_lookups)
792
676
self.assertEqual(network_name, format.network_name())
1124
994
self.assertEqual({}, result)
1127
class TestBranchSetTagsBytes(RemoteBranchTestCase):
1129
def test_trivial(self):
1130
transport = MemoryTransport()
1131
client = FakeClient(transport.base)
1132
client.add_expected_call(
1133
'Branch.get_stacked_on_url', ('quack/',),
1134
'error', ('NotStacked',))
1135
client.add_expected_call(
1136
'Branch.set_tags_bytes', ('quack/', 'branch token', 'repo token'),
1138
transport.mkdir('quack')
1139
transport = transport.clone('quack')
1140
branch = self.make_remote_branch(transport, client)
1141
self.lock_remote_branch(branch)
1142
branch._set_tags_bytes('tags bytes')
1143
self.assertFinished(client)
1144
self.assertEqual('tags bytes', client._calls[-1][-1])
1146
def test_backwards_compatible(self):
1147
transport = MemoryTransport()
1148
client = FakeClient(transport.base)
1149
client.add_expected_call(
1150
'Branch.get_stacked_on_url', ('quack/',),
1151
'error', ('NotStacked',))
1152
client.add_expected_call(
1153
'Branch.set_tags_bytes', ('quack/', 'branch token', 'repo token'),
1154
'unknown', ('Branch.set_tags_bytes',))
1155
transport.mkdir('quack')
1156
transport = transport.clone('quack')
1157
branch = self.make_remote_branch(transport, client)
1158
self.lock_remote_branch(branch)
1159
class StubRealBranch(object):
1162
def _set_tags_bytes(self, bytes):
1163
self.calls.append(('set_tags_bytes', bytes))
1164
real_branch = StubRealBranch()
1165
branch._real_branch = real_branch
1166
branch._set_tags_bytes('tags bytes')
1167
# Call a second time, to exercise the 'remote version already inferred'
1169
branch._set_tags_bytes('tags bytes')
1170
self.assertFinished(client)
1172
[('set_tags_bytes', 'tags bytes')] * 2, real_branch.calls)
1175
class TestBranchHeadsToFetch(RemoteBranchTestCase):
1177
def test_uses_last_revision_info_and_tags_by_default(self):
1178
transport = MemoryTransport()
1179
client = FakeClient(transport.base)
1180
client.add_expected_call(
1181
'Branch.get_stacked_on_url', ('quack/',),
1182
'error', ('NotStacked',))
1183
client.add_expected_call(
1184
'Branch.last_revision_info', ('quack/',),
1185
'success', ('ok', '1', 'rev-tip'))
1186
# XXX: this will break if the default format's serialization of tags
1187
# changes, or if the RPC for fetching tags changes from get_tags_bytes.
1188
client.add_expected_call(
1189
'Branch.get_tags_bytes', ('quack/',),
1190
'success', ('d5:tag-17:rev-foo5:tag-27:rev-bare',))
1191
transport.mkdir('quack')
1192
transport = transport.clone('quack')
1193
branch = self.make_remote_branch(transport, client)
1194
result = branch.heads_to_fetch()
1195
self.assertFinished(client)
1197
(set(['rev-tip']), set(['rev-foo', 'rev-bar'])), result)
1199
def test_uses_rpc_for_formats_with_non_default_heads_to_fetch(self):
1200
transport = MemoryTransport()
1201
client = FakeClient(transport.base)
1202
client.add_expected_call(
1203
'Branch.get_stacked_on_url', ('quack/',),
1204
'error', ('NotStacked',))
1205
client.add_expected_call(
1206
'Branch.heads_to_fetch', ('quack/',),
1207
'success', (['tip'], ['tagged-1', 'tagged-2']))
1208
transport.mkdir('quack')
1209
transport = transport.clone('quack')
1210
branch = self.make_remote_branch(transport, client)
1211
branch._format._use_default_local_heads_to_fetch = lambda: False
1212
result = branch.heads_to_fetch()
1213
self.assertFinished(client)
1214
self.assertEqual((set(['tip']), set(['tagged-1', 'tagged-2'])), result)
1216
def test_backwards_compatible(self):
1217
self.setup_smart_server_with_call_log()
1218
# Make a branch with a single revision.
1219
builder = self.make_branch_builder('foo')
1220
builder.start_series()
1221
builder.build_snapshot('tip', None, [
1222
('add', ('', 'root-id', 'directory', ''))])
1223
builder.finish_series()
1224
branch = builder.get_branch()
1225
# Add two tags to that branch
1226
branch.tags.set_tag('tag-1', 'rev-1')
1227
branch.tags.set_tag('tag-2', 'rev-2')
1228
self.addCleanup(branch.lock_read().unlock)
1229
# Disable the heads_to_fetch verb
1230
verb = 'Branch.heads_to_fetch'
1231
self.disable_verb(verb)
1232
self.reset_smart_call_log()
1233
result = branch.heads_to_fetch()
1234
self.assertEqual((set(['tip']), set(['rev-1', 'rev-2'])), result)
1236
['Branch.last_revision_info', 'Branch.get_tags_bytes'],
1237
[call.call.method for call in self.hpss_calls])
1240
997
class TestBranchLastRevisionInfo(RemoteBranchTestCase):
1242
999
def test_empty_branch(self):
1342
1099
len(branch.repository._real_repository._fallback_repositories))
1344
1101
def test_get_stacked_on_real_branch(self):
1345
base_branch = self.make_branch('base')
1346
stacked_branch = self.make_branch('stacked')
1102
base_branch = self.make_branch('base', format='1.6')
1103
stacked_branch = self.make_branch('stacked', format='1.6')
1347
1104
stacked_branch.set_stacked_on_url('../base')
1348
1105
reference_format = self.get_repo_format()
1349
1106
network_name = reference_format.network_name()
1350
1107
client = FakeClient(self.get_url())
1351
1108
branch_network_name = self.get_branch_format().network_name()
1352
1109
client.add_expected_call(
1353
'BzrDir.open_branchV3', ('stacked/',),
1110
'BzrDir.open_branchV2', ('stacked/',),
1354
1111
'success', ('branch', branch_network_name))
1355
1112
client.add_expected_call(
1356
1113
'BzrDir.find_repositoryV3', ('stacked/',),
1357
'success', ('ok', '', 'yes', 'no', 'yes', network_name))
1114
'success', ('ok', '', 'no', 'no', 'yes', network_name))
1358
1115
# called twice, once from constructor and then again by us
1359
1116
client.add_expected_call(
1360
1117
'Branch.get_stacked_on_url', ('stacked/',),
1747
1513
branch.unlock()
1748
1514
self.assertFinished(client)
1750
def test_set_option_with_dict(self):
1751
client = FakeClient()
1752
client.add_expected_call(
1753
'Branch.get_stacked_on_url', ('memory:///',),
1754
'error', ('NotStacked',),)
1755
client.add_expected_call(
1756
'Branch.lock_write', ('memory:///', '', ''),
1757
'success', ('ok', 'branch token', 'repo token'))
1758
encoded_dict_value = 'd5:ascii1:a11:unicode \xe2\x8c\x9a3:\xe2\x80\xbde'
1759
client.add_expected_call(
1760
'Branch.set_config_option_dict', ('memory:///', 'branch token',
1761
'repo token', encoded_dict_value, 'foo', ''),
1763
client.add_expected_call(
1764
'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
1766
transport = MemoryTransport()
1767
branch = self.make_remote_branch(transport, client)
1769
config = branch._get_config()
1771
{'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'},
1774
self.assertFinished(client)
1776
1516
def test_backwards_compat_set_option(self):
1777
1517
self.setup_smart_server_with_call_log()
1778
1518
branch = self.make_branch('.')
1940
1666
client = FakeClient(transport.base)
1941
1667
transport = transport.clone(transport_path)
1942
1668
# we do not want bzrdir to make any remote calls
1943
bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1669
bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1945
1671
repo = RemoteRepository(bzrdir, None, _client=client)
1946
1672
return repo, client
1949
def remoted_description(format):
1950
return 'Remote: ' + format.get_format_description()
1953
class TestBranchFormat(tests.TestCase):
1955
def test_get_format_description(self):
1956
remote_format = RemoteBranchFormat()
1957
real_format = branch.format_registry.get_default()
1958
remote_format._network_name = real_format.network_name()
1959
self.assertEqual(remoted_description(real_format),
1960
remote_format.get_format_description())
1963
1675
class TestRepositoryFormat(TestRemoteRepository):
1965
1677
def test_fast_delta(self):
1966
true_name = groupcompress_repo.RepositoryFormat2a().network_name()
1678
true_name = groupcompress_repo.RepositoryFormatCHK1().network_name()
1967
1679
true_format = RemoteRepositoryFormat()
1968
1680
true_format._network_name = true_name
1969
1681
self.assertEqual(True, true_format.fast_deltas)
1970
false_name = knitpack_repo.RepositoryFormatKnitPack1().network_name()
1682
false_name = pack_repo.RepositoryFormatKnitPack1().network_name()
1971
1683
false_format = RemoteRepositoryFormat()
1972
1684
false_format._network_name = false_name
1973
1685
self.assertEqual(False, false_format.fast_deltas)
1975
def test_get_format_description(self):
1976
remote_repo_format = RemoteRepositoryFormat()
1977
real_format = repository.format_registry.get_default()
1978
remote_repo_format._network_name = real_format.network_name()
1979
self.assertEqual(remoted_description(real_format),
1980
remote_repo_format.get_format_description())
1983
1688
class TestRepositoryGatherStats(TestRemoteRepository):
2526
2213
self.assertEqual([], client._calls)
2529
class TestRepositoryInsertStreamBase(TestRemoteRepository):
2530
"""Base class for Repository.insert_stream and .insert_stream_1.19
2534
def checkInsertEmptyStream(self, repo, client):
2535
"""Insert an empty stream, checking the result.
2537
This checks that there are no resume_tokens or missing_keys, and that
2538
the client is finished.
2540
sink = repo._get_sink()
2541
fmt = repository.format_registry.get_default()
2542
resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
2543
self.assertEqual([], resume_tokens)
2544
self.assertEqual(set(), missing_keys)
2545
self.assertFinished(client)
2548
class TestRepositoryInsertStream(TestRepositoryInsertStreamBase):
2549
"""Tests for using Repository.insert_stream verb when the _1.19 variant is
2216
class TestRepositoryInsertStream(TestRemoteRepository):
2217
"""Tests for using Repository.insert_stream verb when the _1.18 variant is
2552
This test case is very similar to TestRepositoryInsertStream_1_19.
2220
This test case is very similar to TestRepositoryInsertStream_1_18.
2555
2223
def setUp(self):
2556
2224
TestRemoteRepository.setUp(self)
2557
self.disable_verb('Repository.insert_stream_1.19')
2225
self.disable_verb('Repository.insert_stream_1.18')
2559
2227
def test_unlocked_repo(self):
2560
2228
transport_path = 'quack'
2561
2229
repo, client = self.setup_fake_client_and_repository(transport_path)
2562
2230
client.add_expected_call(
2563
'Repository.insert_stream_1.19', ('quack/', ''),
2564
'unknown', ('Repository.insert_stream_1.19',))
2565
client.add_expected_call(
2566
'Repository.insert_stream', ('quack/', ''),
2568
client.add_expected_call(
2569
'Repository.insert_stream', ('quack/', ''),
2571
self.checkInsertEmptyStream(repo, client)
2231
'Repository.insert_stream_1.18', ('quack/', ''),
2232
'unknown', ('Repository.insert_stream_1.18',))
2233
client.add_expected_call(
2234
'Repository.insert_stream', ('quack/', ''),
2236
client.add_expected_call(
2237
'Repository.insert_stream', ('quack/', ''),
2239
sink = repo._get_sink()
2240
fmt = repository.RepositoryFormat.get_default_format()
2241
resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
2242
self.assertEqual([], resume_tokens)
2243
self.assertEqual(set(), missing_keys)
2244
self.assertFinished(client)
2573
2246
def test_locked_repo_with_no_lock_token(self):
2574
2247
transport_path = 'quack'
2604
2282
'Repository.insert_stream_locked', ('quack/', '', 'a token'),
2605
2283
'success', ('ok',))
2606
2284
repo.lock_write()
2607
self.checkInsertEmptyStream(repo, client)
2285
sink = repo._get_sink()
2286
fmt = repository.RepositoryFormat.get_default_format()
2287
resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
2288
self.assertEqual([], resume_tokens)
2289
self.assertEqual(set(), missing_keys)
2290
self.assertFinished(client)
2609
2292
def test_stream_with_inventory_deltas(self):
2610
"""'inventory-deltas' substreams cannot be sent to the
2611
Repository.insert_stream verb, because not all servers that implement
2612
that verb will accept them. So when one is encountered the RemoteSink
2613
immediately stops using that verb and falls back to VFS insert_stream.
2293
"""'inventory-deltas' substreams can't be sent to the
2294
Repository.insert_stream verb. So when one is encountered the
2295
RemoteSink immediately stops using that verb and falls back to VFS
2615
2298
transport_path = 'quack'
2616
2299
repo, client = self.setup_fake_client_and_repository(transport_path)
2617
2300
client.add_expected_call(
2618
'Repository.insert_stream_1.19', ('quack/', ''),
2619
'unknown', ('Repository.insert_stream_1.19',))
2301
'Repository.insert_stream_1.18', ('quack/', ''),
2302
'unknown', ('Repository.insert_stream_1.18',))
2620
2303
client.add_expected_call(
2621
2304
'Repository.insert_stream', ('quack/', ''),
2622
2305
'success', ('ok',))
2702
2380
return stream_with_inv_delta()
2705
class TestRepositoryInsertStream_1_19(TestRepositoryInsertStreamBase):
2383
class TestRepositoryInsertStream_1_18(TestRemoteRepository):
2707
2385
def test_unlocked_repo(self):
2708
2386
transport_path = 'quack'
2709
2387
repo, client = self.setup_fake_client_and_repository(transport_path)
2710
2388
client.add_expected_call(
2711
'Repository.insert_stream_1.19', ('quack/', ''),
2389
'Repository.insert_stream_1.18', ('quack/', ''),
2712
2390
'success', ('ok',))
2713
2391
client.add_expected_call(
2714
'Repository.insert_stream_1.19', ('quack/', ''),
2392
'Repository.insert_stream_1.18', ('quack/', ''),
2715
2393
'success', ('ok',))
2716
self.checkInsertEmptyStream(repo, client)
2394
sink = repo._get_sink()
2395
fmt = repository.RepositoryFormat.get_default_format()
2396
resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
2397
self.assertEqual([], resume_tokens)
2398
self.assertEqual(set(), missing_keys)
2399
self.assertFinished(client)
2718
2401
def test_locked_repo_with_no_lock_token(self):
2719
2402
transport_path = 'quack'
2722
2405
'Repository.lock_write', ('quack/', ''),
2723
2406
'success', ('ok', ''))
2724
2407
client.add_expected_call(
2725
'Repository.insert_stream_1.19', ('quack/', ''),
2408
'Repository.insert_stream_1.18', ('quack/', ''),
2726
2409
'success', ('ok',))
2727
2410
client.add_expected_call(
2728
'Repository.insert_stream_1.19', ('quack/', ''),
2411
'Repository.insert_stream_1.18', ('quack/', ''),
2729
2412
'success', ('ok',))
2730
2413
repo.lock_write()
2731
self.checkInsertEmptyStream(repo, client)
2414
sink = repo._get_sink()
2415
fmt = repository.RepositoryFormat.get_default_format()
2416
resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
2417
self.assertEqual([], resume_tokens)
2418
self.assertEqual(set(), missing_keys)
2419
self.assertFinished(client)
2733
2421
def test_locked_repo_with_lock_token(self):
2734
2422
transport_path = 'quack'
2737
2425
'Repository.lock_write', ('quack/', ''),
2738
2426
'success', ('ok', 'a token'))
2739
2427
client.add_expected_call(
2740
'Repository.insert_stream_1.19', ('quack/', '', 'a token'),
2428
'Repository.insert_stream_1.18', ('quack/', '', 'a token'),
2741
2429
'success', ('ok',))
2742
2430
client.add_expected_call(
2743
'Repository.insert_stream_1.19', ('quack/', '', 'a token'),
2431
'Repository.insert_stream_1.18', ('quack/', '', 'a token'),
2744
2432
'success', ('ok',))
2745
2433
repo.lock_write()
2746
self.checkInsertEmptyStream(repo, client)
2434
sink = repo._get_sink()
2435
fmt = repository.RepositoryFormat.get_default_format()
2436
resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
2437
self.assertEqual([], resume_tokens)
2438
self.assertEqual(set(), missing_keys)
2439
self.assertFinished(client)
2749
2442
class TestRepositoryTarball(TestRemoteRepository):
3055
2708
expected_error = errors.PermissionDenied(path, extra)
3056
2709
self.assertEqual(expected_error, translated_error)
3058
# GZ 2011-03-02: TODO test for PermissionDenied with non-ascii 'extra'
3060
def test_NoSuchFile_context_path(self):
3061
local_path = "local path"
3062
translated_error = self.translateTuple(('ReadError', "remote path"),
3064
expected_error = errors.ReadError(local_path)
3065
self.assertEqual(expected_error, translated_error)
3067
def test_NoSuchFile_without_context(self):
3068
remote_path = "remote path"
3069
translated_error = self.translateTuple(('ReadError', remote_path))
3070
expected_error = errors.ReadError(remote_path)
3071
self.assertEqual(expected_error, translated_error)
3073
def test_ReadOnlyError(self):
3074
translated_error = self.translateTuple(('ReadOnlyError',))
3075
expected_error = errors.TransportNotPossible("readonly transport")
3076
self.assertEqual(expected_error, translated_error)
3078
def test_MemoryError(self):
3079
translated_error = self.translateTuple(('MemoryError',))
3080
self.assertStartsWith(str(translated_error),
3081
"remote server out of memory")
3083
def test_generic_IndexError_no_classname(self):
3084
err = errors.ErrorFromSmartServer(('error', "list index out of range"))
3085
translated_error = self.translateErrorFromSmartServer(err)
3086
expected_error = errors.UnknownErrorFromSmartServer(err)
3087
self.assertEqual(expected_error, translated_error)
3089
# GZ 2011-03-02: TODO test generic non-ascii error string
3091
def test_generic_KeyError(self):
3092
err = errors.ErrorFromSmartServer(('error', 'KeyError', "1"))
3093
translated_error = self.translateErrorFromSmartServer(err)
3094
expected_error = errors.UnknownErrorFromSmartServer(err)
3095
self.assertEqual(expected_error, translated_error)
3098
2712
class TestErrorTranslationRobustness(TestErrorTranslationBase):
3099
2713
"""Unit tests for bzrlib.remote._translate_error's robustness.
3344
2955
def test_copy_content_into_avoids_revision_history(self):
3345
2956
local = self.make_branch('local')
3346
builder = self.make_branch_builder('remote')
3347
builder.build_commit(message="Commit.")
2957
remote_backing_tree = self.make_branch_and_tree('remote')
2958
remote_backing_tree.commit("Commit.")
3348
2959
remote_branch_url = self.smart_server.get_url() + 'remote'
3349
2960
remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
3350
2961
local.repository.fetch(remote_branch.repository)
3351
2962
self.hpss_calls = []
3352
2963
remote_branch.copy_content_into(local)
3353
2964
self.assertFalse('Branch.revision_history' in self.hpss_calls)
3355
def test_fetch_everything_needs_just_one_call(self):
3356
local = self.make_branch('local')
3357
builder = self.make_branch_builder('remote')
3358
builder.build_commit(message="Commit.")
3359
remote_branch_url = self.smart_server.get_url() + 'remote'
3360
remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
3361
self.hpss_calls = []
3362
local.repository.fetch(remote_branch.repository,
3363
fetch_spec=_mod_graph.EverythingResult(remote_branch.repository))
3364
self.assertEqual(['Repository.get_stream_1.19'], self.hpss_calls)
3366
def override_verb(self, verb_name, verb):
3367
request_handlers = request.request_handlers
3368
orig_verb = request_handlers.get(verb_name)
3369
request_handlers.register(verb_name, verb, override_existing=True)
3370
self.addCleanup(request_handlers.register, verb_name, orig_verb,
3371
override_existing=True)
3373
def test_fetch_everything_backwards_compat(self):
3374
"""Can fetch with EverythingResult even with pre 2.4 servers.
3376
Pre-2.4 do not support 'everything' searches with the
3377
Repository.get_stream_1.19 verb.
3380
class OldGetStreamVerb(SmartServerRepositoryGetStream_1_19):
3381
"""A version of the Repository.get_stream_1.19 verb patched to
3382
reject 'everything' searches the way 2.3 and earlier do.
3384
def recreate_search(self, repository, search_bytes, discard_excess=False):
3385
verb_log.append(search_bytes.split('\n', 1)[0])
3386
if search_bytes == 'everything':
3387
return (None, request.FailedSmartServerResponse(('BadSearch',)))
3388
return super(OldGetStreamVerb,
3389
self).recreate_search(repository, search_bytes,
3390
discard_excess=discard_excess)
3391
self.override_verb('Repository.get_stream_1.19', OldGetStreamVerb)
3392
local = self.make_branch('local')
3393
builder = self.make_branch_builder('remote')
3394
builder.build_commit(message="Commit.")
3395
remote_branch_url = self.smart_server.get_url() + 'remote'
3396
remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
3397
self.hpss_calls = []
3398
local.repository.fetch(remote_branch.repository,
3399
fetch_spec=_mod_graph.EverythingResult(remote_branch.repository))
3400
# make sure the overridden verb was used
3401
self.assertLength(1, verb_log)
3402
# more than one HPSS call is needed, but because it's a VFS callback
3403
# its hard to predict exactly how many.
3404
self.assertTrue(len(self.hpss_calls) > 1)