225
220
_SmartClient.__init__(self, FakeMedium(self._calls, fake_medium_base))
227
222
def add_expected_call(self, call_name, call_args, response_type,
228
response_args, response_body=None):
223
response_args, response_body=None):
229
224
if self._expected_calls is None:
230
225
self._expected_calls = []
231
226
self._expected_calls.append((call_name, call_args))
232
227
self.responses.append((response_type, response_args, response_body))
234
229
def add_success_response(self, *args):
235
self.responses.append((b'success', args, None))
230
self.responses.append(('success', args, None))
237
232
def add_success_response_with_body(self, body, *args):
238
self.responses.append((b'success', args, body))
233
self.responses.append(('success', args, body))
239
234
if self._expected_calls is not None:
240
235
self._expected_calls.append(None)
242
237
def add_error_response(self, *args):
243
self.responses.append((b'error', args))
238
self.responses.append(('error', args))
245
240
def add_unknown_method_response(self, verb):
246
self.responses.append((b'unknown', verb))
241
self.responses.append(('unknown', verb))
248
243
def finished_test(self):
249
244
if self._expected_calls:
250
245
raise AssertionError("%r finished but was still expecting %r"
251
% (self, self._expected_calls[0]))
246
% (self, self._expected_calls[0]))
253
248
def _get_next_response(self):
255
250
response_tuple = self.responses.pop(0)
257
raise AssertionError("%r didn't expect any more calls" % (self,))
258
if response_tuple[0] == b'unknown':
251
except IndexError, e:
252
raise AssertionError("%r didn't expect any more calls"
254
if response_tuple[0] == 'unknown':
259
255
raise errors.UnknownSmartMethod(response_tuple[1])
260
elif response_tuple[0] == b'error':
256
elif response_tuple[0] == 'error':
261
257
raise errors.ErrorFromSmartServer(response_tuple[1])
262
258
return response_tuple
438
433
def test_backwards_compat(self):
439
434
self.setup_smart_server_with_call_log()
440
a_dir = self.make_controldir('.')
435
a_dir = self.make_bzrdir('.')
441
436
self.reset_smart_call_log()
442
verb = b'BzrDir.cloning_metadir'
437
verb = 'BzrDir.cloning_metadir'
443
438
self.disable_verb(verb)
444
a_dir.cloning_metadir()
439
format = a_dir.cloning_metadir()
445
440
call_count = len([call for call in self.hpss_calls if
446
call.call.method == verb])
441
call.call.method == verb])
447
442
self.assertEqual(1, call_count)
449
444
def test_branch_reference(self):
450
445
transport = self.get_transport('quack')
451
446
referenced = self.make_branch('referenced')
452
expected = referenced.controldir.cloning_metadir()
447
expected = referenced.bzrdir.cloning_metadir()
453
448
client = FakeClient(transport.base)
454
449
client.add_expected_call(
455
b'BzrDir.cloning_metadir', (b'quack/', b'False'),
456
b'error', (b'BranchReference',)),
450
'BzrDir.cloning_metadir', ('quack/', 'False'),
451
'error', ('BranchReference',)),
457
452
client.add_expected_call(
458
b'BzrDir.open_branchV3', (b'quack/',),
459
b'success', (b'ref', self.get_url('referenced').encode('utf-8'))),
460
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
462
result = a_controldir.cloning_metadir()
453
'BzrDir.open_branchV3', ('quack/',),
454
'success', ('ref', self.get_url('referenced'))),
455
a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
457
result = a_bzrdir.cloning_metadir()
463
458
# We should have got a control dir matching the referenced branch.
464
459
self.assertEqual(bzrdir.BzrDirMetaFormat1, type(result))
465
self.assertEqual(expected._repository_format,
466
result._repository_format)
460
self.assertEqual(expected._repository_format, result._repository_format)
467
461
self.assertEqual(expected._branch_format, result._branch_format)
468
462
self.assertFinished(client)
470
464
def test_current_server(self):
471
465
transport = self.get_transport('.')
472
466
transport = transport.clone('quack')
473
self.make_controldir('quack')
467
self.make_bzrdir('quack')
474
468
client = FakeClient(transport.base)
475
469
reference_bzrdir_format = controldir.format_registry.get('default')()
476
470
control_name = reference_bzrdir_format.network_name()
477
471
client.add_expected_call(
478
b'BzrDir.cloning_metadir', (b'quack/', b'False'),
479
b'success', (control_name, b'', (b'branch', b''))),
480
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
482
result = a_controldir.cloning_metadir()
472
'BzrDir.cloning_metadir', ('quack/', 'False'),
473
'success', (control_name, '', ('branch', ''))),
474
a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
476
result = a_bzrdir.cloning_metadir()
483
477
# We should have got a reference control dir with default branch and
484
478
# repository formats.
485
479
# This pokes a little, just to be sure.
548
541
branch_name = reference_bzrdir_format.get_branch_format().network_name()
549
542
client.add_success_response_with_body(
550
543
bencode.bencode({
551
b"foo": (b"branch", branch_name),
552
b"": (b"branch", branch_name)}), b"success")
553
client.add_success_response(
554
b'ok', b'', b'no', b'no', b'no',
555
reference_bzrdir_format.repository_format.network_name())
556
client.add_error_response(b'NotStacked')
557
client.add_success_response(
558
b'ok', b'', b'no', b'no', b'no',
559
reference_bzrdir_format.repository_format.network_name())
560
client.add_error_response(b'NotStacked')
544
"foo": ("branch", branch_name),
545
"": ("branch", branch_name)}), "success")
546
client.add_success_response(
547
'ok', '', 'no', 'no', 'no',
548
reference_bzrdir_format.repository_format.network_name())
549
client.add_error_response('NotStacked')
550
client.add_success_response(
551
'ok', '', 'no', 'no', 'no',
552
reference_bzrdir_format.repository_format.network_name())
553
client.add_error_response('NotStacked')
561
554
transport.mkdir('quack')
562
555
transport = transport.clone('quack')
563
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
565
result = a_controldir.get_branches()
566
self.assertEqual({"", "foo"}, set(result.keys()))
556
a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
558
result = a_bzrdir.get_branches()
559
self.assertEqual(set(["", "foo"]), set(result.keys()))
567
560
self.assertEqual(
568
[('call_expecting_body', b'BzrDir.get_branches', (b'quack/',)),
569
('call', b'BzrDir.find_repositoryV3', (b'quack/', )),
570
('call', b'Branch.get_stacked_on_url', (b'quack/', )),
571
('call', b'BzrDir.find_repositoryV3', (b'quack/', )),
572
('call', b'Branch.get_stacked_on_url', (b'quack/', ))],
561
[('call_expecting_body', 'BzrDir.get_branches', ('quack/',)),
562
('call', 'BzrDir.find_repositoryV3', ('quack/', )),
563
('call', 'Branch.get_stacked_on_url', ('quack/', )),
564
('call', 'BzrDir.find_repositoryV3', ('quack/', )),
565
('call', 'Branch.get_stacked_on_url', ('quack/', ))],
594
587
transport = self.get_transport('quack')
595
588
client = FakeClient(transport.base)
596
589
client.add_expected_call(
597
b'BzrDir.has_workingtree', (b'quack/',),
598
b'success', (b'yes',)),
599
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
601
self.assertTrue(a_controldir.has_workingtree())
590
'BzrDir.has_workingtree', ('quack/',),
591
'success', ('yes',)),
592
a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
594
self.assertTrue(a_bzrdir.has_workingtree())
602
595
self.assertFinished(client)
604
597
def test_no_workingtree(self):
605
598
transport = self.get_transport('quack')
606
599
client = FakeClient(transport.base)
607
600
client.add_expected_call(
608
b'BzrDir.has_workingtree', (b'quack/',),
609
b'success', (b'no',)),
610
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
612
self.assertFalse(a_controldir.has_workingtree())
601
'BzrDir.has_workingtree', ('quack/',),
603
a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
605
self.assertFalse(a_bzrdir.has_workingtree())
613
606
self.assertFinished(client)
639
632
def test_absent(self):
640
633
client, transport = self.make_fake_client_and_transport()
641
634
client.add_expected_call(
642
b'BzrDir.open_2.1', (b'quack/',), b'success', (b'no',))
635
'BzrDir.open_2.1', ('quack/',), 'success', ('no',))
643
636
self.assertRaises(errors.NotBranchError, RemoteBzrDir, transport,
644
RemoteBzrDirFormat(), _client=client,
637
RemoteBzrDirFormat(), _client=client, _force_probe=True)
646
638
self.assertFinished(client)
648
640
def test_present_without_workingtree(self):
649
641
client, transport = self.make_fake_client_and_transport()
650
642
client.add_expected_call(
651
b'BzrDir.open_2.1', (b'quack/',), b'success', (b'yes', b'no'))
643
'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'no'))
652
644
bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
653
_client=client, _force_probe=True)
645
_client=client, _force_probe=True)
654
646
self.assertIsInstance(bd, RemoteBzrDir)
655
647
self.assertFalse(bd.has_workingtree())
656
648
self.assertRaises(errors.NoWorkingTree, bd.open_workingtree)
727
716
transport = transport.clone('quack')
728
717
client = FakeClient(transport.base)
729
718
client.add_expected_call(
730
b'BzrDir.open_branchV3', (b'quack/',),
731
b'success', (b'branch', branch_network_name))
732
client.add_expected_call(
733
b'BzrDir.find_repositoryV3', (b'quack/',),
734
b'success', (b'ok', b'', b'no', b'no', b'no', network_name))
735
client.add_expected_call(
736
b'Branch.get_stacked_on_url', (b'quack/',),
737
b'error', (b'NotStacked',))
719
'BzrDir.open_branchV3', ('quack/',),
720
'success', ('branch', branch_network_name))
721
client.add_expected_call(
722
'BzrDir.find_repositoryV3', ('quack/',),
723
'success', ('ok', '', 'no', 'no', 'no', network_name))
724
client.add_expected_call(
725
'Branch.get_stacked_on_url', ('quack/',),
726
'error', ('NotStacked',))
738
727
bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
740
729
result = bzrdir.open_branch()
741
730
self.assertIsInstance(result, RemoteBranch)
742
self.assertEqual(bzrdir, result.controldir)
731
self.assertEqual(bzrdir, result.bzrdir)
743
732
self.assertFinished(client)
745
734
def test_branch_missing(self):
783
771
network_name = reference_format.network_name()
784
772
branch_network_name = self.get_branch_format().network_name()
785
773
client.add_expected_call(
786
b'BzrDir.open_branchV3', (b'~hello/',),
787
b'success', (b'branch', branch_network_name))
788
client.add_expected_call(
789
b'BzrDir.find_repositoryV3', (b'~hello/',),
790
b'success', (b'ok', b'', b'no', b'no', b'no', network_name))
791
client.add_expected_call(
792
b'Branch.get_stacked_on_url', (b'~hello/',),
793
b'error', (b'NotStacked',))
774
'BzrDir.open_branchV3', ('~hello/',),
775
'success', ('branch', branch_network_name))
776
client.add_expected_call(
777
'BzrDir.find_repositoryV3', ('~hello/',),
778
'success', ('ok', '', 'no', 'no', 'no', network_name))
779
client.add_expected_call(
780
'Branch.get_stacked_on_url', ('~hello/',),
781
'error', ('NotStacked',))
794
782
bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
784
result = bzrdir.open_branch()
797
785
self.assertFinished(client)
799
def check_open_repository(self, rich_root, subtrees,
800
external_lookup=b'no'):
787
def check_open_repository(self, rich_root, subtrees, external_lookup='no'):
801
788
reference_format = self.get_repo_format()
802
789
network_name = reference_format.network_name()
803
790
transport = MemoryTransport()
804
791
transport.mkdir('quack')
805
792
transport = transport.clone('quack')
807
rich_response = b'yes'
794
rich_response = 'yes'
809
rich_response = b'no'
811
subtree_response = b'yes'
798
subtree_response = 'yes'
813
subtree_response = b'no'
800
subtree_response = 'no'
814
801
client = FakeClient(transport.base)
815
802
client.add_success_response(
816
b'ok', b'', rich_response, subtree_response, external_lookup,
803
'ok', '', rich_response, subtree_response, external_lookup,
818
805
bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
820
807
result = bzrdir.open_repository()
821
808
self.assertEqual(
822
[('call', b'BzrDir.find_repositoryV3', (b'quack/',))],
809
[('call', 'BzrDir.find_repositoryV3', ('quack/',))],
824
811
self.assertIsInstance(result, RemoteRepository)
825
self.assertEqual(bzrdir, result.controldir)
812
self.assertEqual(bzrdir, result.bzrdir)
826
813
self.assertEqual(rich_root, result._format.rich_root_data)
827
814
self.assertEqual(subtrees, result._format.supports_tree_reference)
912
897
def test_backwards_compat(self):
913
898
self.setup_smart_server_with_call_log()
914
bzrdir = self.make_controldir('.')
899
bzrdir = self.make_bzrdir('.')
915
900
self.reset_smart_call_log()
916
self.disable_verb(b'BzrDir.create_repository')
917
bzrdir.create_repository()
901
self.disable_verb('BzrDir.create_repository')
902
repo = bzrdir.create_repository()
918
903
create_repo_call_count = len([call for call in self.hpss_calls if
919
call.call.method == b'BzrDir.create_repository'])
904
call.call.method == 'BzrDir.create_repository'])
920
905
self.assertEqual(1, create_repo_call_count)
922
907
def test_current_server(self):
923
908
transport = self.get_transport('.')
924
909
transport = transport.clone('quack')
925
self.make_controldir('quack')
910
self.make_bzrdir('quack')
926
911
client = FakeClient(transport.base)
927
912
reference_bzrdir_format = controldir.format_registry.get('default')()
928
913
reference_format = reference_bzrdir_format.repository_format
929
914
network_name = reference_format.network_name()
930
915
client.add_expected_call(
931
b'BzrDir.create_repository', (b'quack/',
932
b'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
934
b'success', (b'ok', b'yes', b'yes', b'yes', network_name))
935
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
937
repo = a_controldir.create_repository()
916
'BzrDir.create_repository', ('quack/',
917
'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
919
'success', ('ok', 'yes', 'yes', 'yes', network_name))
920
a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
922
repo = a_bzrdir.create_repository()
938
923
# We should have got a remote repository
939
924
self.assertIsInstance(repo, remote.RemoteRepository)
940
925
# its format should have the settings from the response
954
939
server_url = 'bzr://example.com/'
955
940
self.permit_url(server_url)
956
941
client = FakeClient(server_url)
957
client.add_unknown_method_response(b'BzrDir.find_repositoryV3')
958
client.add_unknown_method_response(b'BzrDir.find_repositoryV2')
959
client.add_success_response(b'ok', b'', b'no', b'no')
942
client.add_unknown_method_response('BzrDir.find_repositoryV3')
943
client.add_unknown_method_response('BzrDir.find_repositoryV2')
944
client.add_success_response('ok', '', 'no', 'no')
960
945
# A real repository instance will be created to determine the network
962
947
client.add_success_response_with_body(
963
b"Bazaar-NG meta directory, format 1\n", b'ok')
964
client.add_success_response(b'stat', b'0', b'65535')
948
"Bazaar-NG meta directory, format 1\n", 'ok')
949
client.add_success_response('stat', '0', '65535')
965
950
client.add_success_response_with_body(
966
reference_format.get_format_string(), b'ok')
951
reference_format.get_format_string(), 'ok')
967
952
# PackRepository wants to do a stat
968
client.add_success_response(b'stat', b'0', b'65535')
953
client.add_success_response('stat', '0', '65535')
969
954
remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
971
956
bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
973
958
repo = bzrdir.open_repository()
974
959
self.assertEqual(
975
[('call', b'BzrDir.find_repositoryV3', (b'quack/',)),
976
('call', b'BzrDir.find_repositoryV2', (b'quack/',)),
977
('call', b'BzrDir.find_repository', (b'quack/',)),
978
('call_expecting_body', b'get', (b'/quack/.bzr/branch-format',)),
979
('call', b'stat', (b'/quack/.bzr',)),
980
('call_expecting_body', b'get', (b'/quack/.bzr/repository/format',)),
981
('call', b'stat', (b'/quack/.bzr/repository',)),
960
[('call', 'BzrDir.find_repositoryV3', ('quack/',)),
961
('call', 'BzrDir.find_repositoryV2', ('quack/',)),
962
('call', 'BzrDir.find_repository', ('quack/',)),
963
('call_expecting_body', 'get', ('/quack/.bzr/branch-format',)),
964
('call', 'stat', ('/quack/.bzr',)),
965
('call_expecting_body', 'get', ('/quack/.bzr/repository/format',)),
966
('call', 'stat', ('/quack/.bzr/repository',)),
984
969
self.assertEqual(network_name, repo._format.network_name())
990
975
server_url = 'bzr://example.com/'
991
976
self.permit_url(server_url)
992
977
client = FakeClient(server_url)
993
client.add_unknown_method_response(b'BzrDir.find_repositoryV3')
994
client.add_success_response(b'ok', b'', b'no', b'no', b'no')
978
client.add_unknown_method_response('BzrDir.find_repositoryV3')
979
client.add_success_response('ok', '', 'no', 'no', 'no')
995
980
# A real repository instance will be created to determine the network
997
982
client.add_success_response_with_body(
998
b"Bazaar-NG meta directory, format 1\n", b'ok')
999
client.add_success_response(b'stat', b'0', b'65535')
983
"Bazaar-NG meta directory, format 1\n", 'ok')
984
client.add_success_response('stat', '0', '65535')
1000
985
client.add_success_response_with_body(
1001
reference_format.get_format_string(), b'ok')
986
reference_format.get_format_string(), 'ok')
1002
987
# PackRepository wants to do a stat
1003
client.add_success_response(b'stat', b'0', b'65535')
988
client.add_success_response('stat', '0', '65535')
1004
989
remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
1006
991
bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
1008
993
repo = bzrdir.open_repository()
1009
994
self.assertEqual(
1010
[('call', b'BzrDir.find_repositoryV3', (b'quack/',)),
1011
('call', b'BzrDir.find_repositoryV2', (b'quack/',)),
1012
('call_expecting_body', b'get', (b'/quack/.bzr/branch-format',)),
1013
('call', b'stat', (b'/quack/.bzr',)),
1014
('call_expecting_body', b'get',
1015
(b'/quack/.bzr/repository/format',)),
1016
('call', b'stat', (b'/quack/.bzr/repository',)),
995
[('call', 'BzrDir.find_repositoryV3', ('quack/',)),
996
('call', 'BzrDir.find_repositoryV2', ('quack/',)),
997
('call_expecting_body', 'get', ('/quack/.bzr/branch-format',)),
998
('call', 'stat', ('/quack/.bzr',)),
999
('call_expecting_body', 'get', ('/quack/.bzr/repository/format',)),
1000
('call', 'stat', ('/quack/.bzr/repository',)),
1019
1003
self.assertEqual(network_name, repo._format.network_name())
1045
1028
transport = self.get_transport()
1046
1029
client = FakeClient(transport.base)
1047
1030
client.add_expected_call(
1048
b'BzrDirFormat.initialize_ex_1.16',
1049
(default_format_name, b'path', b'False', b'False', b'False', b'',
1050
b'', b'', b'', b'False'),
1052
(b'.', b'no', b'no', b'yes', b'repo fmt', b'repo bzrdir fmt',
1053
b'bzrdir fmt', b'False', b'', b'', b'repo lock token'))
1031
'BzrDirFormat.initialize_ex_1.16',
1032
(default_format_name, 'path', 'False', 'False', 'False', '',
1033
'', '', '', 'False'),
1035
('.', 'no', 'no', 'yes', 'repo fmt', 'repo bzrdir fmt',
1036
'bzrdir fmt', 'False', '', '', 'repo lock token'))
1054
1037
# XXX: It would be better to call fmt.initialize_on_transport_ex, but
1055
1038
# it's currently hard to test that without supplying a real remote
1056
1039
# transport connected to a real server.
1057
fmt._initialize_on_transport_ex_rpc(
1058
client, b'path', transport, False, False, False, None, None, None,
1040
result = fmt._initialize_on_transport_ex_rpc(client, 'path',
1041
transport, False, False, False, None, None, None, None, False)
1060
1042
self.assertFinished(client)
1062
1044
def test_error(self):
1068
1050
transport = self.get_transport()
1069
1051
client = FakeClient(transport.base)
1070
1052
client.add_expected_call(
1071
b'BzrDirFormat.initialize_ex_1.16',
1072
(default_format_name, b'path', b'False', b'False', b'False', b'',
1073
b'', b'', b'', b'False'),
1075
(b'PermissionDenied', b'path', b'extra info'))
1053
'BzrDirFormat.initialize_ex_1.16',
1054
(default_format_name, 'path', 'False', 'False', 'False', '',
1055
'', '', '', 'False'),
1057
('PermissionDenied', 'path', 'extra info'))
1076
1058
# XXX: It would be better to call fmt.initialize_on_transport_ex, but
1077
1059
# it's currently hard to test that without supplying a real remote
1078
1060
# transport connected to a real server.
1079
err = self.assertRaises(
1080
errors.PermissionDenied,
1081
fmt._initialize_on_transport_ex_rpc, client, b'path', transport,
1061
err = self.assertRaises(errors.PermissionDenied,
1062
fmt._initialize_on_transport_ex_rpc, client, 'path', transport,
1082
1063
False, False, False, None, None, None, None, False)
1083
1064
self.assertEqual('path', err.path)
1084
1065
self.assertEqual(': extra info', err.extra)
1315
1296
self.setup_smart_server_with_call_log()
1316
1297
branch = self.make_branch('.')
1317
1298
self.reset_smart_call_log()
1318
verb = b'Branch.get_tags_bytes'
1299
verb = 'Branch.get_tags_bytes'
1319
1300
self.disable_verb(verb)
1320
1301
branch.tags.get_tag_dict()
1321
1302
call_count = len([call for call in self.hpss_calls if
1322
call.call.method == verb])
1303
call.call.method == verb])
1323
1304
self.assertEqual(1, call_count)
1325
1306
def test_trivial(self):
1326
1307
transport = MemoryTransport()
1327
1308
client = FakeClient(transport.base)
1328
1309
client.add_expected_call(
1329
b'Branch.get_stacked_on_url', (b'quack/',),
1330
b'error', (b'NotStacked',))
1310
'Branch.get_stacked_on_url', ('quack/',),
1311
'error', ('NotStacked',))
1331
1312
client.add_expected_call(
1332
b'Branch.get_tags_bytes', (b'quack/',),
1313
'Branch.get_tags_bytes', ('quack/',),
1334
1315
transport.mkdir('quack')
1335
1316
transport = transport.clone('quack')
1336
1317
branch = self.make_remote_branch(transport, client)
1345
1326
transport = MemoryTransport()
1346
1327
client = FakeClient(transport.base)
1347
1328
client.add_expected_call(
1348
b'Branch.get_stacked_on_url', (b'quack/',),
1349
b'error', (b'NotStacked',))
1329
'Branch.get_stacked_on_url', ('quack/',),
1330
'error', ('NotStacked',))
1350
1331
client.add_expected_call(
1351
b'Branch.set_tags_bytes', (b'quack/',
1352
b'branch token', b'repo token'),
1332
'Branch.set_tags_bytes', ('quack/', 'branch token', 'repo token'),
1354
1334
transport.mkdir('quack')
1355
1335
transport = transport.clone('quack')
1356
1336
branch = self.make_remote_branch(transport, client)
1357
1337
self.lock_remote_branch(branch)
1358
branch._set_tags_bytes(b'tags bytes')
1338
branch._set_tags_bytes('tags bytes')
1359
1339
self.assertFinished(client)
1360
self.assertEqual(b'tags bytes', client._calls[-1][-1])
1340
self.assertEqual('tags bytes', client._calls[-1][-1])
1362
1342
def test_backwards_compatible(self):
1363
1343
transport = MemoryTransport()
1364
1344
client = FakeClient(transport.base)
1365
1345
client.add_expected_call(
1366
b'Branch.get_stacked_on_url', (b'quack/',),
1367
b'error', (b'NotStacked',))
1346
'Branch.get_stacked_on_url', ('quack/',),
1347
'error', ('NotStacked',))
1368
1348
client.add_expected_call(
1369
b'Branch.set_tags_bytes', (b'quack/',
1370
b'branch token', b'repo token'),
1371
b'unknown', (b'Branch.set_tags_bytes',))
1349
'Branch.set_tags_bytes', ('quack/', 'branch token', 'repo token'),
1350
'unknown', ('Branch.set_tags_bytes',))
1372
1351
transport.mkdir('quack')
1373
1352
transport = transport.clone('quack')
1374
1353
branch = self.make_remote_branch(transport, client)
1375
1354
self.lock_remote_branch(branch)
1377
1355
class StubRealBranch(object):
1378
1356
def __init__(self):
1379
1357
self.calls = []
1381
1358
def _set_tags_bytes(self, bytes):
1382
1359
self.calls.append(('set_tags_bytes', bytes))
1383
1360
real_branch = StubRealBranch()
1384
1361
branch._real_branch = real_branch
1385
branch._set_tags_bytes(b'tags bytes')
1362
branch._set_tags_bytes('tags bytes')
1386
1363
# Call a second time, to exercise the 'remote version already inferred'
1388
branch._set_tags_bytes(b'tags bytes')
1365
branch._set_tags_bytes('tags bytes')
1389
1366
self.assertFinished(client)
1390
1367
self.assertEqual(
1391
[('set_tags_bytes', b'tags bytes')] * 2, real_branch.calls)
1368
[('set_tags_bytes', 'tags bytes')] * 2, real_branch.calls)
1394
1371
class TestBranchHeadsToFetch(RemoteBranchTestCase):
1397
1374
transport = MemoryTransport()
1398
1375
client = FakeClient(transport.base)
1399
1376
client.add_expected_call(
1400
b'Branch.get_stacked_on_url', (b'quack/',),
1401
b'error', (b'NotStacked',))
1402
client.add_expected_call(
1403
b'Branch.last_revision_info', (b'quack/',),
1404
b'success', (b'ok', b'1', b'rev-tip'))
1405
client.add_expected_call(
1406
b'Branch.get_config_file', (b'quack/',),
1407
b'success', (b'ok',), b'')
1377
'Branch.get_stacked_on_url', ('quack/',),
1378
'error', ('NotStacked',))
1379
client.add_expected_call(
1380
'Branch.last_revision_info', ('quack/',),
1381
'success', ('ok', '1', 'rev-tip'))
1382
client.add_expected_call(
1383
'Branch.get_config_file', ('quack/',),
1384
'success', ('ok',), '')
1408
1385
transport.mkdir('quack')
1409
1386
transport = transport.clone('quack')
1410
1387
branch = self.make_remote_branch(transport, client)
1411
1388
result = branch.heads_to_fetch()
1412
1389
self.assertFinished(client)
1413
self.assertEqual(({b'rev-tip'}, set()), result)
1390
self.assertEqual((set(['rev-tip']), set()), result)
1415
1392
def test_uses_last_revision_info_and_tags_when_set(self):
1416
1393
transport = MemoryTransport()
1417
1394
client = FakeClient(transport.base)
1418
1395
client.add_expected_call(
1419
b'Branch.get_stacked_on_url', (b'quack/',),
1420
b'error', (b'NotStacked',))
1421
client.add_expected_call(
1422
b'Branch.last_revision_info', (b'quack/',),
1423
b'success', (b'ok', b'1', b'rev-tip'))
1424
client.add_expected_call(
1425
b'Branch.get_config_file', (b'quack/',),
1426
b'success', (b'ok',), b'branch.fetch_tags = True')
1396
'Branch.get_stacked_on_url', ('quack/',),
1397
'error', ('NotStacked',))
1398
client.add_expected_call(
1399
'Branch.last_revision_info', ('quack/',),
1400
'success', ('ok', '1', 'rev-tip'))
1401
client.add_expected_call(
1402
'Branch.get_config_file', ('quack/',),
1403
'success', ('ok',), 'branch.fetch_tags = True')
1427
1404
# XXX: this will break if the default format's serialization of tags
1428
1405
# changes, or if the RPC for fetching tags changes from get_tags_bytes.
1429
1406
client.add_expected_call(
1430
b'Branch.get_tags_bytes', (b'quack/',),
1431
b'success', (b'd5:tag-17:rev-foo5:tag-27:rev-bare',))
1407
'Branch.get_tags_bytes', ('quack/',),
1408
'success', ('d5:tag-17:rev-foo5:tag-27:rev-bare',))
1432
1409
transport.mkdir('quack')
1433
1410
transport = transport.clone('quack')
1434
1411
branch = self.make_remote_branch(transport, client)
1435
1412
result = branch.heads_to_fetch()
1436
1413
self.assertFinished(client)
1437
1414
self.assertEqual(
1438
({b'rev-tip'}, {b'rev-foo', b'rev-bar'}), result)
1415
(set(['rev-tip']), set(['rev-foo', 'rev-bar'])), result)
1440
1417
def test_uses_rpc_for_formats_with_non_default_heads_to_fetch(self):
1441
1418
transport = MemoryTransport()
1442
1419
client = FakeClient(transport.base)
1443
1420
client.add_expected_call(
1444
b'Branch.get_stacked_on_url', (b'quack/',),
1445
b'error', (b'NotStacked',))
1421
'Branch.get_stacked_on_url', ('quack/',),
1422
'error', ('NotStacked',))
1446
1423
client.add_expected_call(
1447
b'Branch.heads_to_fetch', (b'quack/',),
1448
b'success', ([b'tip'], [b'tagged-1', b'tagged-2']))
1424
'Branch.heads_to_fetch', ('quack/',),
1425
'success', (['tip'], ['tagged-1', 'tagged-2']))
1449
1426
transport.mkdir('quack')
1450
1427
transport = transport.clone('quack')
1451
1428
branch = self.make_remote_branch(transport, client)
1452
1429
branch._format._use_default_local_heads_to_fetch = lambda: False
1453
1430
result = branch.heads_to_fetch()
1454
1431
self.assertFinished(client)
1455
self.assertEqual(({b'tip'}, {b'tagged-1', b'tagged-2'}), result)
1432
self.assertEqual((set(['tip']), set(['tagged-1', 'tagged-2'])), result)
1457
1434
def make_branch_with_tags(self):
1458
1435
self.setup_smart_server_with_call_log()
1459
1436
# Make a branch with a single revision.
1460
1437
builder = self.make_branch_builder('foo')
1461
1438
builder.start_series()
1462
builder.build_snapshot(None, [
1463
('add', ('', b'root-id', 'directory', ''))],
1439
builder.build_snapshot('tip', None, [
1440
('add', ('', 'root-id', 'directory', ''))])
1465
1441
builder.finish_series()
1466
1442
branch = builder.get_branch()
1467
1443
# Add two tags to that branch
1468
branch.tags.set_tag('tag-1', b'rev-1')
1469
branch.tags.set_tag('tag-2', b'rev-2')
1444
branch.tags.set_tag('tag-1', 'rev-1')
1445
branch.tags.set_tag('tag-2', 'rev-2')
1472
1448
def test_backwards_compatible(self):
1545
1521
# doesn't just open in - this test probably needs to be rewritten using
1546
1522
# a spawn()ed server.
1547
1523
stacked_branch = self.make_branch('stacked', format='1.9')
1548
self.make_branch('base', format='1.9')
1524
memory_branch = self.make_branch('base', format='1.9')
1549
1525
vfs_url = self.get_vfs_only_url('base')
1550
1526
stacked_branch.set_stacked_on_url(vfs_url)
1551
transport = stacked_branch.controldir.root_transport
1527
transport = stacked_branch.bzrdir.root_transport
1552
1528
client = FakeClient(transport.base)
1553
1529
client.add_expected_call(
1554
b'Branch.get_stacked_on_url', (b'stacked/',),
1555
b'success', (b'ok', vfs_url.encode('utf-8')))
1530
'Branch.get_stacked_on_url', ('stacked/',),
1531
'success', ('ok', vfs_url))
1556
1532
# XXX: Multiple calls are bad, this second call documents what is
1558
1534
client.add_expected_call(
1559
b'Branch.get_stacked_on_url', (b'stacked/',),
1560
b'success', (b'ok', vfs_url.encode('utf-8')))
1535
'Branch.get_stacked_on_url', ('stacked/',),
1536
'success', ('ok', vfs_url))
1561
1537
bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1563
1539
repo_fmt = remote.RemoteRepositoryFormat()
1564
1540
repo_fmt._custom_format = stacked_branch.repository._format
1565
1541
branch = RemoteBranch(bzrdir, RemoteRepository(bzrdir, repo_fmt),
1567
1543
result = branch.get_stacked_on_url()
1568
1544
self.assertEqual(vfs_url, result)
1570
1546
def test_backwards_compatible(self):
1571
1547
# like with bzr1.6 with no Branch.get_stacked_on_url rpc
1572
self.make_branch('base', format='1.6')
1548
base_branch = self.make_branch('base', format='1.6')
1573
1549
stacked_branch = self.make_branch('stacked', format='1.6')
1574
1550
stacked_branch.set_stacked_on_url('../base')
1575
1551
client = FakeClient(self.get_url())
1576
1552
branch_network_name = self.get_branch_format().network_name()
1577
1553
client.add_expected_call(
1578
b'BzrDir.open_branchV3', (b'stacked/',),
1579
b'success', (b'branch', branch_network_name))
1554
'BzrDir.open_branchV3', ('stacked/',),
1555
'success', ('branch', branch_network_name))
1580
1556
client.add_expected_call(
1581
b'BzrDir.find_repositoryV3', (b'stacked/',),
1582
b'success', (b'ok', b'', b'no', b'no', b'yes',
1583
stacked_branch.repository._format.network_name()))
1557
'BzrDir.find_repositoryV3', ('stacked/',),
1558
'success', ('ok', '', 'no', 'no', 'yes',
1559
stacked_branch.repository._format.network_name()))
1584
1560
# called twice, once from constructor and then again by us
1585
1561
client.add_expected_call(
1586
b'Branch.get_stacked_on_url', (b'stacked/',),
1587
b'unknown', (b'Branch.get_stacked_on_url',))
1562
'Branch.get_stacked_on_url', ('stacked/',),
1563
'unknown', ('Branch.get_stacked_on_url',))
1588
1564
client.add_expected_call(
1589
b'Branch.get_stacked_on_url', (b'stacked/',),
1590
b'unknown', (b'Branch.get_stacked_on_url',))
1565
'Branch.get_stacked_on_url', ('stacked/',),
1566
'unknown', ('Branch.get_stacked_on_url',))
1591
1567
# this will also do vfs access, but that goes direct to the transport
1592
1568
# and isn't seen by the FakeClient.
1593
1569
bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1594
RemoteBzrDirFormat(), _client=client)
1570
RemoteBzrDirFormat(), _client=client)
1595
1571
branch = bzrdir.open_branch()
1596
1572
result = branch.get_stacked_on_url()
1597
1573
self.assertEqual('../base', result)
1611
1587
client = FakeClient(self.get_url())
1612
1588
branch_network_name = self.get_branch_format().network_name()
1613
1589
client.add_expected_call(
1614
b'BzrDir.open_branchV3', (b'stacked/',),
1615
b'success', (b'branch', branch_network_name))
1590
'BzrDir.open_branchV3', ('stacked/',),
1591
'success', ('branch', branch_network_name))
1616
1592
client.add_expected_call(
1617
b'BzrDir.find_repositoryV3', (b'stacked/',),
1618
b'success', (b'ok', b'', b'yes', b'no', b'yes', network_name))
1593
'BzrDir.find_repositoryV3', ('stacked/',),
1594
'success', ('ok', '', 'yes', 'no', 'yes', network_name))
1619
1595
# called twice, once from constructor and then again by us
1620
1596
client.add_expected_call(
1621
b'Branch.get_stacked_on_url', (b'stacked/',),
1622
b'success', (b'ok', b'../base'))
1597
'Branch.get_stacked_on_url', ('stacked/',),
1598
'success', ('ok', '../base'))
1623
1599
client.add_expected_call(
1624
b'Branch.get_stacked_on_url', (b'stacked/',),
1625
b'success', (b'ok', b'../base'))
1600
'Branch.get_stacked_on_url', ('stacked/',),
1601
'success', ('ok', '../base'))
1626
1602
bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1627
RemoteBzrDirFormat(), _client=client)
1603
RemoteBzrDirFormat(), _client=client)
1628
1604
branch = bzrdir.open_branch()
1629
1605
result = branch.get_stacked_on_url()
1630
1606
self.assertEqual('../base', result)
1647
1623
client = FakeClient(transport.base)
1648
1624
client.add_expected_call(
1649
b'Branch.get_stacked_on_url', (b'branch/',),
1650
b'error', (b'NotStacked',))
1651
client.add_expected_call(
1652
b'Branch.lock_write', (b'branch/', b'', b''),
1653
b'success', (b'ok', b'branch token', b'repo token'))
1654
client.add_expected_call(
1655
b'Branch.last_revision_info',
1657
b'success', (b'ok', b'0', b'null:'))
1658
client.add_expected_call(
1659
b'Branch.set_last_revision', (b'branch/',
1660
b'branch token', b'repo token', b'null:',),
1661
b'success', (b'ok',))
1662
client.add_expected_call(
1663
b'Branch.unlock', (b'branch/', b'branch token', b'repo token'),
1664
b'success', (b'ok',))
1625
'Branch.get_stacked_on_url', ('branch/',),
1626
'error', ('NotStacked',))
1627
client.add_expected_call(
1628
'Branch.lock_write', ('branch/', '', ''),
1629
'success', ('ok', 'branch token', 'repo token'))
1630
client.add_expected_call(
1631
'Branch.last_revision_info',
1633
'success', ('ok', '0', 'null:'))
1634
client.add_expected_call(
1635
'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'null:',),
1637
client.add_expected_call(
1638
'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1665
1640
branch = self.make_remote_branch(transport, client)
1666
1641
branch.lock_write()
1667
1642
result = branch._set_last_revision(NULL_REVISION)
1679
1654
client = FakeClient(transport.base)
1680
1655
client.add_expected_call(
1681
b'Branch.get_stacked_on_url', (b'branch/',),
1682
b'error', (b'NotStacked',))
1683
client.add_expected_call(
1684
b'Branch.lock_write', (b'branch/', b'', b''),
1685
b'success', (b'ok', b'branch token', b'repo token'))
1686
client.add_expected_call(
1687
b'Branch.last_revision_info',
1689
b'success', (b'ok', b'0', b'null:'))
1690
lines = [b'rev-id2']
1691
encoded_body = bz2.compress(b'\n'.join(lines))
1692
client.add_success_response_with_body(encoded_body, b'ok')
1693
client.add_expected_call(
1694
b'Branch.set_last_revision', (b'branch/',
1695
b'branch token', b'repo token', b'rev-id2',),
1696
b'success', (b'ok',))
1697
client.add_expected_call(
1698
b'Branch.unlock', (b'branch/', b'branch token', b'repo token'),
1699
b'success', (b'ok',))
1656
'Branch.get_stacked_on_url', ('branch/',),
1657
'error', ('NotStacked',))
1658
client.add_expected_call(
1659
'Branch.lock_write', ('branch/', '', ''),
1660
'success', ('ok', 'branch token', 'repo token'))
1661
client.add_expected_call(
1662
'Branch.last_revision_info',
1664
'success', ('ok', '0', 'null:'))
1666
encoded_body = bz2.compress('\n'.join(lines))
1667
client.add_success_response_with_body(encoded_body, 'ok')
1668
client.add_expected_call(
1669
'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'rev-id2',),
1671
client.add_expected_call(
1672
'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1700
1674
branch = self.make_remote_branch(transport, client)
1701
1675
# Lock the branch, reset the record of remote calls.
1702
1676
branch.lock_write()
1703
result = branch._set_last_revision(b'rev-id2')
1677
result = branch._set_last_revision('rev-id2')
1704
1678
branch.unlock()
1705
1679
self.assertEqual(None, result)
1706
1680
self.assertFinished(client)
1712
1686
# A response of 'NoSuchRevision' is translated into an exception.
1713
1687
client = FakeClient(transport.base)
1714
1688
client.add_expected_call(
1715
b'Branch.get_stacked_on_url', (b'branch/',),
1716
b'error', (b'NotStacked',))
1717
client.add_expected_call(
1718
b'Branch.lock_write', (b'branch/', b'', b''),
1719
b'success', (b'ok', b'branch token', b'repo token'))
1720
client.add_expected_call(
1721
b'Branch.last_revision_info',
1723
b'success', (b'ok', b'0', b'null:'))
1689
'Branch.get_stacked_on_url', ('branch/',),
1690
'error', ('NotStacked',))
1691
client.add_expected_call(
1692
'Branch.lock_write', ('branch/', '', ''),
1693
'success', ('ok', 'branch token', 'repo token'))
1694
client.add_expected_call(
1695
'Branch.last_revision_info',
1697
'success', ('ok', '0', 'null:'))
1724
1698
# get_graph calls to construct the revision history, for the set_rh
1727
encoded_body = bz2.compress(b'\n'.join(lines))
1728
client.add_success_response_with_body(encoded_body, b'ok')
1729
client.add_expected_call(
1730
b'Branch.set_last_revision', (b'branch/',
1731
b'branch token', b'repo token', b'rev-id',),
1732
b'error', (b'NoSuchRevision', b'rev-id'))
1733
client.add_expected_call(
1734
b'Branch.unlock', (b'branch/', b'branch token', b'repo token'),
1735
b'success', (b'ok',))
1701
encoded_body = bz2.compress('\n'.join(lines))
1702
client.add_success_response_with_body(encoded_body, 'ok')
1703
client.add_expected_call(
1704
'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'rev-id',),
1705
'error', ('NoSuchRevision', 'rev-id'))
1706
client.add_expected_call(
1707
'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1737
1710
branch = self.make_remote_branch(transport, client)
1738
1711
branch.lock_write()
1739
1712
self.assertRaises(
1740
errors.NoSuchRevision, branch._set_last_revision, b'rev-id')
1713
errors.NoSuchRevision, branch._set_last_revision, 'rev-id')
1741
1714
branch.unlock()
1742
1715
self.assertFinished(client)
1752
1725
rejection_msg_unicode = u'rejection message\N{INTERROBANG}'
1753
1726
rejection_msg_utf8 = rejection_msg_unicode.encode('utf8')
1754
1727
client.add_expected_call(
1755
b'Branch.get_stacked_on_url', (b'branch/',),
1756
b'error', (b'NotStacked',))
1757
client.add_expected_call(
1758
b'Branch.lock_write', (b'branch/', b'', b''),
1759
b'success', (b'ok', b'branch token', b'repo token'))
1760
client.add_expected_call(
1761
b'Branch.last_revision_info',
1763
b'success', (b'ok', b'0', b'null:'))
1765
encoded_body = bz2.compress(b'\n'.join(lines))
1766
client.add_success_response_with_body(encoded_body, b'ok')
1767
client.add_expected_call(
1768
b'Branch.set_last_revision', (b'branch/',
1769
b'branch token', b'repo token', b'rev-id',),
1770
b'error', (b'TipChangeRejected', rejection_msg_utf8))
1771
client.add_expected_call(
1772
b'Branch.unlock', (b'branch/', b'branch token', b'repo token'),
1773
b'success', (b'ok',))
1728
'Branch.get_stacked_on_url', ('branch/',),
1729
'error', ('NotStacked',))
1730
client.add_expected_call(
1731
'Branch.lock_write', ('branch/', '', ''),
1732
'success', ('ok', 'branch token', 'repo token'))
1733
client.add_expected_call(
1734
'Branch.last_revision_info',
1736
'success', ('ok', '0', 'null:'))
1738
encoded_body = bz2.compress('\n'.join(lines))
1739
client.add_success_response_with_body(encoded_body, 'ok')
1740
client.add_expected_call(
1741
'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'rev-id',),
1742
'error', ('TipChangeRejected', rejection_msg_utf8))
1743
client.add_expected_call(
1744
'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1774
1746
branch = self.make_remote_branch(transport, client)
1775
1747
branch.lock_write()
1776
1748
# The 'TipChangeRejected' error response triggered by calling
1777
1749
# set_last_revision_info causes a TipChangeRejected exception.
1778
1750
err = self.assertRaises(
1779
1751
errors.TipChangeRejected,
1780
branch._set_last_revision, b'rev-id')
1752
branch._set_last_revision, 'rev-id')
1781
1753
# The UTF-8 message from the response has been decoded into a unicode
1783
self.assertIsInstance(err.msg, str)
1755
self.assertIsInstance(err.msg, unicode)
1784
1756
self.assertEqual(rejection_msg_unicode, err.msg)
1785
1757
branch.unlock()
1786
1758
self.assertFinished(client)
1789
1761
class TestBranchSetLastRevisionInfo(RemoteBranchTestCase):
1791
1763
def test_set_last_revision_info(self):
1792
# set_last_revision_info(num, b'rev-id') is translated to calling
1764
# set_last_revision_info(num, 'rev-id') is translated to calling
1793
1765
# Branch.set_last_revision_info(num, 'rev-id') on the wire.
1794
1766
transport = MemoryTransport()
1795
1767
transport.mkdir('branch')
1796
1768
transport = transport.clone('branch')
1797
1769
client = FakeClient(transport.base)
1798
1770
# get_stacked_on_url
1799
client.add_error_response(b'NotStacked')
1771
client.add_error_response('NotStacked')
1801
client.add_success_response(b'ok', b'branch token', b'repo token')
1773
client.add_success_response('ok', 'branch token', 'repo token')
1802
1774
# query the current revision
1803
client.add_success_response(b'ok', b'0', b'null:')
1775
client.add_success_response('ok', '0', 'null:')
1804
1776
# set_last_revision
1805
client.add_success_response(b'ok')
1777
client.add_success_response('ok')
1807
client.add_success_response(b'ok')
1779
client.add_success_response('ok')
1809
1781
branch = self.make_remote_branch(transport, client)
1810
1782
# Lock the branch, reset the record of remote calls.
1811
1783
branch.lock_write()
1812
1784
client._calls = []
1813
result = branch.set_last_revision_info(1234, b'a-revision-id')
1785
result = branch.set_last_revision_info(1234, 'a-revision-id')
1814
1786
self.assertEqual(
1815
[('call', b'Branch.last_revision_info', (b'branch/',)),
1816
('call', b'Branch.set_last_revision_info',
1817
(b'branch/', b'branch token', b'repo token',
1818
b'1234', b'a-revision-id'))],
1787
[('call', 'Branch.last_revision_info', ('branch/',)),
1788
('call', 'Branch.set_last_revision_info',
1789
('branch/', 'branch token', 'repo token',
1790
'1234', 'a-revision-id'))],
1820
1792
self.assertEqual(None, result)
1860
1832
transport = transport.clone('branch')
1861
1833
client = FakeClient(transport.base)
1862
1834
client.add_expected_call(
1863
b'Branch.get_stacked_on_url', (b'branch/',),
1864
b'error', (b'NotStacked',))
1865
client.add_expected_call(
1866
b'Branch.last_revision_info',
1868
b'success', (b'ok', b'0', b'null:'))
1869
client.add_expected_call(
1870
b'Branch.set_last_revision_info',
1871
(b'branch/', b'branch token', b'repo token', b'1234', b'a-revision-id',),
1872
b'unknown', b'Branch.set_last_revision_info')
1835
'Branch.get_stacked_on_url', ('branch/',),
1836
'error', ('NotStacked',))
1837
client.add_expected_call(
1838
'Branch.last_revision_info',
1840
'success', ('ok', '0', 'null:'))
1841
client.add_expected_call(
1842
'Branch.set_last_revision_info',
1843
('branch/', 'branch token', 'repo token', '1234', 'a-revision-id',),
1844
'unknown', 'Branch.set_last_revision_info')
1874
1846
branch = self.make_remote_branch(transport, client)
1876
1847
class StubRealBranch(object):
1877
1848
def __init__(self):
1878
1849
self.calls = []
1880
1850
def set_last_revision_info(self, revno, revision_id):
1881
1851
self.calls.append(
1882
1852
('set_last_revision_info', revno, revision_id))
1884
1853
def _clear_cached_state(self):
1886
1855
real_branch = StubRealBranch()
1959
1928
# in an empty branch we decode the response properly
1960
1929
client = FakeClient()
1961
1930
client.add_expected_call(
1962
b'Branch.get_stacked_on_url', (b'memory:///',),
1963
b'error', (b'NotStacked',),)
1964
client.add_success_response_with_body(b'# config file body', b'ok')
1931
'Branch.get_stacked_on_url', ('memory:///',),
1932
'error', ('NotStacked',),)
1933
client.add_success_response_with_body('# config file body', 'ok')
1965
1934
transport = MemoryTransport()
1966
1935
branch = self.make_remote_branch(transport, client)
1967
1936
config = branch.get_config()
1968
1937
config.has_explicit_nickname()
1969
1938
self.assertEqual(
1970
[('call', b'Branch.get_stacked_on_url', (b'memory:///',)),
1971
('call_expecting_body', b'Branch.get_config_file', (b'memory:///',))],
1939
[('call', 'Branch.get_stacked_on_url', ('memory:///',)),
1940
('call_expecting_body', 'Branch.get_config_file', ('memory:///',))],
1974
1943
def test_get_multi_line_branch_conf(self):
1988
1957
def test_set_option(self):
1989
1958
client = FakeClient()
1990
1959
client.add_expected_call(
1991
b'Branch.get_stacked_on_url', (b'memory:///',),
1992
b'error', (b'NotStacked',),)
1993
client.add_expected_call(
1994
b'Branch.lock_write', (b'memory:///', b'', b''),
1995
b'success', (b'ok', b'branch token', b'repo token'))
1996
client.add_expected_call(
1997
b'Branch.set_config_option', (b'memory:///', b'branch token',
1998
b'repo token', b'foo', b'bar', b''),
2000
client.add_expected_call(
2001
b'Branch.unlock', (b'memory:///', b'branch token', b'repo token'),
2002
b'success', (b'ok',))
1960
'Branch.get_stacked_on_url', ('memory:///',),
1961
'error', ('NotStacked',),)
1962
client.add_expected_call(
1963
'Branch.lock_write', ('memory:///', '', ''),
1964
'success', ('ok', 'branch token', 'repo token'))
1965
client.add_expected_call(
1966
'Branch.set_config_option', ('memory:///', 'branch token',
1967
'repo token', 'foo', 'bar', ''),
1969
client.add_expected_call(
1970
'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
2003
1972
transport = MemoryTransport()
2004
1973
branch = self.make_remote_branch(transport, client)
2005
1974
branch.lock_write()
2011
1980
def test_set_option_with_dict(self):
2012
1981
client = FakeClient()
2013
1982
client.add_expected_call(
2014
b'Branch.get_stacked_on_url', (b'memory:///',),
2015
b'error', (b'NotStacked',),)
2016
client.add_expected_call(
2017
b'Branch.lock_write', (b'memory:///', b'', b''),
2018
b'success', (b'ok', b'branch token', b'repo token'))
2019
encoded_dict_value = b'd5:ascii1:a11:unicode \xe2\x8c\x9a3:\xe2\x80\xbde'
2020
client.add_expected_call(
2021
b'Branch.set_config_option_dict', (b'memory:///', b'branch token',
2022
b'repo token', encoded_dict_value, b'foo', b''),
2024
client.add_expected_call(
2025
b'Branch.unlock', (b'memory:///', b'branch token', b'repo token'),
2026
b'success', (b'ok',))
1983
'Branch.get_stacked_on_url', ('memory:///',),
1984
'error', ('NotStacked',),)
1985
client.add_expected_call(
1986
'Branch.lock_write', ('memory:///', '', ''),
1987
'success', ('ok', 'branch token', 'repo token'))
1988
encoded_dict_value = 'd5:ascii1:a11:unicode \xe2\x8c\x9a3:\xe2\x80\xbde'
1989
client.add_expected_call(
1990
'Branch.set_config_option_dict', ('memory:///', 'branch token',
1991
'repo token', encoded_dict_value, 'foo', ''),
1993
client.add_expected_call(
1994
'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
2027
1996
transport = MemoryTransport()
2028
1997
branch = self.make_remote_branch(transport, client)
2029
1998
branch.lock_write()
2034
2003
branch.unlock()
2035
2004
self.assertFinished(client)
2037
def test_set_option_with_bool(self):
2038
client = FakeClient()
2039
client.add_expected_call(
2040
b'Branch.get_stacked_on_url', (b'memory:///',),
2041
b'error', (b'NotStacked',),)
2042
client.add_expected_call(
2043
b'Branch.lock_write', (b'memory:///', b'', b''),
2044
b'success', (b'ok', b'branch token', b'repo token'))
2045
client.add_expected_call(
2046
b'Branch.set_config_option', (b'memory:///', b'branch token',
2047
b'repo token', b'True', b'foo', b''),
2049
client.add_expected_call(
2050
b'Branch.unlock', (b'memory:///', b'branch token', b'repo token'),
2051
b'success', (b'ok',))
2052
transport = MemoryTransport()
2053
branch = self.make_remote_branch(transport, client)
2055
config = branch._get_config()
2056
config.set_option(True, 'foo')
2058
self.assertFinished(client)
2060
2006
def test_backwards_compat_set_option(self):
2061
2007
self.setup_smart_server_with_call_log()
2062
2008
branch = self.make_branch('.')
2063
verb = b'Branch.set_config_option'
2009
verb = 'Branch.set_config_option'
2064
2010
self.disable_verb(verb)
2065
2011
branch.lock_write()
2066
2012
self.addCleanup(branch.unlock)
2090
2036
# in an empty branch we decode the response properly
2091
2037
client = FakeClient()
2092
2038
client.add_expected_call(
2093
b'Branch.get_stacked_on_url', (b'memory:///',),
2094
b'error', (b'NotStacked',),)
2095
client.add_success_response_with_body(b'# config file body', b'ok')
2039
'Branch.get_stacked_on_url', ('memory:///',),
2040
'error', ('NotStacked',),)
2041
client.add_success_response_with_body('# config file body', 'ok')
2096
2042
transport = MemoryTransport()
2097
2043
branch = self.make_remote_branch(transport, client)
2098
2044
config = branch.get_config_stack()
2099
2045
config.get("email")
2100
2046
config.get("log_format")
2101
2047
self.assertEqual(
2102
[('call', b'Branch.get_stacked_on_url', (b'memory:///',)),
2103
('call_expecting_body', b'Branch.get_config_file', (b'memory:///',))],
2048
[('call', 'Branch.get_stacked_on_url', ('memory:///',)),
2049
('call_expecting_body', 'Branch.get_config_file', ('memory:///',))],
2106
2052
def test_set_branch_conf(self):
2107
2053
client = FakeClient()
2108
2054
client.add_expected_call(
2109
b'Branch.get_stacked_on_url', (b'memory:///',),
2110
b'error', (b'NotStacked',),)
2111
client.add_expected_call(
2112
b'Branch.lock_write', (b'memory:///', b'', b''),
2113
b'success', (b'ok', b'branch token', b'repo token'))
2114
client.add_expected_call(
2115
b'Branch.get_config_file', (b'memory:///', ),
2116
b'success', (b'ok', ), b"# line 1\n")
2117
client.add_expected_call(
2118
b'Branch.get_config_file', (b'memory:///', ),
2119
b'success', (b'ok', ), b"# line 1\n")
2120
client.add_expected_call(
2121
b'Branch.put_config_file', (b'memory:///', b'branch token',
2123
b'success', (b'ok',))
2124
client.add_expected_call(
2125
b'Branch.unlock', (b'memory:///', b'branch token', b'repo token'),
2126
b'success', (b'ok',))
2055
'Branch.get_stacked_on_url', ('memory:///',),
2056
'error', ('NotStacked',),)
2057
client.add_expected_call(
2058
'Branch.lock_write', ('memory:///', '', ''),
2059
'success', ('ok', 'branch token', 'repo token'))
2060
client.add_expected_call(
2061
'Branch.get_config_file', ('memory:///', ),
2062
'success', ('ok', ), "# line 1\n")
2063
client.add_expected_call(
2064
'Branch.get_config_file', ('memory:///', ),
2065
'success', ('ok', ), "# line 1\n")
2066
client.add_expected_call(
2067
'Branch.put_config_file', ('memory:///', 'branch token',
2070
client.add_expected_call(
2071
'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
2127
2073
transport = MemoryTransport()
2128
2074
branch = self.make_remote_branch(transport, client)
2129
2075
branch.lock_write()
2132
2078
branch.unlock()
2133
2079
self.assertFinished(client)
2134
2080
self.assertEqual(
2135
[('call', b'Branch.get_stacked_on_url', (b'memory:///',)),
2136
('call', b'Branch.lock_write', (b'memory:///', b'', b'')),
2137
('call_expecting_body', b'Branch.get_config_file',
2139
('call_expecting_body', b'Branch.get_config_file',
2141
('call_with_body_bytes_expecting_body', b'Branch.put_config_file',
2142
(b'memory:///', b'branch token', b'repo token'),
2143
b'# line 1\nemail = The Dude <lebowski@example.com>\n'),
2144
('call', b'Branch.unlock',
2145
(b'memory:///', b'branch token', b'repo token'))],
2081
[('call', 'Branch.get_stacked_on_url', ('memory:///',)),
2082
('call', 'Branch.lock_write', ('memory:///', '', '')),
2083
('call_expecting_body', 'Branch.get_config_file', ('memory:///',)),
2084
('call_expecting_body', 'Branch.get_config_file', ('memory:///',)),
2085
('call_with_body_bytes_expecting_body', 'Branch.put_config_file',
2086
('memory:///', 'branch token', 'repo token'),
2087
'# line 1\nemail = The Dude <lebowski@example.com>\n'),
2088
('call', 'Branch.unlock', ('memory:///', 'branch token', 'repo token'))],
2170
2113
transport = MemoryTransport()
2171
2114
client = FakeClient(transport.base)
2172
2115
client.add_expected_call(
2173
b'Branch.get_stacked_on_url', (b'quack/',),
2174
b'error', (b'NotStacked',),)
2175
client.add_expected_call(
2176
b'Branch.revision_id_to_revno', (b'quack/', b'null:'),
2177
b'success', (b'ok', b'0',),)
2178
client.add_expected_call(
2179
b'Branch.revision_id_to_revno', (b'quack/', b'unknown'),
2180
b'error', (b'NoSuchRevision', b'unknown',),)
2116
'Branch.get_stacked_on_url', ('quack/',),
2117
'error', ('NotStacked',),)
2118
client.add_expected_call(
2119
'Branch.revision_id_to_revno', ('quack/', 'null:'),
2120
'success', ('ok', '0',),)
2121
client.add_expected_call(
2122
'Branch.revision_id_to_revno', ('quack/', 'unknown'),
2123
'error', ('NoSuchRevision', 'unknown',),)
2181
2124
transport.mkdir('quack')
2182
2125
transport = transport.clone('quack')
2183
2126
branch = self.make_remote_branch(transport, client)
2184
self.assertEqual(0, branch.revision_id_to_revno(b'null:'))
2127
self.assertEqual(0, branch.revision_id_to_revno('null:'))
2185
2128
self.assertRaises(errors.NoSuchRevision,
2186
branch.revision_id_to_revno, b'unknown')
2129
branch.revision_id_to_revno, 'unknown')
2187
2130
self.assertFinished(client)
2189
2132
def test_dotted(self):
2190
2133
transport = MemoryTransport()
2191
2134
client = FakeClient(transport.base)
2192
2135
client.add_expected_call(
2193
b'Branch.get_stacked_on_url', (b'quack/',),
2194
b'error', (b'NotStacked',),)
2195
client.add_expected_call(
2196
b'Branch.revision_id_to_revno', (b'quack/', b'null:'),
2197
b'success', (b'ok', b'0',),)
2198
client.add_expected_call(
2199
b'Branch.revision_id_to_revno', (b'quack/', b'unknown'),
2200
b'error', (b'NoSuchRevision', b'unknown',),)
2136
'Branch.get_stacked_on_url', ('quack/',),
2137
'error', ('NotStacked',),)
2138
client.add_expected_call(
2139
'Branch.revision_id_to_revno', ('quack/', 'null:'),
2140
'success', ('ok', '0',),)
2141
client.add_expected_call(
2142
'Branch.revision_id_to_revno', ('quack/', 'unknown'),
2143
'error', ('NoSuchRevision', 'unknown',),)
2201
2144
transport.mkdir('quack')
2202
2145
transport = transport.clone('quack')
2203
2146
branch = self.make_remote_branch(transport, client)
2204
self.assertEqual((0, ), branch.revision_id_to_dotted_revno(b'null:'))
2147
self.assertEqual((0, ), branch.revision_id_to_dotted_revno('null:'))
2205
2148
self.assertRaises(errors.NoSuchRevision,
2206
branch.revision_id_to_dotted_revno, b'unknown')
2207
self.assertFinished(client)
2209
def test_ghost_revid(self):
2210
transport = MemoryTransport()
2211
client = FakeClient(transport.base)
2212
client.add_expected_call(
2213
b'Branch.get_stacked_on_url', (b'quack/',),
2214
b'error', (b'NotStacked',),)
2215
# Some older versions of bzr/brz didn't explicitly return
2216
# GhostRevisionsHaveNoRevno
2217
client.add_expected_call(
2218
b'Branch.revision_id_to_revno', (b'quack/', b'revid'),
2219
b'error', (b'error', b'GhostRevisionsHaveNoRevno',
2220
b'The reivison {revid} was not found because there was '
2221
b'a ghost at {ghost-revid}'))
2222
client.add_expected_call(
2223
b'Branch.revision_id_to_revno', (b'quack/', b'revid'),
2224
b'error', (b'GhostRevisionsHaveNoRevno', b'revid', b'ghost-revid',))
2225
transport.mkdir('quack')
2226
transport = transport.clone('quack')
2227
branch = self.make_remote_branch(transport, client)
2228
self.assertRaises(errors.GhostRevisionsHaveNoRevno,
2229
branch.revision_id_to_dotted_revno, b'revid')
2230
self.assertRaises(errors.GhostRevisionsHaveNoRevno,
2231
branch.revision_id_to_dotted_revno, b'revid')
2149
branch.revision_id_to_dotted_revno, 'unknown')
2232
2150
self.assertFinished(client)
2234
2152
def test_dotted_no_smart_verb(self):
2235
2153
self.setup_smart_server_with_call_log()
2236
2154
branch = self.make_branch('.')
2237
self.disable_verb(b'Branch.revision_id_to_revno')
2155
self.disable_verb('Branch.revision_id_to_revno')
2238
2156
self.reset_smart_call_log()
2239
2157
self.assertEqual((0, ),
2240
branch.revision_id_to_dotted_revno(b'null:'))
2158
branch.revision_id_to_dotted_revno('null:'))
2241
2159
self.assertLength(8, self.hpss_calls)
2438
2353
transport_path = 'quack'
2439
2354
repo, client = self.setup_fake_client_and_repository(transport_path)
2440
2355
client.add_success_response_with_body(
2441
b'revisions: 2\nsize: 18\n', b'ok')
2356
'revisions: 2\nsize: 18\n', 'ok')
2442
2357
result = repo.gather_stats(None)
2443
2358
self.assertEqual(
2444
[('call_expecting_body', b'Repository.gather_stats',
2445
(b'quack/', b'', b'no'))],
2359
[('call_expecting_body', 'Repository.gather_stats',
2360
('quack/','','no'))],
2447
2362
self.assertEqual({'revisions': 2, 'size': 18}, result)
2449
2364
def test_revid_no_committers(self):
2450
2365
# ('ok',), body without committers
2451
body = (b'firstrev: 123456.300 3600\n'
2452
b'latestrev: 654231.400 0\n'
2366
body = ('firstrev: 123456.300 3600\n'
2367
'latestrev: 654231.400 0\n'
2455
2370
transport_path = 'quick'
2456
2371
revid = u'\xc8'.encode('utf8')
2457
2372
repo, client = self.setup_fake_client_and_repository(transport_path)
2458
client.add_success_response_with_body(body, b'ok')
2373
client.add_success_response_with_body(body, 'ok')
2459
2374
result = repo.gather_stats(revid)
2460
2375
self.assertEqual(
2461
[('call_expecting_body', b'Repository.gather_stats',
2462
(b'quick/', revid, b'no'))],
2376
[('call_expecting_body', 'Repository.gather_stats',
2377
('quick/', revid, 'no'))],
2464
2379
self.assertEqual({'revisions': 2, 'size': 18,
2465
2380
'firstrev': (123456.300, 3600),
2466
'latestrev': (654231.400, 0), },
2381
'latestrev': (654231.400, 0),},
2469
2384
def test_revid_with_committers(self):
2470
2385
# ('ok',), body with committers
2471
body = (b'committers: 128\n'
2472
b'firstrev: 123456.300 3600\n'
2473
b'latestrev: 654231.400 0\n'
2386
body = ('committers: 128\n'
2387
'firstrev: 123456.300 3600\n'
2388
'latestrev: 654231.400 0\n'
2476
2391
transport_path = 'buick'
2477
2392
revid = u'\xc8'.encode('utf8')
2478
2393
repo, client = self.setup_fake_client_and_repository(transport_path)
2479
client.add_success_response_with_body(body, b'ok')
2394
client.add_success_response_with_body(body, 'ok')
2480
2395
result = repo.gather_stats(revid, True)
2481
2396
self.assertEqual(
2482
[('call_expecting_body', b'Repository.gather_stats',
2483
(b'buick/', revid, b'yes'))],
2397
[('call_expecting_body', 'Repository.gather_stats',
2398
('buick/', revid, 'yes'))],
2485
2400
self.assertEqual({'revisions': 2, 'size': 18,
2486
2401
'committers': 128,
2487
2402
'firstrev': (123456.300, 3600),
2488
'latestrev': (654231.400, 0), },
2403
'latestrev': (654231.400, 0),},
2519
2434
def test_reconcile(self):
2520
2435
transport_path = 'hill'
2521
2436
repo, client = self.setup_fake_client_and_repository(transport_path)
2522
body = (b"garbage_inventories: 2\n"
2523
b"inconsistent_parents: 3\n")
2437
body = ("garbage_inventories: 2\n"
2438
"inconsistent_parents: 3\n")
2524
2439
client.add_expected_call(
2525
b'Repository.lock_write', (b'hill/', b''),
2526
b'success', (b'ok', b'a token'))
2527
client.add_success_response_with_body(body, b'ok')
2440
'Repository.lock_write', ('hill/', ''),
2441
'success', ('ok', 'a token'))
2442
client.add_success_response_with_body(body, 'ok')
2528
2443
reconciler = repo.reconcile()
2529
2444
self.assertEqual(
2530
[('call', b'Repository.lock_write', (b'hill/', b'')),
2531
('call_expecting_body', b'Repository.reconcile',
2532
(b'hill/', b'a token'))],
2445
[('call', 'Repository.lock_write', ('hill/', '')),
2446
('call_expecting_body', 'Repository.reconcile',
2447
('hill/', 'a token'))],
2534
2449
self.assertEqual(2, reconciler.garbage_inventories)
2535
2450
self.assertEqual(3, reconciler.inconsistent_parents)
2577
2492
transport_path = 'quack'
2578
2493
repo, client = self.setup_fake_client_and_repository(transport_path)
2579
2494
client.add_expected_call(
2580
b'Repository.lock_write', (b'quack/', b''),
2581
b'success', (b'ok', b'a token'))
2582
client.add_expected_call(
2583
b'Repository.start_write_group', (b'quack/', b'a token'),
2584
b'success', (b'ok', (b'token1', )))
2585
client.add_expected_call(
2586
b'Repository.add_signature_text', (b'quack/', b'a token', b'rev1',
2588
b'success', (b'ok', ), None)
2495
'Repository.lock_write', ('quack/', ''),
2496
'success', ('ok', 'a token'))
2497
client.add_expected_call(
2498
'Repository.start_write_group', ('quack/', 'a token'),
2499
'success', ('ok', ('token1', )))
2500
client.add_expected_call(
2501
'Repository.add_signature_text', ('quack/', 'a token', 'rev1',
2503
'success', ('ok', ), None)
2589
2504
repo.lock_write()
2590
2505
repo.start_write_group()
2592
None, repo.add_signature_text(b"rev1", b"every bloody emperor"))
2507
repo.add_signature_text("rev1", "every bloody emperor"))
2593
2508
self.assertEqual(
2594
2509
('call_with_body_bytes_expecting_body',
2595
b'Repository.add_signature_text',
2596
(b'quack/', b'a token', b'rev1', b'token1'),
2597
b'every bloody emperor'),
2510
'Repository.add_signature_text',
2511
('quack/', 'a token', 'rev1', 'token1'),
2512
'every bloody emperor'),
2598
2513
client._calls[-1])
2635
2549
self.assertEqual({r1: (NULL_REVISION,)}, parents)
2636
2550
self.assertEqual(
2637
2551
[('call_with_body_bytes_expecting_body',
2638
b'Repository.get_parent_map', (b'quack/',
2639
b'include-missing:', r2),
2552
'Repository.get_parent_map', ('quack/', 'include-missing:', r2),
2641
2554
('call_with_body_bytes_expecting_body',
2642
b'Repository.get_parent_map', (b'quack/',
2643
b'include-missing:', r1),
2555
'Repository.get_parent_map', ('quack/', 'include-missing:', r1),
2649
2561
def test_get_parent_map_reconnects_if_unknown_method(self):
2650
2562
transport_path = 'quack'
2651
rev_id = b'revision-id'
2563
rev_id = 'revision-id'
2652
2564
repo, client = self.setup_fake_client_and_repository(transport_path)
2653
client.add_unknown_method_response(b'Repository.get_parent_map')
2654
client.add_success_response_with_body(rev_id, b'ok')
2565
client.add_unknown_method_response('Repository.get_parent_map')
2566
client.add_success_response_with_body(rev_id, 'ok')
2655
2567
self.assertFalse(client._medium._is_remote_before((1, 2)))
2656
2568
parents = repo.get_parent_map([rev_id])
2657
2569
self.assertEqual(
2658
2570
[('call_with_body_bytes_expecting_body',
2659
b'Repository.get_parent_map',
2660
(b'quack/', b'include-missing:', rev_id), b'\n\n0'),
2571
'Repository.get_parent_map',
2572
('quack/', 'include-missing:', rev_id), '\n\n0'),
2661
2573
('disconnect medium',),
2662
('call_expecting_body', b'Repository.get_revision_graph',
2574
('call_expecting_body', 'Repository.get_revision_graph',
2665
2577
# The medium is now marked as being connected to an older server
2666
2578
self.assertTrue(client._medium._is_remote_before((1, 2)))
2667
self.assertEqual({rev_id: (b'null:',)}, parents)
2579
self.assertEqual({rev_id: ('null:',)}, parents)
2669
2581
def test_get_parent_map_fallback_parentless_node(self):
2670
2582
"""get_parent_map falls back to get_revision_graph on old servers. The
2678
2590
This is the test for https://bugs.launchpad.net/bzr/+bug/214894
2680
rev_id = b'revision-id'
2592
rev_id = 'revision-id'
2681
2593
transport_path = 'quack'
2682
2594
repo, client = self.setup_fake_client_and_repository(transport_path)
2683
client.add_success_response_with_body(rev_id, b'ok')
2595
client.add_success_response_with_body(rev_id, 'ok')
2684
2596
client._medium._remember_remote_is_before((1, 2))
2685
2597
parents = repo.get_parent_map([rev_id])
2686
2598
self.assertEqual(
2687
[('call_expecting_body', b'Repository.get_revision_graph',
2599
[('call_expecting_body', 'Repository.get_revision_graph',
2690
self.assertEqual({rev_id: (b'null:',)}, parents)
2602
self.assertEqual({rev_id: ('null:',)}, parents)
2692
2604
def test_get_parent_map_unexpected_response(self):
2693
2605
repo, client = self.setup_fake_client_and_repository('path')
2694
client.add_success_response(b'something unexpected!')
2606
client.add_success_response('something unexpected!')
2695
2607
self.assertRaises(
2696
2608
errors.UnexpectedSmartServerResponse,
2697
repo.get_parent_map, [b'a-revision-id'])
2609
repo.get_parent_map, ['a-revision-id'])
2699
2611
def test_get_parent_map_negative_caches_missing_keys(self):
2700
2612
self.setup_smart_server_with_call_log()
2743
2654
self.addCleanup(repo.unlock)
2744
2655
self.reset_smart_call_log()
2745
2656
graph = repo.get_graph()
2746
# Query for b'first' and b'null:'. Because b'null:' is a parent of
2657
# Query for 'first' and 'null:'. Because 'null:' is a parent of
2747
2658
# 'first' it will be a candidate for the stop_keys of subsequent
2748
# requests, and because b'null:' was queried but not returned it will
2749
# be cached as missing.
2750
self.assertEqual({b'first': (b'null:',)},
2751
graph.get_parent_map([b'first', b'null:']))
2659
# requests, and because 'null:' was queried but not returned it will be
2660
# cached as missing.
2661
self.assertEqual({'first': ('null:',)},
2662
graph.get_parent_map(['first', 'null:']))
2752
2663
# Now query for another key. This request will pass along a recipe of
2753
2664
# start and stop keys describing the already cached results, and this
2754
2665
# recipe's revision count must be correct (or else it will trigger an
2755
2666
# error from the server).
2756
self.assertEqual({}, graph.get_parent_map([b'another-key']))
2667
self.assertEqual({}, graph.get_parent_map(['another-key']))
2757
2668
# This assertion guards against disableExtraResults silently failing to
2758
2669
# work, thus invalidating the test.
2759
2670
self.assertLength(2, self.hpss_calls)
2789
2702
r1 = u'\u0e33'.encode('utf8')
2790
2703
r2 = u'\u0dab'.encode('utf8')
2791
lines = [b' '.join([r2, r1]), r1]
2792
encoded_body = bz2.compress(b'\n'.join(lines))
2704
lines = [' '.join([r2, r1]), r1]
2705
encoded_body = bz2.compress('\n'.join(lines))
2794
2707
transport_path = 'quack'
2795
2708
repo, client = self.setup_fake_client_and_repository(transport_path)
2796
client.add_success_response_with_body(encoded_body, b'ok')
2709
client.add_success_response_with_body(encoded_body, 'ok')
2797
2710
repo.lock_read()
2798
2711
# get_cached_parent_map should *not* trigger an RPC
2799
2712
self.assertEqual({}, repo.get_cached_parent_map([r1]))
2800
2713
self.assertEqual([], client._calls)
2801
2714
self.assertEqual({r2: (r1,)}, repo.get_parent_map([r2]))
2802
2715
self.assertEqual({r1: (NULL_REVISION,)},
2803
repo.get_cached_parent_map([r1]))
2716
repo.get_cached_parent_map([r1]))
2804
2717
self.assertEqual(
2805
2718
[('call_with_body_bytes_expecting_body',
2806
b'Repository.get_parent_map', (b'quack/',
2807
b'include-missing:', r2),
2719
'Repository.get_parent_map', ('quack/', 'include-missing:', r2),
2836
2747
transport_path = 'quack'
2837
2748
repo, client = self.setup_fake_client_and_repository(transport_path)
2838
2749
client.add_success_response_with_body(
2840
2751
self.assertRaises(errors.NoSuchRevision, repo.get_revisions,
2841
[b'somerev1', b'anotherrev2'])
2752
['somerev1', 'anotherrev2'])
2842
2753
self.assertEqual(
2843
[('call_with_body_bytes_expecting_body',
2844
b'Repository.iter_revisions', (b'quack/', ),
2845
b"somerev1\nanotherrev2")],
2754
[('call_with_body_bytes_expecting_body', 'Repository.iter_revisions',
2755
('quack/', ), "somerev1\nanotherrev2")],
2848
2758
def test_hpss_get_single_revision(self):
2849
2759
transport_path = 'quack'
2850
2760
repo, client = self.setup_fake_client_and_repository(transport_path)
2851
somerev1 = Revision(b"somerev1")
2761
somerev1 = Revision("somerev1")
2852
2762
somerev1.committer = "Joe Committer <joe@example.com>"
2853
2763
somerev1.timestamp = 1321828927
2854
2764
somerev1.timezone = -60
2855
somerev1.inventory_sha1 = b"691b39be74c67b1212a75fcb19c433aaed903c2b"
2765
somerev1.inventory_sha1 = "691b39be74c67b1212a75fcb19c433aaed903c2b"
2856
2766
somerev1.message = "Message"
2857
body = zlib.compress(b''.join(chk_bencode_serializer.write_revision_to_lines(
2767
body = zlib.compress(chk_bencode_serializer.write_revision_to_string(
2859
2769
# Split up body into two bits to make sure the zlib compression object
2860
2770
# gets data fed twice.
2861
2771
client.add_success_response_with_body(
2862
[body[:10], body[10:]], b'ok', b'10')
2863
revs = repo.get_revisions([b'somerev1'])
2772
[body[:10], body[10:]], 'ok', '10')
2773
revs = repo.get_revisions(['somerev1'])
2864
2774
self.assertEqual(revs, [somerev1])
2865
2775
self.assertEqual(
2866
[('call_with_body_bytes_expecting_body',
2867
b'Repository.iter_revisions',
2868
(b'quack/', ), b"somerev1")],
2776
[('call_with_body_bytes_expecting_body', 'Repository.iter_revisions',
2777
('quack/', ), "somerev1")],
2908
2817
r11 = u'\u0e33'.encode('utf8')
2909
2818
r12 = u'\xc9'.encode('utf8')
2910
2819
r2 = u'\u0dab'.encode('utf8')
2911
lines = [b' '.join([r2, r11, r12]), r11, r12]
2912
encoded_body = b'\n'.join(lines)
2820
lines = [' '.join([r2, r11, r12]), r11, r12]
2821
encoded_body = '\n'.join(lines)
2914
2823
transport_path = 'sinhala'
2915
2824
repo, client = self.setup_fake_client_and_repository(transport_path)
2916
client.add_success_response_with_body(encoded_body, b'ok')
2825
client.add_success_response_with_body(encoded_body, 'ok')
2917
2826
result = repo._get_revision_graph(r2)
2918
2827
self.assertEqual(
2919
[('call_expecting_body', b'Repository.get_revision_graph',
2920
(b'sinhala/', r2))],
2828
[('call_expecting_body', 'Repository.get_revision_graph',
2922
2831
self.assertEqual({r11: (), r12: (), r2: (r11, r12), }, result)
2924
2833
def test_no_such_revision(self):
2926
2835
transport_path = 'sinhala'
2927
2836
repo, client = self.setup_fake_client_and_repository(transport_path)
2928
client.add_error_response(b'nosuchrevision', revid)
2837
client.add_error_response('nosuchrevision', revid)
2929
2838
# also check that the right revision is reported in the error
2930
2839
self.assertRaises(errors.NoSuchRevision,
2931
repo._get_revision_graph, revid)
2840
repo._get_revision_graph, revid)
2932
2841
self.assertEqual(
2933
[('call_expecting_body', b'Repository.get_revision_graph',
2934
(b'sinhala/', revid))],
2842
[('call_expecting_body', 'Repository.get_revision_graph',
2843
('sinhala/', revid))],
2937
2846
def test_unexpected_error(self):
2939
2848
transport_path = 'sinhala'
2940
2849
repo, client = self.setup_fake_client_and_repository(transport_path)
2941
client.add_error_response(b'AnUnexpectedError')
2850
client.add_error_response('AnUnexpectedError')
2942
2851
e = self.assertRaises(errors.UnknownErrorFromSmartServer,
2943
repo._get_revision_graph, revid)
2944
self.assertEqual((b'AnUnexpectedError',), e.error_tuple)
2852
repo._get_revision_graph, revid)
2853
self.assertEqual(('AnUnexpectedError',), e.error_tuple)
2947
2856
class TestRepositoryGetRevIdForRevno(TestRemoteRepository):
2949
2858
def test_ok(self):
2950
2859
repo, client = self.setup_fake_client_and_repository('quack')
2951
2860
client.add_expected_call(
2952
b'Repository.get_rev_id_for_revno', (b'quack/',
2953
5, (42, b'rev-foo')),
2954
b'success', (b'ok', b'rev-five'))
2955
result = repo.get_rev_id_for_revno(5, (42, b'rev-foo'))
2956
self.assertEqual((True, b'rev-five'), result)
2861
'Repository.get_rev_id_for_revno', ('quack/', 5, (42, 'rev-foo')),
2862
'success', ('ok', 'rev-five'))
2863
result = repo.get_rev_id_for_revno(5, (42, 'rev-foo'))
2864
self.assertEqual((True, 'rev-five'), result)
2957
2865
self.assertFinished(client)
2959
2867
def test_history_incomplete(self):
2960
2868
repo, client = self.setup_fake_client_and_repository('quack')
2961
2869
client.add_expected_call(
2962
b'Repository.get_rev_id_for_revno', (b'quack/',
2963
5, (42, b'rev-foo')),
2964
b'success', (b'history-incomplete', 10, b'rev-ten'))
2965
result = repo.get_rev_id_for_revno(5, (42, b'rev-foo'))
2966
self.assertEqual((False, (10, b'rev-ten')), result)
2870
'Repository.get_rev_id_for_revno', ('quack/', 5, (42, 'rev-foo')),
2871
'success', ('history-incomplete', 10, 'rev-ten'))
2872
result = repo.get_rev_id_for_revno(5, (42, 'rev-foo'))
2873
self.assertEqual((False, (10, 'rev-ten')), result)
2967
2874
self.assertFinished(client)
2969
2876
def test_history_incomplete_with_fallback(self):
2982
2889
repo.add_fallback_repository(fallback_repo)
2983
2890
# First the client should ask the primary repo
2984
2891
client.add_expected_call(
2985
b'Repository.get_rev_id_for_revno', (b'quack/',
2986
1, (42, b'rev-foo')),
2987
b'success', (b'history-incomplete', 2, b'rev-two'))
2892
'Repository.get_rev_id_for_revno', ('quack/', 1, (42, 'rev-foo')),
2893
'success', ('history-incomplete', 2, 'rev-two'))
2988
2894
# Then it should ask the fallback, using revno/revid from the
2989
2895
# history-incomplete response as the known revno/revid.
2990
2896
client.add_expected_call(
2991
b'Repository.get_rev_id_for_revno', (
2992
b'fallback/', 1, (2, b'rev-two')),
2993
b'success', (b'ok', b'rev-one'))
2994
result = repo.get_rev_id_for_revno(1, (42, b'rev-foo'))
2995
self.assertEqual((True, b'rev-one'), result)
2897
'Repository.get_rev_id_for_revno',('fallback/', 1, (2, 'rev-two')),
2898
'success', ('ok', 'rev-one'))
2899
result = repo.get_rev_id_for_revno(1, (42, 'rev-foo'))
2900
self.assertEqual((True, 'rev-one'), result)
2996
2901
self.assertFinished(client)
2998
2903
def test_nosuchrevision(self):
3000
2905
# remote repo. The client translates that response to NoSuchRevision.
3001
2906
repo, client = self.setup_fake_client_and_repository('quack')
3002
2907
client.add_expected_call(
3003
b'Repository.get_rev_id_for_revno', (b'quack/',
3004
5, (42, b'rev-foo')),
3005
b'error', (b'nosuchrevision', b'rev-foo'))
2908
'Repository.get_rev_id_for_revno', ('quack/', 5, (42, 'rev-foo')),
2909
'error', ('nosuchrevision', 'rev-foo'))
3006
2910
self.assertRaises(
3007
2911
errors.NoSuchRevision,
3008
repo.get_rev_id_for_revno, 5, (42, b'rev-foo'))
3009
self.assertFinished(client)
3011
def test_outofbounds(self):
3012
repo, client = self.setup_fake_client_and_repository('quack')
3013
client.add_expected_call(
3014
b'Repository.get_rev_id_for_revno', (b'quack/',
3015
43, (42, b'rev-foo')),
3016
b'error', (b'revno-outofbounds', 43, 0, 42))
3018
errors.RevnoOutOfBounds,
3019
repo.get_rev_id_for_revno, 43, (42, b'rev-foo'))
3020
self.assertFinished(client)
3022
def test_outofbounds_old(self):
3023
# Older versions of bzr didn't support RevnoOutOfBounds
3024
repo, client = self.setup_fake_client_and_repository('quack')
3025
client.add_expected_call(
3026
b'Repository.get_rev_id_for_revno', (b'quack/',
3027
43, (42, b'rev-foo')),
3029
b'error', b'ValueError',
3030
b'requested revno (43) is later than given known revno (42)'))
3032
errors.RevnoOutOfBounds,
3033
repo.get_rev_id_for_revno, 43, (42, b'rev-foo'))
2912
repo.get_rev_id_for_revno, 5, (42, 'rev-foo'))
3034
2913
self.assertFinished(client)
3036
2915
def test_branch_fallback_locking(self):
3162
3041
def test_lock_write(self):
3163
3042
transport_path = 'quack'
3164
3043
repo, client = self.setup_fake_client_and_repository(transport_path)
3165
client.add_success_response(b'ok', b'a token')
3044
client.add_success_response('ok', 'a token')
3166
3045
token = repo.lock_write().repository_token
3167
3046
self.assertEqual(
3168
[('call', b'Repository.lock_write', (b'quack/', b''))],
3047
[('call', 'Repository.lock_write', ('quack/', ''))],
3170
self.assertEqual(b'a token', token)
3049
self.assertEqual('a token', token)
3172
3051
def test_lock_write_already_locked(self):
3173
3052
transport_path = 'quack'
3174
3053
repo, client = self.setup_fake_client_and_repository(transport_path)
3175
client.add_error_response(b'LockContention')
3054
client.add_error_response('LockContention')
3176
3055
self.assertRaises(errors.LockContention, repo.lock_write)
3177
3056
self.assertEqual(
3178
[('call', b'Repository.lock_write', (b'quack/', b''))],
3057
[('call', 'Repository.lock_write', ('quack/', ''))],
3181
3060
def test_lock_write_unlockable(self):
3182
3061
transport_path = 'quack'
3183
3062
repo, client = self.setup_fake_client_and_repository(transport_path)
3184
client.add_error_response(b'UnlockableTransport')
3063
client.add_error_response('UnlockableTransport')
3185
3064
self.assertRaises(errors.UnlockableTransport, repo.lock_write)
3186
3065
self.assertEqual(
3187
[('call', b'Repository.lock_write', (b'quack/', b''))],
3066
[('call', 'Repository.lock_write', ('quack/', ''))],
3207
3086
# groups. For those, fall back to the "real" repository.
3208
3087
transport_path = 'quack'
3209
3088
repo, client = self.setup_fake_client_and_repository(transport_path)
3211
3089
def stub_ensure_real():
3212
3090
client._calls.append(('_ensure_real',))
3213
3091
repo._real_repository = _StubRealPackRepository(client._calls)
3214
3092
repo._ensure_real = stub_ensure_real
3215
3093
client.add_expected_call(
3216
b'Repository.lock_write', (b'quack/', b''),
3217
b'success', (b'ok', b'a token'))
3094
'Repository.lock_write', ('quack/', ''),
3095
'success', ('ok', 'a token'))
3218
3096
client.add_expected_call(
3219
b'Repository.start_write_group', (b'quack/', b'a token'),
3220
b'error', (b'UnsuspendableWriteGroup',))
3097
'Repository.start_write_group', ('quack/', 'a token'),
3098
'error', ('UnsuspendableWriteGroup',))
3221
3099
repo.lock_write()
3222
3100
repo.start_write_group()
3223
self.assertEqual(client._calls[-2:], [
3101
self.assertEqual(client._calls[-2:], [
3224
3102
('_ensure_real',),
3225
3103
('start_write_group',)])
3228
3106
transport_path = 'quack'
3229
3107
repo, client = self.setup_fake_client_and_repository(transport_path)
3230
3108
client.add_expected_call(
3231
b'Repository.lock_write', (b'quack/', b''),
3232
b'success', (b'ok', b'a token'))
3233
client.add_expected_call(
3234
b'Repository.start_write_group', (b'quack/', b'a token'),
3235
b'success', (b'ok', [b'token1']))
3236
client.add_expected_call(
3237
b'Repository.commit_write_group', (b'quack/',
3238
b'a token', [b'token1']),
3239
b'success', (b'ok',))
3109
'Repository.lock_write', ('quack/', ''),
3110
'success', ('ok', 'a token'))
3111
client.add_expected_call(
3112
'Repository.start_write_group', ('quack/', 'a token'),
3113
'success', ('ok', ['token1']))
3114
client.add_expected_call(
3115
'Repository.commit_write_group', ('quack/', 'a token', ['token1']),
3240
3117
repo.lock_write()
3241
3118
repo.start_write_group()
3242
3119
repo.commit_write_group()
3245
3122
transport_path = 'quack'
3246
3123
repo, client = self.setup_fake_client_and_repository(transport_path)
3247
3124
client.add_expected_call(
3248
b'Repository.lock_write', (b'quack/', b''),
3249
b'success', (b'ok', b'a token'))
3250
client.add_expected_call(
3251
b'Repository.start_write_group', (b'quack/', b'a token'),
3252
b'success', (b'ok', [b'token1']))
3253
client.add_expected_call(
3254
b'Repository.abort_write_group', (b'quack/',
3255
b'a token', [b'token1']),
3256
b'success', (b'ok',))
3125
'Repository.lock_write', ('quack/', ''),
3126
'success', ('ok', 'a token'))
3127
client.add_expected_call(
3128
'Repository.start_write_group', ('quack/', 'a token'),
3129
'success', ('ok', ['token1']))
3130
client.add_expected_call(
3131
'Repository.abort_write_group', ('quack/', 'a token', ['token1']),
3257
3133
repo.lock_write()
3258
3134
repo.start_write_group()
3259
3135
repo.abort_write_group(False)
3308
3183
def test_unlock(self):
3309
3184
transport_path = 'quack'
3310
3185
repo, client = self.setup_fake_client_and_repository(transport_path)
3311
client.add_success_response(b'ok', b'a token')
3312
client.add_success_response(b'ok')
3186
client.add_success_response('ok', 'a token')
3187
client.add_success_response('ok')
3313
3188
repo.lock_write()
3315
3190
self.assertEqual(
3316
[('call', b'Repository.lock_write', (b'quack/', b'')),
3317
('call', b'Repository.unlock', (b'quack/', b'a token'))],
3191
[('call', 'Repository.lock_write', ('quack/', '')),
3192
('call', 'Repository.unlock', ('quack/', 'a token'))],
3320
3195
def test_unlock_wrong_token(self):
3321
3196
# If somehow the token is wrong, unlock will raise TokenMismatch.
3322
3197
transport_path = 'quack'
3323
3198
repo, client = self.setup_fake_client_and_repository(transport_path)
3324
client.add_success_response(b'ok', b'a token')
3325
client.add_error_response(b'TokenMismatch')
3199
client.add_success_response('ok', 'a token')
3200
client.add_error_response('TokenMismatch')
3326
3201
repo.lock_write()
3327
3202
self.assertRaises(errors.TokenMismatch, repo.unlock)
3348
3223
transport_path = 'quack'
3349
3224
repo, client = self.setup_fake_client_and_repository(transport_path)
3350
3225
client.add_expected_call(
3351
b'Repository.iter_files_bytes', (b'quack/', ),
3352
b'success', (b'ok',), iter([b"ok\x000", b"\n", zlib.compress(b"mydata" * 10)]))
3353
for (identifier, byte_stream) in repo.iter_files_bytes([(b"somefile",
3354
b"somerev", b"myid")]):
3355
self.assertEqual(b"myid", identifier)
3356
self.assertEqual(b"".join(byte_stream), b"mydata" * 10)
3226
'Repository.iter_files_bytes', ('quack/', ),
3227
'success', ('ok',), iter(["ok\x000", "\n", zlib.compress("mydata" * 10)]))
3228
for (identifier, byte_stream) in repo.iter_files_bytes([("somefile",
3229
"somerev", "myid")]):
3230
self.assertEqual("myid", identifier)
3231
self.assertEqual("".join(byte_stream), "mydata" * 10)
3358
3233
def test_missing(self):
3359
3234
transport_path = 'quack'
3360
3235
repo, client = self.setup_fake_client_and_repository(transport_path)
3361
3236
client.add_expected_call(
3362
b'Repository.iter_files_bytes',
3364
b'error', (b'RevisionNotPresent', b'somefile', b'somerev'),
3365
iter([b"absent\0somefile\0somerev\n"]))
3237
'Repository.iter_files_bytes',
3239
'error', ('RevisionNotPresent', 'somefile', 'somerev'),
3240
iter(["absent\0somefile\0somerev\n"]))
3366
3241
self.assertRaises(errors.RevisionNotPresent, list,
3367
repo.iter_files_bytes(
3368
[(b"somefile", b"somerev", b"myid")]))
3242
repo.iter_files_bytes(
3243
[("somefile", "somerev", "myid")]))
3371
3246
class TestRepositoryInsertStreamBase(TestRemoteRepository):
3372
3247
"""Base class for Repository.insert_stream and .insert_stream_1.19
3376
3251
def checkInsertEmptyStream(self, repo, client):
3377
3252
"""Insert an empty stream, checking the result.
3397
3272
def setUp(self):
3398
3273
super(TestRepositoryInsertStream, self).setUp()
3399
self.disable_verb(b'Repository.insert_stream_1.19')
3274
self.disable_verb('Repository.insert_stream_1.19')
3401
3276
def test_unlocked_repo(self):
3402
3277
transport_path = 'quack'
3403
3278
repo, client = self.setup_fake_client_and_repository(transport_path)
3404
3279
client.add_expected_call(
3405
b'Repository.insert_stream_1.19', (b'quack/', b''),
3406
b'unknown', (b'Repository.insert_stream_1.19',))
3407
client.add_expected_call(
3408
b'Repository.insert_stream', (b'quack/', b''),
3409
b'success', (b'ok',))
3410
client.add_expected_call(
3411
b'Repository.insert_stream', (b'quack/', b''),
3412
b'success', (b'ok',))
3280
'Repository.insert_stream_1.19', ('quack/', ''),
3281
'unknown', ('Repository.insert_stream_1.19',))
3282
client.add_expected_call(
3283
'Repository.insert_stream', ('quack/', ''),
3285
client.add_expected_call(
3286
'Repository.insert_stream', ('quack/', ''),
3413
3288
self.checkInsertEmptyStream(repo, client)
3415
3290
def test_locked_repo_with_no_lock_token(self):
3416
3291
transport_path = 'quack'
3417
3292
repo, client = self.setup_fake_client_and_repository(transport_path)
3418
3293
client.add_expected_call(
3419
b'Repository.lock_write', (b'quack/', b''),
3420
b'success', (b'ok', b''))
3421
client.add_expected_call(
3422
b'Repository.insert_stream_1.19', (b'quack/', b''),
3423
b'unknown', (b'Repository.insert_stream_1.19',))
3424
client.add_expected_call(
3425
b'Repository.insert_stream', (b'quack/', b''),
3426
b'success', (b'ok',))
3427
client.add_expected_call(
3428
b'Repository.insert_stream', (b'quack/', b''),
3429
b'success', (b'ok',))
3294
'Repository.lock_write', ('quack/', ''),
3295
'success', ('ok', ''))
3296
client.add_expected_call(
3297
'Repository.insert_stream_1.19', ('quack/', ''),
3298
'unknown', ('Repository.insert_stream_1.19',))
3299
client.add_expected_call(
3300
'Repository.insert_stream', ('quack/', ''),
3302
client.add_expected_call(
3303
'Repository.insert_stream', ('quack/', ''),
3430
3305
repo.lock_write()
3431
3306
self.checkInsertEmptyStream(repo, client)
3434
3309
transport_path = 'quack'
3435
3310
repo, client = self.setup_fake_client_and_repository(transport_path)
3436
3311
client.add_expected_call(
3437
b'Repository.lock_write', (b'quack/', b''),
3438
b'success', (b'ok', b'a token'))
3439
client.add_expected_call(
3440
b'Repository.insert_stream_1.19', (b'quack/', b'', b'a token'),
3441
b'unknown', (b'Repository.insert_stream_1.19',))
3442
client.add_expected_call(
3443
b'Repository.insert_stream_locked', (b'quack/', b'', b'a token'),
3444
b'success', (b'ok',))
3445
client.add_expected_call(
3446
b'Repository.insert_stream_locked', (b'quack/', b'', b'a token'),
3447
b'success', (b'ok',))
3312
'Repository.lock_write', ('quack/', ''),
3313
'success', ('ok', 'a token'))
3314
client.add_expected_call(
3315
'Repository.insert_stream_1.19', ('quack/', '', 'a token'),
3316
'unknown', ('Repository.insert_stream_1.19',))
3317
client.add_expected_call(
3318
'Repository.insert_stream_locked', ('quack/', '', 'a token'),
3320
client.add_expected_call(
3321
'Repository.insert_stream_locked', ('quack/', '', 'a token'),
3448
3323
repo.lock_write()
3449
3324
self.checkInsertEmptyStream(repo, client)
3457
3332
transport_path = 'quack'
3458
3333
repo, client = self.setup_fake_client_and_repository(transport_path)
3459
3334
client.add_expected_call(
3460
b'Repository.insert_stream_1.19', (b'quack/', b''),
3461
b'unknown', (b'Repository.insert_stream_1.19',))
3462
client.add_expected_call(
3463
b'Repository.insert_stream', (b'quack/', b''),
3464
b'success', (b'ok',))
3465
client.add_expected_call(
3466
b'Repository.insert_stream', (b'quack/', b''),
3467
b'success', (b'ok',))
3335
'Repository.insert_stream_1.19', ('quack/', ''),
3336
'unknown', ('Repository.insert_stream_1.19',))
3337
client.add_expected_call(
3338
'Repository.insert_stream', ('quack/', ''),
3340
client.add_expected_call(
3341
'Repository.insert_stream', ('quack/', ''),
3468
3343
# Create a fake real repository for insert_stream to fall back on, so
3469
3344
# that we can directly see the records the RemoteSink passes to the
3472
3346
class FakeRealSink:
3473
3347
def __init__(self):
3474
3348
self.records = []
3476
3349
def insert_stream(self, stream, src_format, resume_tokens):
3477
3350
for substream_kind, substream in stream:
3478
3351
self.records.append(
3479
3352
(substream_kind, [record.key for record in substream]))
3480
return [b'fake tokens'], [b'fake missing keys']
3353
return ['fake tokens'], ['fake missing keys']
3481
3354
fake_real_sink = FakeRealSink()
3483
3355
class FakeRealRepository:
3484
3356
def _get_sink(self):
3485
3357
return fake_real_sink
3487
3358
def is_in_write_group(self):
3490
3360
def refresh_data(self):
3492
3362
repo._real_repository = FakeRealRepository()
3517
3387
* texts substream: (some-rev, some-file)
3519
3389
# Define a stream using generators so that it isn't rewindable.
3520
inv = inventory.Inventory(revision_id=b'rev1')
3521
inv.root.revision = b'rev1'
3390
inv = inventory.Inventory(revision_id='rev1')
3391
inv.root.revision = 'rev1'
3523
3392
def stream_with_inv_delta():
3524
3393
yield ('inventories', inventories_substream())
3525
3394
yield ('inventory-deltas', inventory_delta_substream())
3526
3395
yield ('texts', [
3527
3396
versionedfile.FulltextContentFactory(
3528
(b'some-rev', b'some-file'), (), None, b'content')])
3397
('some-rev', 'some-file'), (), None, 'content')])
3530
3398
def inventories_substream():
3531
3399
# An empty inventory fulltext. This will be streamed normally.
3532
chunks = fmt._serializer.write_inventory_to_lines(inv)
3533
yield versionedfile.ChunkedContentFactory(
3534
(b'rev1',), (), None, chunks, chunks_are_lines=True)
3400
text = fmt._serializer.write_inventory_to_string(inv)
3401
yield versionedfile.FulltextContentFactory(
3402
('rev1',), (), None, text)
3536
3403
def inventory_delta_substream():
3537
3404
# An inventory delta. This can't be streamed via this verb, so it
3538
3405
# will trigger a fallback to VFS insert_stream.
3539
3406
entry = inv.make_entry(
3540
'directory', 'newdir', inv.root.file_id, b'newdir-id')
3541
entry.revision = b'ghost'
3542
delta = [(None, 'newdir', b'newdir-id', entry)]
3407
'directory', 'newdir', inv.root.file_id, 'newdir-id')
3408
entry.revision = 'ghost'
3409
delta = [(None, 'newdir', 'newdir-id', entry)]
3543
3410
serializer = inventory_delta.InventoryDeltaSerializer(
3544
3411
versioned_root=True, tree_references=False)
3545
lines = serializer.delta_to_lines(b'rev1', b'rev2', delta)
3412
lines = serializer.delta_to_lines('rev1', 'rev2', delta)
3546
3413
yield versionedfile.ChunkedContentFactory(
3547
(b'rev2',), ((b'rev1',)), None, lines)
3414
('rev2',), (('rev1',)), None, lines)
3548
3415
# Another delta.
3549
lines = serializer.delta_to_lines(b'rev1', b'rev3', delta)
3416
lines = serializer.delta_to_lines('rev1', 'rev3', delta)
3550
3417
yield versionedfile.ChunkedContentFactory(
3551
(b'rev3',), ((b'rev1',)), None, lines)
3418
('rev3',), (('rev1',)), None, lines)
3552
3419
return stream_with_inv_delta()
3558
3425
transport_path = 'quack'
3559
3426
repo, client = self.setup_fake_client_and_repository(transport_path)
3560
3427
client.add_expected_call(
3561
b'Repository.insert_stream_1.19', (b'quack/', b''),
3562
b'success', (b'ok',))
3428
'Repository.insert_stream_1.19', ('quack/', ''),
3563
3430
client.add_expected_call(
3564
b'Repository.insert_stream_1.19', (b'quack/', b''),
3565
b'success', (b'ok',))
3431
'Repository.insert_stream_1.19', ('quack/', ''),
3566
3433
self.checkInsertEmptyStream(repo, client)
3568
3435
def test_locked_repo_with_no_lock_token(self):
3569
3436
transport_path = 'quack'
3570
3437
repo, client = self.setup_fake_client_and_repository(transport_path)
3571
3438
client.add_expected_call(
3572
b'Repository.lock_write', (b'quack/', b''),
3573
b'success', (b'ok', b''))
3574
client.add_expected_call(
3575
b'Repository.insert_stream_1.19', (b'quack/', b''),
3576
b'success', (b'ok',))
3577
client.add_expected_call(
3578
b'Repository.insert_stream_1.19', (b'quack/', b''),
3579
b'success', (b'ok',))
3439
'Repository.lock_write', ('quack/', ''),
3440
'success', ('ok', ''))
3441
client.add_expected_call(
3442
'Repository.insert_stream_1.19', ('quack/', ''),
3444
client.add_expected_call(
3445
'Repository.insert_stream_1.19', ('quack/', ''),
3580
3447
repo.lock_write()
3581
3448
self.checkInsertEmptyStream(repo, client)
3584
3451
transport_path = 'quack'
3585
3452
repo, client = self.setup_fake_client_and_repository(transport_path)
3586
3453
client.add_expected_call(
3587
b'Repository.lock_write', (b'quack/', b''),
3588
b'success', (b'ok', b'a token'))
3589
client.add_expected_call(
3590
b'Repository.insert_stream_1.19', (b'quack/', b'', b'a token'),
3591
b'success', (b'ok',))
3592
client.add_expected_call(
3593
b'Repository.insert_stream_1.19', (b'quack/', b'', b'a token'),
3594
b'success', (b'ok',))
3454
'Repository.lock_write', ('quack/', ''),
3455
'success', ('ok', 'a token'))
3456
client.add_expected_call(
3457
'Repository.insert_stream_1.19', ('quack/', '', 'a token'),
3459
client.add_expected_call(
3460
'Repository.insert_stream_1.19', ('quack/', '', 'a token'),
3595
3462
repo.lock_write()
3596
3463
self.checkInsertEmptyStream(repo, client)
3784
3650
def test_NoSuchRevision(self):
3785
3651
branch = self.make_branch('')
3787
3653
translated_error = self.translateTuple(
3788
(b'NoSuchRevision', revid), branch=branch)
3654
('NoSuchRevision', revid), branch=branch)
3789
3655
expected_error = errors.NoSuchRevision(branch, revid)
3790
3656
self.assertEqual(expected_error, translated_error)
3792
3658
def test_nosuchrevision(self):
3793
3659
repository = self.make_repository('')
3795
3661
translated_error = self.translateTuple(
3796
(b'nosuchrevision', revid), repository=repository)
3662
('nosuchrevision', revid), repository=repository)
3797
3663
expected_error = errors.NoSuchRevision(repository, revid)
3798
3664
self.assertEqual(expected_error, translated_error)
3800
3666
def test_nobranch(self):
3801
bzrdir = self.make_controldir('')
3802
translated_error = self.translateTuple((b'nobranch',), bzrdir=bzrdir)
3667
bzrdir = self.make_bzrdir('')
3668
translated_error = self.translateTuple(('nobranch',), bzrdir=bzrdir)
3803
3669
expected_error = errors.NotBranchError(path=bzrdir.root_transport.base)
3804
3670
self.assertEqual(expected_error, translated_error)
3806
3672
def test_nobranch_one_arg(self):
3807
bzrdir = self.make_controldir('')
3673
bzrdir = self.make_bzrdir('')
3808
3674
translated_error = self.translateTuple(
3809
(b'nobranch', b'extra detail'), bzrdir=bzrdir)
3675
('nobranch', 'extra detail'), bzrdir=bzrdir)
3810
3676
expected_error = errors.NotBranchError(
3811
3677
path=bzrdir.root_transport.base,
3812
3678
detail='extra detail')
3813
3679
self.assertEqual(expected_error, translated_error)
3815
3681
def test_norepository(self):
3816
bzrdir = self.make_controldir('')
3817
translated_error = self.translateTuple((b'norepository',),
3682
bzrdir = self.make_bzrdir('')
3683
translated_error = self.translateTuple(('norepository',),
3819
3685
expected_error = errors.NoRepositoryPresent(bzrdir)
3820
3686
self.assertEqual(expected_error, translated_error)
3822
3688
def test_LockContention(self):
3823
translated_error = self.translateTuple((b'LockContention',))
3689
translated_error = self.translateTuple(('LockContention',))
3824
3690
expected_error = errors.LockContention('(remote lock)')
3825
3691
self.assertEqual(expected_error, translated_error)
3827
3693
def test_UnlockableTransport(self):
3828
bzrdir = self.make_controldir('')
3694
bzrdir = self.make_bzrdir('')
3829
3695
translated_error = self.translateTuple(
3830
(b'UnlockableTransport',), bzrdir=bzrdir)
3696
('UnlockableTransport',), bzrdir=bzrdir)
3831
3697
expected_error = errors.UnlockableTransport(bzrdir.root_transport)
3832
3698
self.assertEqual(expected_error, translated_error)
3834
3700
def test_LockFailed(self):
3835
3701
lock = 'str() of a server lock'
3836
3702
why = 'str() of why'
3837
translated_error = self.translateTuple(
3838
(b'LockFailed', lock.encode('ascii'), why.encode('ascii')))
3703
translated_error = self.translateTuple(('LockFailed', lock, why))
3839
3704
expected_error = errors.LockFailed(lock, why)
3840
3705
self.assertEqual(expected_error, translated_error)
3842
3707
def test_TokenMismatch(self):
3843
3708
token = 'a lock token'
3844
translated_error = self.translateTuple(
3845
(b'TokenMismatch',), token=token)
3709
translated_error = self.translateTuple(('TokenMismatch',), token=token)
3846
3710
expected_error = errors.TokenMismatch(token, '(remote token)')
3847
3711
self.assertEqual(expected_error, translated_error)
3850
3714
branch = self.make_branch('a')
3851
3715
other_branch = self.make_branch('b')
3852
3716
translated_error = self.translateTuple(
3853
(b'Diverged',), branch=branch, other_branch=other_branch)
3717
('Diverged',), branch=branch, other_branch=other_branch)
3854
3718
expected_error = errors.DivergedBranches(branch, other_branch)
3855
3719
self.assertEqual(expected_error, translated_error)
3857
3721
def test_NotStacked(self):
3858
3722
branch = self.make_branch('')
3859
translated_error = self.translateTuple((b'NotStacked',), branch=branch)
3723
translated_error = self.translateTuple(('NotStacked',), branch=branch)
3860
3724
expected_error = errors.NotStacked(branch)
3861
3725
self.assertEqual(expected_error, translated_error)
3863
3727
def test_ReadError_no_args(self):
3864
3728
path = 'a path'
3865
translated_error = self.translateTuple((b'ReadError',), path=path)
3729
translated_error = self.translateTuple(('ReadError',), path=path)
3866
3730
expected_error = errors.ReadError(path)
3867
3731
self.assertEqual(expected_error, translated_error)
3869
3733
def test_ReadError(self):
3870
3734
path = 'a path'
3871
translated_error = self.translateTuple(
3872
(b'ReadError', path.encode('utf-8')))
3735
translated_error = self.translateTuple(('ReadError', path))
3873
3736
expected_error = errors.ReadError(path)
3874
3737
self.assertEqual(expected_error, translated_error)
3876
3739
def test_IncompatibleRepositories(self):
3877
translated_error = self.translateTuple((b'IncompatibleRepositories',
3878
b"repo1", b"repo2", b"details here"))
3740
translated_error = self.translateTuple(('IncompatibleRepositories',
3741
"repo1", "repo2", "details here"))
3879
3742
expected_error = errors.IncompatibleRepositories("repo1", "repo2",
3881
self.assertEqual(expected_error, translated_error)
3883
def test_GhostRevisionsHaveNoRevno(self):
3884
translated_error = self.translateTuple((b'GhostRevisionsHaveNoRevno',
3885
b"revid1", b"revid2"))
3886
expected_error = errors.GhostRevisionsHaveNoRevno(b"revid1", b"revid2")
3887
3744
self.assertEqual(expected_error, translated_error)
3889
3746
def test_PermissionDenied_no_args(self):
3890
3747
path = 'a path'
3891
translated_error = self.translateTuple((b'PermissionDenied',),
3748
translated_error = self.translateTuple(('PermissionDenied',),
3893
3750
expected_error = errors.PermissionDenied(path)
3894
3751
self.assertEqual(expected_error, translated_error)
3896
3753
def test_PermissionDenied_one_arg(self):
3897
3754
path = 'a path'
3898
translated_error = self.translateTuple(
3899
(b'PermissionDenied', path.encode('utf-8')))
3755
translated_error = self.translateTuple(('PermissionDenied', path))
3900
3756
expected_error = errors.PermissionDenied(path)
3901
3757
self.assertEqual(expected_error, translated_error)
3924
3780
def test_NoSuchFile_context_path(self):
3925
3781
local_path = "local path"
3926
translated_error = self.translateTuple((b'ReadError', b"remote path"),
3782
translated_error = self.translateTuple(('ReadError', "remote path"),
3928
3784
expected_error = errors.ReadError(local_path)
3929
3785
self.assertEqual(expected_error, translated_error)
3931
3787
def test_NoSuchFile_without_context(self):
3932
3788
remote_path = "remote path"
3933
translated_error = self.translateTuple(
3934
(b'ReadError', remote_path.encode('utf-8')))
3789
translated_error = self.translateTuple(('ReadError', remote_path))
3935
3790
expected_error = errors.ReadError(remote_path)
3936
3791
self.assertEqual(expected_error, translated_error)
3938
3793
def test_ReadOnlyError(self):
3939
translated_error = self.translateTuple((b'ReadOnlyError',))
3794
translated_error = self.translateTuple(('ReadOnlyError',))
3940
3795
expected_error = errors.TransportNotPossible("readonly transport")
3941
3796
self.assertEqual(expected_error, translated_error)
3943
3798
def test_MemoryError(self):
3944
translated_error = self.translateTuple((b'MemoryError',))
3799
translated_error = self.translateTuple(('MemoryError',))
3945
3800
self.assertStartsWith(str(translated_error),
3946
"remote server out of memory")
3801
"remote server out of memory")
3948
3803
def test_generic_IndexError_no_classname(self):
3949
err = errors.ErrorFromSmartServer(
3950
(b'error', b"list index out of range"))
3804
err = errors.ErrorFromSmartServer(('error', "list index out of range"))
3951
3805
translated_error = self.translateErrorFromSmartServer(err)
3952
3806
expected_error = errors.UnknownErrorFromSmartServer(err)
3953
3807
self.assertEqual(expected_error, translated_error)
4240
4090
orig_info = request_handlers.get_info(verb_name)
4241
4091
request_handlers.register(verb_name, verb, override_existing=True)
4242
4092
self.addCleanup(request_handlers.register, verb_name, orig_verb,
4243
override_existing=True, info=orig_info)
4093
override_existing=True, info=orig_info)
4245
4095
def test_fetch_everything_backwards_compat(self):
4246
4096
"""Can fetch with EverythingResult even with pre 2.4 servers.
4248
4098
Pre-2.4 do not support 'everything' searches with the
4249
4099
Repository.get_stream_1.19 verb.
4253
4102
class OldGetStreamVerb(SmartServerRepositoryGetStream_1_19):
4254
4103
"""A version of the Repository.get_stream_1.19 verb patched to
4255
4104
reject 'everything' searches the way 2.3 and earlier do.
4258
4106
def recreate_search(self, repository, search_bytes,
4259
4107
discard_excess=False):
4260
verb_log.append(search_bytes.split(b'\n', 1)[0])
4261
if search_bytes == b'everything':
4108
verb_log.append(search_bytes.split('\n', 1)[0])
4109
if search_bytes == 'everything':
4263
request.FailedSmartServerResponse((b'BadSearch',)))
4111
request.FailedSmartServerResponse(('BadSearch',)))
4264
4112
return super(OldGetStreamVerb,
4265
self).recreate_search(repository, search_bytes,
4266
discard_excess=discard_excess)
4267
self.override_verb(b'Repository.get_stream_1.19', OldGetStreamVerb)
4113
self).recreate_search(repository, search_bytes,
4114
discard_excess=discard_excess)
4115
self.override_verb('Repository.get_stream_1.19', OldGetStreamVerb)
4268
4116
local = self.make_branch('local')
4269
4117
builder = self.make_branch_builder('remote')
4270
4118
builder.build_commit(message="Commit.")
4335
4183
def __init__(self, urgency):
4336
4184
self.urgency = urgency
4337
remote.no_context_error_translators.register(b"OutOfCoffee",
4338
lambda err: OutOfCoffee(err.error_args[0]))
4185
remote.no_context_error_translators.register("OutOfCoffee",
4186
lambda err: OutOfCoffee(err.error_args[0]))
4339
4187
transport = MemoryTransport()
4340
4188
client = FakeClient(transport.base)
4341
4189
client.add_expected_call(
4342
b'Branch.get_stacked_on_url', (b'quack/',),
4343
b'error', (b'NotStacked',))
4190
'Branch.get_stacked_on_url', ('quack/',),
4191
'error', ('NotStacked',))
4344
4192
client.add_expected_call(
4345
b'Branch.last_revision_info',
4347
b'error', (b'OutOfCoffee', b'low'))
4193
'Branch.last_revision_info',
4195
'error', ('OutOfCoffee', 'low'))
4348
4196
transport.mkdir('quack')
4349
4197
transport = transport.clone('quack')
4350
4198
branch = self.make_remote_branch(transport, client)
4356
4204
def __init__(self, branch, urgency):
4357
4205
self.branch = branch
4358
4206
self.urgency = urgency
4359
remote.error_translators.register(b"OutOfTea",
4360
lambda err, find, path: OutOfTea(
4361
err.error_args[0].decode(
4207
remote.error_translators.register("OutOfTea",
4208
lambda err, find, path: OutOfTea(err.error_args[0],
4364
4210
transport = MemoryTransport()
4365
4211
client = FakeClient(transport.base)
4366
4212
client.add_expected_call(
4367
b'Branch.get_stacked_on_url', (b'quack/',),
4368
b'error', (b'NotStacked',))
4213
'Branch.get_stacked_on_url', ('quack/',),
4214
'error', ('NotStacked',))
4369
4215
client.add_expected_call(
4370
b'Branch.last_revision_info',
4372
b'error', (b'OutOfTea', b'low'))
4216
'Branch.last_revision_info',
4218
'error', ('OutOfTea', 'low'))
4373
4219
transport.mkdir('quack')
4374
4220
transport = transport.clone('quack')
4375
4221
branch = self.make_remote_branch(transport, client)
4383
4229
transport_path = 'quack'
4384
4230
repo, client = self.setup_fake_client_and_repository(transport_path)
4385
4231
client.add_expected_call(
4386
b'Repository.lock_write', (b'quack/', b''),
4387
b'success', (b'ok', b'token'))
4388
client.add_expected_call(
4389
b'Repository.pack', (b'quack/', b'token', b'False'),
4390
b'success', (b'ok',), )
4391
client.add_expected_call(
4392
b'Repository.unlock', (b'quack/', b'token'),
4393
b'success', (b'ok', ))
4232
'Repository.lock_write', ('quack/', ''),
4233
'success', ('ok', 'token'))
4234
client.add_expected_call(
4235
'Repository.pack', ('quack/', 'token', 'False'),
4236
'success', ('ok',), )
4237
client.add_expected_call(
4238
'Repository.unlock', ('quack/', 'token'),
4239
'success', ('ok', ))
4396
4242
def test_pack_with_hint(self):
4397
4243
transport_path = 'quack'
4398
4244
repo, client = self.setup_fake_client_and_repository(transport_path)
4399
4245
client.add_expected_call(
4400
b'Repository.lock_write', (b'quack/', b''),
4401
b'success', (b'ok', b'token'))
4402
client.add_expected_call(
4403
b'Repository.pack', (b'quack/', b'token', b'False'),
4404
b'success', (b'ok',), )
4405
client.add_expected_call(
4406
b'Repository.unlock', (b'quack/', b'token', b'False'),
4407
b'success', (b'ok', ))
4246
'Repository.lock_write', ('quack/', ''),
4247
'success', ('ok', 'token'))
4248
client.add_expected_call(
4249
'Repository.pack', ('quack/', 'token', 'False'),
4250
'success', ('ok',), )
4251
client.add_expected_call(
4252
'Repository.unlock', ('quack/', 'token', 'False'),
4253
'success', ('ok', ))
4408
4254
repo.pack(['hinta', 'hintb'])
4443
4288
transport_path = 'quack'
4444
4289
repo, client = self.setup_fake_client_and_repository(transport_path)
4445
4290
client.add_expected_call(
4446
b'VersionedFileRepository.get_inventories', (
4447
b'quack/', b'unordered'),
4448
b'success', (b'ok', ), iter([]))
4291
'VersionedFileRepository.get_inventories', ('quack/', 'unordered'),
4292
'success', ('ok', ), iter([]))
4449
4293
self.assertRaises(errors.NoSuchRevision, list, repo.iter_inventories(
4453
class TestRepositoryRevisionTreeArchive(TestRemoteRepository):
4454
"""Test Repository.iter_inventories."""
4456
def _serialize_inv_delta(self, old_name, new_name, delta):
4457
serializer = inventory_delta.InventoryDeltaSerializer(True, False)
4458
return b"".join(serializer.delta_to_lines(old_name, new_name, delta))
4460
def test_simple(self):
4461
transport_path = 'quack'
4462
repo, client = self.setup_fake_client_and_repository(transport_path)
4463
fmt = controldir.format_registry.get('2a')().repository_format
4465
stream = [('inventory-deltas', [
4466
versionedfile.FulltextContentFactory(b'somerevid', None, None,
4467
self._serialize_inv_delta(b'null:', b'somerevid', []))])]
4468
client.add_expected_call(
4469
b'VersionedFileRepository.get_inventories', (
4470
b'quack/', b'unordered'),
4471
b'success', (b'ok', ),
4472
_stream_to_byte_stream(stream, fmt))
4474
with tarfile.open(mode='w', fileobj=f) as tf:
4475
info = tarfile.TarInfo('somefile')
4477
contents = b'some data'
4478
info.type = tarfile.REGTYPE
4480
info.size = len(contents)
4481
tf.addfile(info, BytesIO(contents))
4482
client.add_expected_call(
4483
b'Repository.revision_archive', (b'quack/',
4484
b'somerevid', b'tar', b'foo.tar', b'', b'', None),
4485
b'success', (b'ok', ),
4487
tree = repo.revision_tree(b'somerevid')
4488
self.assertEqual(f.getvalue(), b''.join(
4489
tree.archive('tar', 'foo.tar')))
4492
class TestRepositoryAnnotate(TestRemoteRepository):
4493
"""Test RemoteRevisionTree.annotate.."""
4495
def _serialize_inv_delta(self, old_name, new_name, delta):
4496
serializer = inventory_delta.InventoryDeltaSerializer(True, False)
4497
return b"".join(serializer.delta_to_lines(old_name, new_name, delta))
4499
def test_simple(self):
4500
transport_path = 'quack'
4501
repo, client = self.setup_fake_client_and_repository(transport_path)
4502
fmt = controldir.format_registry.get('2a')().repository_format
4505
('inventory-deltas', [
4506
versionedfile.FulltextContentFactory(
4507
b'somerevid', None, None,
4508
self._serialize_inv_delta(b'null:', b'somerevid', []))])]
4509
client.add_expected_call(
4510
b'VersionedFileRepository.get_inventories', (
4511
b'quack/', b'unordered'),
4512
b'success', (b'ok', ),
4513
_stream_to_byte_stream(stream, fmt))
4514
client.add_expected_call(
4515
b'Repository.annotate_file_revision',
4516
(b'quack/', b'somerevid', b'filename', b'', b'current:'),
4517
b'success', (b'ok', ),
4518
bencode.bencode([[b'baserevid', b'line 1\n'],
4519
[b'somerevid', b'line2\n']]))
4520
tree = repo.revision_tree(b'somerevid')
4522
(b'baserevid', b'line 1\n'),
4523
(b'somerevid', b'line2\n')],
4524
list(tree.annotate_iter('filename')))
4527
class TestBranchGetAllReferenceInfo(RemoteBranchTestCase):
4529
def test_get_all_reference_info(self):
4530
transport = MemoryTransport()
4531
client = FakeClient(transport.base)
4532
client.add_expected_call(
4533
b'Branch.get_stacked_on_url', (b'quack/',),
4534
b'error', (b'NotStacked',))
4535
client.add_expected_call(
4536
b'Branch.get_all_reference_info', (b'quack/',),
4537
b'success', (b'ok',), bencode.bencode([
4538
(b'file-id', b'https://www.example.com/', b'')]))
4539
transport.mkdir('quack')
4540
transport = transport.clone('quack')
4541
branch = self.make_remote_branch(transport, client)
4542
result = branch._get_all_reference_info()
4543
self.assertFinished(client)
4544
self.assertEqual({b'file-id': ('https://www.example.com/', None)}, result)