431
438
def test_backwards_compat(self):
432
439
self.setup_smart_server_with_call_log()
433
a_dir = self.make_bzrdir('.')
440
a_dir = self.make_controldir('.')
434
441
self.reset_smart_call_log()
435
verb = 'BzrDir.cloning_metadir'
442
verb = b'BzrDir.cloning_metadir'
436
443
self.disable_verb(verb)
437
format = a_dir.cloning_metadir()
444
a_dir.cloning_metadir()
438
445
call_count = len([call for call in self.hpss_calls if
439
call.call.method == verb])
446
call.call.method == verb])
440
447
self.assertEqual(1, call_count)
442
449
def test_branch_reference(self):
443
450
transport = self.get_transport('quack')
444
451
referenced = self.make_branch('referenced')
445
expected = referenced.bzrdir.cloning_metadir()
452
expected = referenced.controldir.cloning_metadir()
446
453
client = FakeClient(transport.base)
447
454
client.add_expected_call(
448
'BzrDir.cloning_metadir', ('quack/', 'False'),
449
'error', ('BranchReference',)),
455
b'BzrDir.cloning_metadir', (b'quack/', b'False'),
456
b'error', (b'BranchReference',)),
450
457
client.add_expected_call(
451
'BzrDir.open_branchV3', ('quack/',),
452
'success', ('ref', self.get_url('referenced'))),
453
a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
455
result = a_bzrdir.cloning_metadir()
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()
456
463
# We should have got a control dir matching the referenced branch.
457
464
self.assertEqual(bzrdir.BzrDirMetaFormat1, type(result))
458
self.assertEqual(expected._repository_format, result._repository_format)
465
self.assertEqual(expected._repository_format,
466
result._repository_format)
459
467
self.assertEqual(expected._branch_format, result._branch_format)
460
468
self.assertFinished(client)
462
470
def test_current_server(self):
463
471
transport = self.get_transport('.')
464
472
transport = transport.clone('quack')
465
self.make_bzrdir('quack')
473
self.make_controldir('quack')
466
474
client = FakeClient(transport.base)
467
reference_bzrdir_format = bzrdir.format_registry.get('default')()
475
reference_bzrdir_format = controldir.format_registry.get('default')()
468
476
control_name = reference_bzrdir_format.network_name()
469
477
client.add_expected_call(
470
'BzrDir.cloning_metadir', ('quack/', 'False'),
471
'success', (control_name, '', ('branch', ''))),
472
a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
474
result = a_bzrdir.cloning_metadir()
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()
475
483
# We should have got a reference control dir with default branch and
476
484
# repository formats.
477
485
# This pokes a little, just to be sure.
480
488
self.assertEqual(None, result._branch_format)
481
489
self.assertFinished(client)
491
def test_unknown(self):
492
transport = self.get_transport('quack')
493
referenced = self.make_branch('referenced')
494
referenced.controldir.cloning_metadir()
495
client = FakeClient(transport.base)
496
client.add_expected_call(
497
b'BzrDir.cloning_metadir', (b'quack/', b'False'),
498
b'success', (b'unknown', b'unknown', (b'branch', b''))),
499
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
501
self.assertRaises(errors.UnknownFormatError,
502
a_controldir.cloning_metadir)
505
class TestBzrDirCheckoutMetaDir(TestRemote):
507
def test__get_checkout_format(self):
508
transport = MemoryTransport()
509
client = FakeClient(transport.base)
510
reference_bzrdir_format = controldir.format_registry.get('default')()
511
control_name = reference_bzrdir_format.network_name()
512
client.add_expected_call(
513
b'BzrDir.checkout_metadir', (b'quack/', ),
514
b'success', (control_name, b'', b''))
515
transport.mkdir('quack')
516
transport = transport.clone('quack')
517
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
519
result = a_controldir.checkout_metadir()
520
# We should have got a reference control dir with default branch and
521
# repository formats.
522
self.assertEqual(bzrdir.BzrDirMetaFormat1, type(result))
523
self.assertEqual(None, result._repository_format)
524
self.assertEqual(None, result._branch_format)
525
self.assertFinished(client)
527
def test_unknown_format(self):
528
transport = MemoryTransport()
529
client = FakeClient(transport.base)
530
client.add_expected_call(
531
b'BzrDir.checkout_metadir', (b'quack/',),
532
b'success', (b'dontknow', b'', b''))
533
transport.mkdir('quack')
534
transport = transport.clone('quack')
535
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
537
self.assertRaises(errors.UnknownFormatError,
538
a_controldir.checkout_metadir)
539
self.assertFinished(client)
542
class TestBzrDirGetBranches(TestRemote):
544
def test_get_branches(self):
545
transport = MemoryTransport()
546
client = FakeClient(transport.base)
547
reference_bzrdir_format = controldir.format_registry.get('default')()
548
branch_name = reference_bzrdir_format.get_branch_format().network_name()
549
client.add_success_response_with_body(
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')
561
transport.mkdir('quack')
562
transport = transport.clone('quack')
563
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
565
result = a_controldir.get_branches()
566
self.assertEqual({"", "foo"}, set(result.keys()))
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/', ))],
576
class TestBzrDirDestroyBranch(TestRemote):
578
def test_destroy_default(self):
579
transport = self.get_transport('quack')
580
self.make_branch('referenced')
581
client = FakeClient(transport.base)
582
client.add_expected_call(
583
b'BzrDir.destroy_branch', (b'quack/', ),
584
b'success', (b'ok',)),
585
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
587
a_controldir.destroy_branch()
588
self.assertFinished(client)
591
class TestBzrDirHasWorkingTree(TestRemote):
593
def test_has_workingtree(self):
594
transport = self.get_transport('quack')
595
client = FakeClient(transport.base)
596
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())
602
self.assertFinished(client)
604
def test_no_workingtree(self):
605
transport = self.get_transport('quack')
606
client = FakeClient(transport.base)
607
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())
613
self.assertFinished(client)
616
class TestBzrDirDestroyRepository(TestRemote):
618
def test_destroy_repository(self):
619
transport = self.get_transport('quack')
620
client = FakeClient(transport.base)
621
client.add_expected_call(
622
b'BzrDir.destroy_repository', (b'quack/',),
623
b'success', (b'ok',)),
624
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
626
a_controldir.destroy_repository()
627
self.assertFinished(client)
484
630
class TestBzrDirOpen(TestRemote):
632
783
network_name = reference_format.network_name()
633
784
branch_network_name = self.get_branch_format().network_name()
634
785
client.add_expected_call(
635
'BzrDir.open_branchV3', ('~hello/',),
636
'success', ('branch', branch_network_name))
637
client.add_expected_call(
638
'BzrDir.find_repositoryV3', ('~hello/',),
639
'success', ('ok', '', 'no', 'no', 'no', network_name))
640
client.add_expected_call(
641
'Branch.get_stacked_on_url', ('~hello/',),
642
'error', ('NotStacked',))
643
bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
645
result = bzrdir.open_branch()
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',))
794
bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
646
797
self.assertFinished(client)
648
def check_open_repository(self, rich_root, subtrees, external_lookup='no'):
799
def check_open_repository(self, rich_root, subtrees,
800
external_lookup=b'no'):
649
801
reference_format = self.get_repo_format()
650
802
network_name = reference_format.network_name()
651
803
transport = MemoryTransport()
652
804
transport.mkdir('quack')
653
805
transport = transport.clone('quack')
655
rich_response = 'yes'
807
rich_response = b'yes'
809
rich_response = b'no'
659
subtree_response = 'yes'
811
subtree_response = b'yes'
661
subtree_response = 'no'
813
subtree_response = b'no'
662
814
client = FakeClient(transport.base)
663
815
client.add_success_response(
664
'ok', '', rich_response, subtree_response, external_lookup,
816
b'ok', b'', rich_response, subtree_response, external_lookup,
666
bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
818
bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
668
820
result = bzrdir.open_repository()
669
821
self.assertEqual(
670
[('call', 'BzrDir.find_repositoryV3', ('quack/',))],
822
[('call', b'BzrDir.find_repositoryV3', (b'quack/',))],
672
824
self.assertIsInstance(result, RemoteRepository)
673
self.assertEqual(bzrdir, result.bzrdir)
825
self.assertEqual(bzrdir, result.controldir)
674
826
self.assertEqual(rich_root, result._format.rich_root_data)
675
827
self.assertEqual(subtrees, result._format.supports_tree_reference)
706
860
transport = transport.clone('quack')
707
861
self.make_repository('quack')
708
862
client = FakeClient(transport.base)
709
reference_bzrdir_format = bzrdir.format_registry.get('default')()
710
reference_format = reference_bzrdir_format.get_branch_format()
711
network_name = reference_format.network_name()
712
reference_repo_fmt = reference_bzrdir_format.repository_format
713
reference_repo_name = reference_repo_fmt.network_name()
714
client.add_expected_call(
715
'BzrDir.create_branch', ('quack/', network_name),
716
'success', ('ok', network_name, '', 'no', 'no', 'yes',
717
reference_repo_name))
718
a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
720
branch = a_bzrdir.create_branch()
863
reference_bzrdir_format = controldir.format_registry.get('default')()
864
reference_format = reference_bzrdir_format.get_branch_format()
865
network_name = reference_format.network_name()
866
reference_repo_fmt = reference_bzrdir_format.repository_format
867
reference_repo_name = reference_repo_fmt.network_name()
868
client.add_expected_call(
869
b'BzrDir.create_branch', (b'quack/', network_name),
870
b'success', (b'ok', network_name, b'', b'no', b'no', b'yes',
871
reference_repo_name))
872
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
874
branch = a_controldir.create_branch()
875
# We should have got a remote branch
876
self.assertIsInstance(branch, remote.RemoteBranch)
877
# its format should have the settings from the response
878
format = branch._format
879
self.assertEqual(network_name, format.network_name())
881
def test_already_open_repo_and_reused_medium(self):
882
"""Bug 726584: create_branch(..., repository=repo) should work
883
regardless of what the smart medium's base URL is.
885
self.transport_server = test_server.SmartTCPServer_for_testing
886
transport = self.get_transport('.')
887
repo = self.make_repository('quack')
888
# Client's medium rooted a transport root (not at the bzrdir)
889
client = FakeClient(transport.base)
890
transport = transport.clone('quack')
891
reference_bzrdir_format = controldir.format_registry.get('default')()
892
reference_format = reference_bzrdir_format.get_branch_format()
893
network_name = reference_format.network_name()
894
reference_repo_fmt = reference_bzrdir_format.repository_format
895
reference_repo_name = reference_repo_fmt.network_name()
896
client.add_expected_call(
897
b'BzrDir.create_branch', (b'extra/quack/', network_name),
898
b'success', (b'ok', network_name, b'', b'no', b'no', b'yes',
899
reference_repo_name))
900
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
902
branch = a_controldir.create_branch(repository=repo)
721
903
# We should have got a remote branch
722
904
self.assertIsInstance(branch, remote.RemoteBranch)
723
905
# its format should have the settings from the response
772
954
server_url = 'bzr://example.com/'
773
955
self.permit_url(server_url)
774
956
client = FakeClient(server_url)
775
client.add_unknown_method_response('BzrDir.find_repositoryV3')
776
client.add_unknown_method_response('BzrDir.find_repositoryV2')
777
client.add_success_response('ok', '', 'no', 'no')
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')
778
960
# A real repository instance will be created to determine the network
780
962
client.add_success_response_with_body(
781
"Bazaar-NG meta directory, format 1\n", 'ok')
963
b"Bazaar-NG meta directory, format 1\n", b'ok')
964
client.add_success_response(b'stat', b'0', b'65535')
782
965
client.add_success_response_with_body(
783
reference_format.get_format_string(), 'ok')
966
reference_format.get_format_string(), b'ok')
784
967
# PackRepository wants to do a stat
785
client.add_success_response('stat', '0', '65535')
968
client.add_success_response(b'stat', b'0', b'65535')
786
969
remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
788
bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
971
bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
790
973
repo = bzrdir.open_repository()
791
974
self.assertEqual(
792
[('call', 'BzrDir.find_repositoryV3', ('quack/',)),
793
('call', 'BzrDir.find_repositoryV2', ('quack/',)),
794
('call', 'BzrDir.find_repository', ('quack/',)),
795
('call_expecting_body', 'get', ('/quack/.bzr/branch-format',)),
796
('call_expecting_body', 'get', ('/quack/.bzr/repository/format',)),
797
('call', 'stat', ('/quack/.bzr/repository',)),
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',)),
800
984
self.assertEqual(network_name, repo._format.network_name())
806
990
server_url = 'bzr://example.com/'
807
991
self.permit_url(server_url)
808
992
client = FakeClient(server_url)
809
client.add_unknown_method_response('BzrDir.find_repositoryV3')
810
client.add_success_response('ok', '', 'no', 'no', 'no')
993
client.add_unknown_method_response(b'BzrDir.find_repositoryV3')
994
client.add_success_response(b'ok', b'', b'no', b'no', b'no')
811
995
# A real repository instance will be created to determine the network
813
997
client.add_success_response_with_body(
814
"Bazaar-NG meta directory, format 1\n", 'ok')
998
b"Bazaar-NG meta directory, format 1\n", b'ok')
999
client.add_success_response(b'stat', b'0', b'65535')
815
1000
client.add_success_response_with_body(
816
reference_format.get_format_string(), 'ok')
1001
reference_format.get_format_string(), b'ok')
817
1002
# PackRepository wants to do a stat
818
client.add_success_response('stat', '0', '65535')
1003
client.add_success_response(b'stat', b'0', b'65535')
819
1004
remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
821
bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
1006
bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
823
1008
repo = bzrdir.open_repository()
824
1009
self.assertEqual(
825
[('call', 'BzrDir.find_repositoryV3', ('quack/',)),
826
('call', 'BzrDir.find_repositoryV2', ('quack/',)),
827
('call_expecting_body', 'get', ('/quack/.bzr/branch-format',)),
828
('call_expecting_body', 'get', ('/quack/.bzr/repository/format',)),
829
('call', 'stat', ('/quack/.bzr/repository',)),
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',)),
832
1019
self.assertEqual(network_name, repo._format.network_name())
853
1041
def test_success(self):
854
1042
"""Simple test for typical successful call."""
855
fmt = bzrdir.RemoteBzrDirFormat()
1043
fmt = RemoteBzrDirFormat()
856
1044
default_format_name = BzrDirFormat.get_default_format().network_name()
857
1045
transport = self.get_transport()
858
1046
client = FakeClient(transport.base)
859
1047
client.add_expected_call(
860
'BzrDirFormat.initialize_ex_1.16',
861
(default_format_name, 'path', 'False', 'False', 'False', '',
862
'', '', '', 'False'),
864
('.', 'no', 'no', 'yes', 'repo fmt', 'repo bzrdir fmt',
865
'bzrdir fmt', 'False', '', '', 'repo lock token'))
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'))
866
1054
# XXX: It would be better to call fmt.initialize_on_transport_ex, but
867
1055
# it's currently hard to test that without supplying a real remote
868
1056
# transport connected to a real server.
869
result = fmt._initialize_on_transport_ex_rpc(client, 'path',
870
transport, False, False, False, None, None, None, None, False)
1057
fmt._initialize_on_transport_ex_rpc(
1058
client, b'path', transport, False, False, False, None, None, None,
871
1060
self.assertFinished(client)
873
1062
def test_error(self):
874
1063
"""Error responses are translated, e.g. 'PermissionDenied' raises the
875
1064
corresponding error from the client.
877
fmt = bzrdir.RemoteBzrDirFormat()
1066
fmt = RemoteBzrDirFormat()
878
1067
default_format_name = BzrDirFormat.get_default_format().network_name()
879
1068
transport = self.get_transport()
880
1069
client = FakeClient(transport.base)
881
1070
client.add_expected_call(
882
'BzrDirFormat.initialize_ex_1.16',
883
(default_format_name, 'path', 'False', 'False', 'False', '',
884
'', '', '', 'False'),
886
('PermissionDenied', 'path', 'extra info'))
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'))
887
1076
# XXX: It would be better to call fmt.initialize_on_transport_ex, but
888
1077
# it's currently hard to test that without supplying a real remote
889
1078
# transport connected to a real server.
890
err = self.assertRaises(errors.PermissionDenied,
891
fmt._initialize_on_transport_ex_rpc, client, 'path', transport,
1079
err = self.assertRaises(
1080
errors.PermissionDenied,
1081
fmt._initialize_on_transport_ex_rpc, client, b'path', transport,
892
1082
False, False, False, None, None, None, None, False)
893
1083
self.assertEqual('path', err.path)
894
1084
self.assertEqual(': extra info', err.extra)
1101
1345
transport = MemoryTransport()
1102
1346
client = FakeClient(transport.base)
1103
1347
client.add_expected_call(
1104
'Branch.get_stacked_on_url', ('quack/',),
1105
'error', ('NotStacked',))
1348
b'Branch.get_stacked_on_url', (b'quack/',),
1349
b'error', (b'NotStacked',))
1106
1350
client.add_expected_call(
1107
'Branch.set_tags_bytes', ('quack/', 'branch token', 'repo token'),
1351
b'Branch.set_tags_bytes', (b'quack/',
1352
b'branch token', b'repo token'),
1109
1354
transport.mkdir('quack')
1110
1355
transport = transport.clone('quack')
1111
1356
branch = self.make_remote_branch(transport, client)
1112
1357
self.lock_remote_branch(branch)
1113
branch._set_tags_bytes('tags bytes')
1358
branch._set_tags_bytes(b'tags bytes')
1114
1359
self.assertFinished(client)
1115
self.assertEqual('tags bytes', client._calls[-1][-1])
1360
self.assertEqual(b'tags bytes', client._calls[-1][-1])
1117
1362
def test_backwards_compatible(self):
1118
1363
transport = MemoryTransport()
1119
1364
client = FakeClient(transport.base)
1120
1365
client.add_expected_call(
1121
'Branch.get_stacked_on_url', ('quack/',),
1122
'error', ('NotStacked',))
1366
b'Branch.get_stacked_on_url', (b'quack/',),
1367
b'error', (b'NotStacked',))
1123
1368
client.add_expected_call(
1124
'Branch.set_tags_bytes', ('quack/', 'branch token', 'repo token'),
1125
'unknown', ('Branch.set_tags_bytes',))
1369
b'Branch.set_tags_bytes', (b'quack/',
1370
b'branch token', b'repo token'),
1371
b'unknown', (b'Branch.set_tags_bytes',))
1126
1372
transport.mkdir('quack')
1127
1373
transport = transport.clone('quack')
1128
1374
branch = self.make_remote_branch(transport, client)
1129
1375
self.lock_remote_branch(branch)
1130
1377
class StubRealBranch(object):
1131
1378
def __init__(self):
1132
1379
self.calls = []
1133
1381
def _set_tags_bytes(self, bytes):
1134
1382
self.calls.append(('set_tags_bytes', bytes))
1135
1383
real_branch = StubRealBranch()
1136
1384
branch._real_branch = real_branch
1137
branch._set_tags_bytes('tags bytes')
1385
branch._set_tags_bytes(b'tags bytes')
1138
1386
# Call a second time, to exercise the 'remote version already inferred'
1140
branch._set_tags_bytes('tags bytes')
1141
self.assertFinished(client)
1143
[('set_tags_bytes', 'tags bytes')] * 2, real_branch.calls)
1388
branch._set_tags_bytes(b'tags bytes')
1389
self.assertFinished(client)
1391
[('set_tags_bytes', b'tags bytes')] * 2, real_branch.calls)
1394
class TestBranchHeadsToFetch(RemoteBranchTestCase):
1396
def test_uses_last_revision_info_and_tags_by_default(self):
1397
transport = MemoryTransport()
1398
client = FakeClient(transport.base)
1399
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'')
1408
transport.mkdir('quack')
1409
transport = transport.clone('quack')
1410
branch = self.make_remote_branch(transport, client)
1411
result = branch.heads_to_fetch()
1412
self.assertFinished(client)
1413
self.assertEqual(({b'rev-tip'}, set()), result)
1415
def test_uses_last_revision_info_and_tags_when_set(self):
1416
transport = MemoryTransport()
1417
client = FakeClient(transport.base)
1418
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')
1427
# XXX: this will break if the default format's serialization of tags
1428
# changes, or if the RPC for fetching tags changes from get_tags_bytes.
1429
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',))
1432
transport.mkdir('quack')
1433
transport = transport.clone('quack')
1434
branch = self.make_remote_branch(transport, client)
1435
result = branch.heads_to_fetch()
1436
self.assertFinished(client)
1438
({b'rev-tip'}, {b'rev-foo', b'rev-bar'}), result)
1440
def test_uses_rpc_for_formats_with_non_default_heads_to_fetch(self):
1441
transport = MemoryTransport()
1442
client = FakeClient(transport.base)
1443
client.add_expected_call(
1444
b'Branch.get_stacked_on_url', (b'quack/',),
1445
b'error', (b'NotStacked',))
1446
client.add_expected_call(
1447
b'Branch.heads_to_fetch', (b'quack/',),
1448
b'success', ([b'tip'], [b'tagged-1', b'tagged-2']))
1449
transport.mkdir('quack')
1450
transport = transport.clone('quack')
1451
branch = self.make_remote_branch(transport, client)
1452
branch._format._use_default_local_heads_to_fetch = lambda: False
1453
result = branch.heads_to_fetch()
1454
self.assertFinished(client)
1455
self.assertEqual(({b'tip'}, {b'tagged-1', b'tagged-2'}), result)
1457
def make_branch_with_tags(self):
1458
self.setup_smart_server_with_call_log()
1459
# Make a branch with a single revision.
1460
builder = self.make_branch_builder('foo')
1461
builder.start_series()
1462
builder.build_snapshot(None, [
1463
('add', ('', b'root-id', 'directory', ''))],
1465
builder.finish_series()
1466
branch = builder.get_branch()
1467
# 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')
1472
def test_backwards_compatible(self):
1473
br = self.make_branch_with_tags()
1474
br.get_config_stack().set('branch.fetch_tags', True)
1475
self.addCleanup(br.lock_read().unlock)
1476
# Disable the heads_to_fetch verb
1477
verb = b'Branch.heads_to_fetch'
1478
self.disable_verb(verb)
1479
self.reset_smart_call_log()
1480
result = br.heads_to_fetch()
1481
self.assertEqual(({b'tip'}, {b'rev-1', b'rev-2'}), result)
1483
[b'Branch.last_revision_info', b'Branch.get_tags_bytes'],
1484
[call.call.method for call in self.hpss_calls])
1486
def test_backwards_compatible_no_tags(self):
1487
br = self.make_branch_with_tags()
1488
br.get_config_stack().set('branch.fetch_tags', False)
1489
self.addCleanup(br.lock_read().unlock)
1490
# Disable the heads_to_fetch verb
1491
verb = b'Branch.heads_to_fetch'
1492
self.disable_verb(verb)
1493
self.reset_smart_call_log()
1494
result = br.heads_to_fetch()
1495
self.assertEqual(({b'tip'}, set()), result)
1497
[b'Branch.last_revision_info'],
1498
[call.call.method for call in self.hpss_calls])
1146
1501
class TestBranchLastRevisionInfo(RemoteBranchTestCase):
1190
1545
# doesn't just open in - this test probably needs to be rewritten using
1191
1546
# a spawn()ed server.
1192
1547
stacked_branch = self.make_branch('stacked', format='1.9')
1193
memory_branch = self.make_branch('base', format='1.9')
1548
self.make_branch('base', format='1.9')
1194
1549
vfs_url = self.get_vfs_only_url('base')
1195
1550
stacked_branch.set_stacked_on_url(vfs_url)
1196
transport = stacked_branch.bzrdir.root_transport
1551
transport = stacked_branch.controldir.root_transport
1197
1552
client = FakeClient(transport.base)
1198
1553
client.add_expected_call(
1199
'Branch.get_stacked_on_url', ('stacked/',),
1200
'success', ('ok', vfs_url))
1554
b'Branch.get_stacked_on_url', (b'stacked/',),
1555
b'success', (b'ok', vfs_url.encode('utf-8')))
1201
1556
# XXX: Multiple calls are bad, this second call documents what is
1203
1558
client.add_expected_call(
1204
'Branch.get_stacked_on_url', ('stacked/',),
1205
'success', ('ok', vfs_url))
1206
bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1559
b'Branch.get_stacked_on_url', (b'stacked/',),
1560
b'success', (b'ok', vfs_url.encode('utf-8')))
1561
bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1208
1563
repo_fmt = remote.RemoteRepositoryFormat()
1209
1564
repo_fmt._custom_format = stacked_branch.repository._format
1210
1565
branch = RemoteBranch(bzrdir, RemoteRepository(bzrdir, repo_fmt),
1212
1567
result = branch.get_stacked_on_url()
1213
1568
self.assertEqual(vfs_url, result)
1215
1570
def test_backwards_compatible(self):
1216
1571
# like with bzr1.6 with no Branch.get_stacked_on_url rpc
1217
base_branch = self.make_branch('base', format='1.6')
1572
self.make_branch('base', format='1.6')
1218
1573
stacked_branch = self.make_branch('stacked', format='1.6')
1219
1574
stacked_branch.set_stacked_on_url('../base')
1220
1575
client = FakeClient(self.get_url())
1221
1576
branch_network_name = self.get_branch_format().network_name()
1222
1577
client.add_expected_call(
1223
'BzrDir.open_branchV3', ('stacked/',),
1224
'success', ('branch', branch_network_name))
1578
b'BzrDir.open_branchV3', (b'stacked/',),
1579
b'success', (b'branch', branch_network_name))
1225
1580
client.add_expected_call(
1226
'BzrDir.find_repositoryV3', ('stacked/',),
1227
'success', ('ok', '', 'no', 'no', 'yes',
1228
stacked_branch.repository._format.network_name()))
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()))
1229
1584
# called twice, once from constructor and then again by us
1230
1585
client.add_expected_call(
1231
'Branch.get_stacked_on_url', ('stacked/',),
1232
'unknown', ('Branch.get_stacked_on_url',))
1586
b'Branch.get_stacked_on_url', (b'stacked/',),
1587
b'unknown', (b'Branch.get_stacked_on_url',))
1233
1588
client.add_expected_call(
1234
'Branch.get_stacked_on_url', ('stacked/',),
1235
'unknown', ('Branch.get_stacked_on_url',))
1589
b'Branch.get_stacked_on_url', (b'stacked/',),
1590
b'unknown', (b'Branch.get_stacked_on_url',))
1236
1591
# this will also do vfs access, but that goes direct to the transport
1237
1592
# and isn't seen by the FakeClient.
1238
1593
bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1239
remote.RemoteBzrDirFormat(), _client=client)
1594
RemoteBzrDirFormat(), _client=client)
1240
1595
branch = bzrdir.open_branch()
1241
1596
result = branch.get_stacked_on_url()
1242
1597
self.assertEqual('../base', result)
1292
1647
client = FakeClient(transport.base)
1293
1648
client.add_expected_call(
1294
'Branch.get_stacked_on_url', ('branch/',),
1295
'error', ('NotStacked',))
1296
client.add_expected_call(
1297
'Branch.lock_write', ('branch/', '', ''),
1298
'success', ('ok', 'branch token', 'repo token'))
1299
client.add_expected_call(
1300
'Branch.last_revision_info',
1302
'success', ('ok', '0', 'null:'))
1303
client.add_expected_call(
1304
'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'null:',),
1306
client.add_expected_call(
1307
'Branch.unlock', ('branch/', 'branch token', 'repo token'),
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',))
1309
1665
branch = self.make_remote_branch(transport, client)
1310
# This is a hack to work around the problem that RemoteBranch currently
1311
# unnecessarily invokes _ensure_real upon a call to lock_write.
1312
branch._ensure_real = lambda: None
1313
1666
branch.lock_write()
1314
result = branch.set_revision_history([])
1667
result = branch._set_last_revision(NULL_REVISION)
1315
1668
branch.unlock()
1316
1669
self.assertEqual(None, result)
1317
1670
self.assertFinished(client)
1319
1672
def test_set_nonempty(self):
1320
# set_revision_history([rev-id1, ..., rev-idN]) is translated to calling
1673
# set_last_revision_info(N, rev-idN) is translated to calling
1321
1674
# Branch.set_last_revision(path, rev-idN) on the wire.
1322
1675
transport = MemoryTransport()
1323
1676
transport.mkdir('branch')
1326
1679
client = FakeClient(transport.base)
1327
1680
client.add_expected_call(
1328
'Branch.get_stacked_on_url', ('branch/',),
1329
'error', ('NotStacked',))
1330
client.add_expected_call(
1331
'Branch.lock_write', ('branch/', '', ''),
1332
'success', ('ok', 'branch token', 'repo token'))
1333
client.add_expected_call(
1334
'Branch.last_revision_info',
1336
'success', ('ok', '0', 'null:'))
1338
encoded_body = bz2.compress('\n'.join(lines))
1339
client.add_success_response_with_body(encoded_body, 'ok')
1340
client.add_expected_call(
1341
'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'rev-id2',),
1343
client.add_expected_call(
1344
'Branch.unlock', ('branch/', 'branch token', 'repo token'),
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',))
1346
1700
branch = self.make_remote_branch(transport, client)
1347
# This is a hack to work around the problem that RemoteBranch currently
1348
# unnecessarily invokes _ensure_real upon a call to lock_write.
1349
branch._ensure_real = lambda: None
1350
1701
# Lock the branch, reset the record of remote calls.
1351
1702
branch.lock_write()
1352
result = branch.set_revision_history(['rev-id1', 'rev-id2'])
1703
result = branch._set_last_revision(b'rev-id2')
1353
1704
branch.unlock()
1354
1705
self.assertEqual(None, result)
1355
1706
self.assertFinished(client)
1361
1712
# A response of 'NoSuchRevision' is translated into an exception.
1362
1713
client = FakeClient(transport.base)
1363
1714
client.add_expected_call(
1364
'Branch.get_stacked_on_url', ('branch/',),
1365
'error', ('NotStacked',))
1366
client.add_expected_call(
1367
'Branch.lock_write', ('branch/', '', ''),
1368
'success', ('ok', 'branch token', 'repo token'))
1369
client.add_expected_call(
1370
'Branch.last_revision_info',
1372
'success', ('ok', '0', 'null:'))
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:'))
1373
1724
# get_graph calls to construct the revision history, for the set_rh
1376
encoded_body = bz2.compress('\n'.join(lines))
1377
client.add_success_response_with_body(encoded_body, 'ok')
1378
client.add_expected_call(
1379
'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'rev-id',),
1380
'error', ('NoSuchRevision', 'rev-id'))
1381
client.add_expected_call(
1382
'Branch.unlock', ('branch/', 'branch token', 'repo token'),
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',))
1385
1737
branch = self.make_remote_branch(transport, client)
1386
1738
branch.lock_write()
1387
1739
self.assertRaises(
1388
errors.NoSuchRevision, branch.set_revision_history, ['rev-id'])
1740
errors.NoSuchRevision, branch._set_last_revision, b'rev-id')
1389
1741
branch.unlock()
1390
1742
self.assertFinished(client)
1400
1752
rejection_msg_unicode = u'rejection message\N{INTERROBANG}'
1401
1753
rejection_msg_utf8 = rejection_msg_unicode.encode('utf8')
1402
1754
client.add_expected_call(
1403
'Branch.get_stacked_on_url', ('branch/',),
1404
'error', ('NotStacked',))
1405
client.add_expected_call(
1406
'Branch.lock_write', ('branch/', '', ''),
1407
'success', ('ok', 'branch token', 'repo token'))
1408
client.add_expected_call(
1409
'Branch.last_revision_info',
1411
'success', ('ok', '0', 'null:'))
1413
encoded_body = bz2.compress('\n'.join(lines))
1414
client.add_success_response_with_body(encoded_body, 'ok')
1415
client.add_expected_call(
1416
'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'rev-id',),
1417
'error', ('TipChangeRejected', rejection_msg_utf8))
1418
client.add_expected_call(
1419
'Branch.unlock', ('branch/', 'branch token', 'repo token'),
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',))
1421
1774
branch = self.make_remote_branch(transport, client)
1422
branch._ensure_real = lambda: None
1423
1775
branch.lock_write()
1424
1776
# The 'TipChangeRejected' error response triggered by calling
1425
# set_revision_history causes a TipChangeRejected exception.
1777
# set_last_revision_info causes a TipChangeRejected exception.
1426
1778
err = self.assertRaises(
1427
errors.TipChangeRejected, branch.set_revision_history, ['rev-id'])
1779
errors.TipChangeRejected,
1780
branch._set_last_revision, b'rev-id')
1428
1781
# The UTF-8 message from the response has been decoded into a unicode
1430
self.assertIsInstance(err.msg, unicode)
1783
self.assertIsInstance(err.msg, str)
1431
1784
self.assertEqual(rejection_msg_unicode, err.msg)
1432
1785
branch.unlock()
1433
1786
self.assertFinished(client)
1652
2008
branch.unlock()
1653
2009
self.assertFinished(client)
2011
def test_set_option_with_dict(self):
2012
client = FakeClient()
2013
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',))
2027
transport = MemoryTransport()
2028
branch = self.make_remote_branch(transport, client)
2030
config = branch._get_config()
2032
{'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'},
2035
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)
1655
2060
def test_backwards_compat_set_option(self):
1656
2061
self.setup_smart_server_with_call_log()
1657
2062
branch = self.make_branch('.')
1658
verb = 'Branch.set_config_option'
2063
verb = b'Branch.set_config_option'
1659
2064
self.disable_verb(verb)
1660
2065
branch.lock_write()
1661
2066
self.addCleanup(branch.unlock)
1662
2067
self.reset_smart_call_log()
1663
2068
branch._get_config().set_option('value', 'name')
1664
self.assertLength(10, self.hpss_calls)
2069
self.assertLength(11, self.hpss_calls)
1665
2070
self.assertEqual('value', branch._get_config().get_option('name'))
2072
def test_backwards_compat_set_option_with_dict(self):
2073
self.setup_smart_server_with_call_log()
2074
branch = self.make_branch('.')
2075
verb = b'Branch.set_config_option_dict'
2076
self.disable_verb(verb)
2078
self.addCleanup(branch.unlock)
2079
self.reset_smart_call_log()
2080
config = branch._get_config()
2081
value_dict = {'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'}
2082
config.set_option(value_dict, 'name')
2083
self.assertLength(11, self.hpss_calls)
2084
self.assertEqual(value_dict, branch._get_config().get_option('name'))
2087
class TestBranchGetPutConfigStore(RemoteBranchTestCase):
2089
def test_get_branch_conf(self):
2090
# in an empty branch we decode the response properly
2091
client = FakeClient()
2092
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')
2096
transport = MemoryTransport()
2097
branch = self.make_remote_branch(transport, client)
2098
config = branch.get_config_stack()
2100
config.get("log_format")
2102
[('call', b'Branch.get_stacked_on_url', (b'memory:///',)),
2103
('call_expecting_body', b'Branch.get_config_file', (b'memory:///',))],
2106
def test_set_branch_conf(self):
2107
client = FakeClient()
2108
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',))
2127
transport = MemoryTransport()
2128
branch = self.make_remote_branch(transport, client)
2130
config = branch.get_config_stack()
2131
config.set('email', 'The Dude <lebowski@example.com>')
2133
self.assertFinished(client)
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'))],
1668
2149
class TestBranchLockWrite(RemoteBranchTestCase):
1683
2164
self.assertFinished(client)
2167
class TestBranchRevisionIdToRevno(RemoteBranchTestCase):
2169
def test_simple(self):
2170
transport = MemoryTransport()
2171
client = FakeClient(transport.base)
2172
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',),)
2181
transport.mkdir('quack')
2182
transport = transport.clone('quack')
2183
branch = self.make_remote_branch(transport, client)
2184
self.assertEqual(0, branch.revision_id_to_revno(b'null:'))
2185
self.assertRaises(errors.NoSuchRevision,
2186
branch.revision_id_to_revno, b'unknown')
2187
self.assertFinished(client)
2189
def test_dotted(self):
2190
transport = MemoryTransport()
2191
client = FakeClient(transport.base)
2192
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',),)
2201
transport.mkdir('quack')
2202
transport = transport.clone('quack')
2203
branch = self.make_remote_branch(transport, client)
2204
self.assertEqual((0, ), branch.revision_id_to_dotted_revno(b'null:'))
2205
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')
2232
self.assertFinished(client)
2234
def test_dotted_no_smart_verb(self):
2235
self.setup_smart_server_with_call_log()
2236
branch = self.make_branch('.')
2237
self.disable_verb(b'Branch.revision_id_to_revno')
2238
self.reset_smart_call_log()
2239
self.assertEqual((0, ),
2240
branch.revision_id_to_dotted_revno(b'null:'))
2241
self.assertLength(8, self.hpss_calls)
1686
2244
class TestBzrDirGetSetConfig(RemoteBzrDirTestCase):
1688
2246
def test__get_config(self):
1689
2247
client = FakeClient()
1690
client.add_success_response_with_body('default_stack_on = /\n', 'ok')
2248
client.add_success_response_with_body(b'default_stack_on = /\n', b'ok')
1691
2249
transport = MemoryTransport()
1692
2250
bzrdir = self.make_remote_bzrdir(transport, client)
1693
2251
config = bzrdir.get_config()
1694
2252
self.assertEqual('/', config.get_default_stack_on())
1695
2253
self.assertEqual(
1696
[('call_expecting_body', 'BzrDir.get_config_file', ('memory:///',))],
2254
[('call_expecting_body', b'BzrDir.get_config_file',
1699
2258
def test_set_option_uses_vfs(self):
1700
2259
self.setup_smart_server_with_call_log()
1701
bzrdir = self.make_bzrdir('.')
2260
bzrdir = self.make_controldir('.')
1702
2261
self.reset_smart_call_log()
1703
2262
config = bzrdir.get_config()
1704
2263
config.set_default_stack_on('/')
1705
self.assertLength(3, self.hpss_calls)
2264
self.assertLength(4, self.hpss_calls)
1707
2266
def test_backwards_compat_get_option(self):
1708
2267
self.setup_smart_server_with_call_log()
1709
bzrdir = self.make_bzrdir('.')
1710
verb = 'BzrDir.get_config_file'
2268
bzrdir = self.make_controldir('.')
2269
verb = b'BzrDir.get_config_file'
1711
2270
self.disable_verb(verb)
1712
2271
self.reset_smart_call_log()
1713
2272
self.assertEqual(None,
1714
bzrdir._get_config().get_option('default_stack_on'))
1715
self.assertLength(3, self.hpss_calls)
2273
bzrdir._get_config().get_option('default_stack_on'))
2274
self.assertLength(4, self.hpss_calls)
1718
2277
class TestTransportIsReadonly(tests.TestCase):
1720
2279
def test_true(self):
1721
2280
client = FakeClient()
1722
client.add_success_response('yes')
2281
client.add_success_response(b'yes')
1723
2282
transport = RemoteTransport('bzr://example.com/', medium=False,
1724
2283
_client=client)
1725
2284
self.assertEqual(True, transport.is_readonly())
1726
2285
self.assertEqual(
1727
[('call', 'Transport.is_readonly', ())],
2286
[('call', b'Transport.is_readonly', ())],
1730
2289
def test_false(self):
1731
2290
client = FakeClient()
1732
client.add_success_response('no')
2291
client.add_success_response(b'no')
1733
2292
transport = RemoteTransport('bzr://example.com/', medium=False,
1734
2293
_client=client)
1735
2294
self.assertEqual(False, transport.is_readonly())
1736
2295
self.assertEqual(
1737
[('call', 'Transport.is_readonly', ())],
2296
[('call', b'Transport.is_readonly', ())],
1740
2299
def test_error_from_old_server(self):
1852
2438
transport_path = 'quack'
1853
2439
repo, client = self.setup_fake_client_and_repository(transport_path)
1854
2440
client.add_success_response_with_body(
1855
'revisions: 2\nsize: 18\n', 'ok')
2441
b'revisions: 2\nsize: 18\n', b'ok')
1856
2442
result = repo.gather_stats(None)
1857
2443
self.assertEqual(
1858
[('call_expecting_body', 'Repository.gather_stats',
1859
('quack/','','no'))],
2444
[('call_expecting_body', b'Repository.gather_stats',
2445
(b'quack/', b'', b'no'))],
1861
2447
self.assertEqual({'revisions': 2, 'size': 18}, result)
1863
2449
def test_revid_no_committers(self):
1864
2450
# ('ok',), body without committers
1865
body = ('firstrev: 123456.300 3600\n'
1866
'latestrev: 654231.400 0\n'
2451
body = (b'firstrev: 123456.300 3600\n'
2452
b'latestrev: 654231.400 0\n'
1869
2455
transport_path = 'quick'
1870
2456
revid = u'\xc8'.encode('utf8')
1871
2457
repo, client = self.setup_fake_client_and_repository(transport_path)
1872
client.add_success_response_with_body(body, 'ok')
2458
client.add_success_response_with_body(body, b'ok')
1873
2459
result = repo.gather_stats(revid)
1874
2460
self.assertEqual(
1875
[('call_expecting_body', 'Repository.gather_stats',
1876
('quick/', revid, 'no'))],
2461
[('call_expecting_body', b'Repository.gather_stats',
2462
(b'quick/', revid, b'no'))],
1878
2464
self.assertEqual({'revisions': 2, 'size': 18,
1879
2465
'firstrev': (123456.300, 3600),
1880
'latestrev': (654231.400, 0),},
2466
'latestrev': (654231.400, 0), },
1883
2469
def test_revid_with_committers(self):
1884
2470
# ('ok',), body with committers
1885
body = ('committers: 128\n'
1886
'firstrev: 123456.300 3600\n'
1887
'latestrev: 654231.400 0\n'
2471
body = (b'committers: 128\n'
2472
b'firstrev: 123456.300 3600\n'
2473
b'latestrev: 654231.400 0\n'
1890
2476
transport_path = 'buick'
1891
2477
revid = u'\xc8'.encode('utf8')
1892
2478
repo, client = self.setup_fake_client_and_repository(transport_path)
1893
client.add_success_response_with_body(body, 'ok')
2479
client.add_success_response_with_body(body, b'ok')
1894
2480
result = repo.gather_stats(revid, True)
1895
2481
self.assertEqual(
1896
[('call_expecting_body', 'Repository.gather_stats',
1897
('buick/', revid, 'yes'))],
2482
[('call_expecting_body', b'Repository.gather_stats',
2483
(b'buick/', revid, b'yes'))],
1899
2485
self.assertEqual({'revisions': 2, 'size': 18,
1900
2486
'committers': 128,
1901
2487
'firstrev': (123456.300, 3600),
1902
'latestrev': (654231.400, 0),},
2488
'latestrev': (654231.400, 0), },
2492
class TestRepositoryBreakLock(TestRemoteRepository):
2494
def test_break_lock(self):
2495
transport_path = 'quack'
2496
repo, client = self.setup_fake_client_and_repository(transport_path)
2497
client.add_success_response(b'ok')
2500
[('call', b'Repository.break_lock', (b'quack/',))],
2504
class TestRepositoryGetSerializerFormat(TestRemoteRepository):
2506
def test_get_serializer_format(self):
2507
transport_path = 'hill'
2508
repo, client = self.setup_fake_client_and_repository(transport_path)
2509
client.add_success_response(b'ok', b'7')
2510
self.assertEqual(b'7', repo.get_serializer_format())
2512
[('call', b'VersionedFileRepository.get_serializer_format',
2517
class TestRepositoryReconcile(TestRemoteRepository):
2519
def test_reconcile(self):
2520
transport_path = 'hill'
2521
repo, client = self.setup_fake_client_and_repository(transport_path)
2522
body = (b"garbage_inventories: 2\n"
2523
b"inconsistent_parents: 3\n")
2524
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')
2528
reconciler = repo.reconcile()
2530
[('call', b'Repository.lock_write', (b'hill/', b'')),
2531
('call_expecting_body', b'Repository.reconcile',
2532
(b'hill/', b'a token'))],
2534
self.assertEqual(2, reconciler.garbage_inventories)
2535
self.assertEqual(3, reconciler.inconsistent_parents)
2538
class TestRepositoryGetRevisionSignatureText(TestRemoteRepository):
2540
def test_text(self):
2541
# ('ok',), body with signature text
2542
transport_path = 'quack'
2543
repo, client = self.setup_fake_client_and_repository(transport_path)
2544
client.add_success_response_with_body(
2546
self.assertEqual(b"THETEXT", repo.get_signature_text(b"revid"))
2548
[('call_expecting_body', b'Repository.get_revision_signature_text',
2549
(b'quack/', b'revid'))],
2552
def test_no_signature(self):
2553
transport_path = 'quick'
2554
repo, client = self.setup_fake_client_and_repository(transport_path)
2555
client.add_error_response(b'nosuchrevision', b'unknown')
2556
self.assertRaises(errors.NoSuchRevision, repo.get_signature_text,
2559
[('call_expecting_body', b'Repository.get_revision_signature_text',
2560
(b'quick/', b'unknown'))],
1906
2564
class TestRepositoryGetGraph(TestRemoteRepository):
1908
2566
def test_get_graph(self):
2257
3041
self.setup_smart_server_with_call_log()
2258
3042
tree = self.make_branch_and_memory_tree('.')
2259
3043
tree.lock_write()
2260
3045
rev1 = tree.commit('First')
2261
rev2 = tree.commit('Second')
3046
tree.commit('Second')
2263
3048
branch = tree.branch
2264
3049
self.assertFalse(branch.is_locked())
2265
3050
self.reset_smart_call_log()
2266
verb = 'Repository.get_rev_id_for_revno'
3051
verb = b'Repository.get_rev_id_for_revno'
2267
3052
self.disable_verb(verb)
2268
3053
self.assertEqual(rev1, branch.get_rev_id(1))
2269
3054
self.assertLength(1, [call for call in self.hpss_calls if
2270
3055
call.call.method == verb])
3058
class TestRepositoryHasSignatureForRevisionId(TestRemoteRepository):
3060
def test_has_signature_for_revision_id(self):
3061
# ('yes', ) for Repository.has_signature_for_revision_id -> 'True'.
3062
transport_path = 'quack'
3063
repo, client = self.setup_fake_client_and_repository(transport_path)
3064
client.add_success_response(b'yes')
3065
result = repo.has_signature_for_revision_id(b'A')
3067
[('call', b'Repository.has_signature_for_revision_id',
3068
(b'quack/', b'A'))],
3070
self.assertEqual(True, result)
3072
def test_is_not_shared(self):
3073
# ('no', ) for Repository.has_signature_for_revision_id -> 'False'.
3074
transport_path = 'qwack'
3075
repo, client = self.setup_fake_client_and_repository(transport_path)
3076
client.add_success_response(b'no')
3077
result = repo.has_signature_for_revision_id(b'A')
3079
[('call', b'Repository.has_signature_for_revision_id',
3080
(b'qwack/', b'A'))],
3082
self.assertEqual(False, result)
3085
class TestRepositoryPhysicalLockStatus(TestRemoteRepository):
3087
def test_get_physical_lock_status_yes(self):
3088
transport_path = 'qwack'
3089
repo, client = self.setup_fake_client_and_repository(transport_path)
3090
client.add_success_response(b'yes')
3091
result = repo.get_physical_lock_status()
3093
[('call', b'Repository.get_physical_lock_status',
3096
self.assertEqual(True, result)
3098
def test_get_physical_lock_status_no(self):
3099
transport_path = 'qwack'
3100
repo, client = self.setup_fake_client_and_repository(transport_path)
3101
client.add_success_response(b'no')
3102
result = repo.get_physical_lock_status()
3104
[('call', b'Repository.get_physical_lock_status',
3107
self.assertEqual(False, result)
2273
3110
class TestRepositoryIsShared(TestRemoteRepository):
2275
3112
def test_is_shared(self):
2276
3113
# ('yes', ) for Repository.is_shared -> 'True'.
2277
3114
transport_path = 'quack'
2278
3115
repo, client = self.setup_fake_client_and_repository(transport_path)
2279
client.add_success_response('yes')
3116
client.add_success_response(b'yes')
2280
3117
result = repo.is_shared()
2281
3118
self.assertEqual(
2282
[('call', 'Repository.is_shared', ('quack/',))],
3119
[('call', b'Repository.is_shared', (b'quack/',))],
2284
3121
self.assertEqual(True, result)
2300
3162
def test_lock_write(self):
2301
3163
transport_path = 'quack'
2302
3164
repo, client = self.setup_fake_client_and_repository(transport_path)
2303
client.add_success_response('ok', 'a token')
3165
client.add_success_response(b'ok', b'a token')
2304
3166
token = repo.lock_write().repository_token
2305
3167
self.assertEqual(
2306
[('call', 'Repository.lock_write', ('quack/', ''))],
3168
[('call', b'Repository.lock_write', (b'quack/', b''))],
2308
self.assertEqual('a token', token)
3170
self.assertEqual(b'a token', token)
2310
3172
def test_lock_write_already_locked(self):
2311
3173
transport_path = 'quack'
2312
3174
repo, client = self.setup_fake_client_and_repository(transport_path)
2313
client.add_error_response('LockContention')
3175
client.add_error_response(b'LockContention')
2314
3176
self.assertRaises(errors.LockContention, repo.lock_write)
2315
3177
self.assertEqual(
2316
[('call', 'Repository.lock_write', ('quack/', ''))],
3178
[('call', b'Repository.lock_write', (b'quack/', b''))],
2319
3181
def test_lock_write_unlockable(self):
2320
3182
transport_path = 'quack'
2321
3183
repo, client = self.setup_fake_client_and_repository(transport_path)
2322
client.add_error_response('UnlockableTransport')
3184
client.add_error_response(b'UnlockableTransport')
2323
3185
self.assertRaises(errors.UnlockableTransport, repo.lock_write)
2324
3186
self.assertEqual(
2325
[('call', 'Repository.lock_write', ('quack/', ''))],
3187
[('call', b'Repository.lock_write', (b'quack/', b''))],
3191
class TestRepositoryWriteGroups(TestRemoteRepository):
3193
def test_start_write_group(self):
3194
transport_path = 'quack'
3195
repo, client = self.setup_fake_client_and_repository(transport_path)
3196
client.add_expected_call(
3197
b'Repository.lock_write', (b'quack/', b''),
3198
b'success', (b'ok', b'a token'))
3199
client.add_expected_call(
3200
b'Repository.start_write_group', (b'quack/', b'a token'),
3201
b'success', (b'ok', (b'token1', )))
3203
repo.start_write_group()
3205
def test_start_write_group_unsuspendable(self):
3206
# Some repositories do not support suspending write
3207
# groups. For those, fall back to the "real" repository.
3208
transport_path = 'quack'
3209
repo, client = self.setup_fake_client_and_repository(transport_path)
3211
def stub_ensure_real():
3212
client._calls.append(('_ensure_real',))
3213
repo._real_repository = _StubRealPackRepository(client._calls)
3214
repo._ensure_real = stub_ensure_real
3215
client.add_expected_call(
3216
b'Repository.lock_write', (b'quack/', b''),
3217
b'success', (b'ok', b'a token'))
3218
client.add_expected_call(
3219
b'Repository.start_write_group', (b'quack/', b'a token'),
3220
b'error', (b'UnsuspendableWriteGroup',))
3222
repo.start_write_group()
3223
self.assertEqual(client._calls[-2:], [
3225
('start_write_group',)])
3227
def test_commit_write_group(self):
3228
transport_path = 'quack'
3229
repo, client = self.setup_fake_client_and_repository(transport_path)
3230
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',))
3241
repo.start_write_group()
3242
repo.commit_write_group()
3244
def test_abort_write_group(self):
3245
transport_path = 'quack'
3246
repo, client = self.setup_fake_client_and_repository(transport_path)
3247
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',))
3258
repo.start_write_group()
3259
repo.abort_write_group(False)
3261
def test_suspend_write_group(self):
3262
transport_path = 'quack'
3263
repo, client = self.setup_fake_client_and_repository(transport_path)
3264
self.assertEqual([], repo.suspend_write_group())
3266
def test_resume_write_group(self):
3267
transport_path = 'quack'
3268
repo, client = self.setup_fake_client_and_repository(transport_path)
3269
client.add_expected_call(
3270
b'Repository.lock_write', (b'quack/', b''),
3271
b'success', (b'ok', b'a token'))
3272
client.add_expected_call(
3273
b'Repository.check_write_group', (b'quack/',
3274
b'a token', [b'token1']),
3275
b'success', (b'ok',))
3277
repo.resume_write_group(['token1'])
2329
3280
class TestRepositorySetMakeWorkingTrees(TestRemoteRepository):
2331
3282
def test_backwards_compat(self):
2332
3283
self.setup_smart_server_with_call_log()
2333
3284
repo = self.make_repository('.')
2334
3285
self.reset_smart_call_log()
2335
verb = 'Repository.set_make_working_trees'
3286
verb = b'Repository.set_make_working_trees'
2336
3287
self.disable_verb(verb)
2337
3288
repo.set_make_working_trees(True)
2338
3289
call_count = len([call for call in self.hpss_calls if
2339
call.call.method == verb])
3290
call.call.method == verb])
2340
3291
self.assertEqual(1, call_count)
2342
3293
def test_current(self):
2343
3294
transport_path = 'quack'
2344
3295
repo, client = self.setup_fake_client_and_repository(transport_path)
2345
3296
client.add_expected_call(
2346
'Repository.set_make_working_trees', ('quack/', 'True'),
3297
b'Repository.set_make_working_trees', (b'quack/', b'True'),
3298
b'success', (b'ok',))
2348
3299
client.add_expected_call(
2349
'Repository.set_make_working_trees', ('quack/', 'False'),
3300
b'Repository.set_make_working_trees', (b'quack/', b'False'),
3301
b'success', (b'ok',))
2351
3302
repo.set_make_working_trees(True)
2352
3303
repo.set_make_working_trees(False)
2419
3397
def setUp(self):
2420
TestRemoteRepository.setUp(self)
2421
self.disable_verb('Repository.insert_stream_1.19')
3398
super(TestRepositoryInsertStream, self).setUp()
3399
self.disable_verb(b'Repository.insert_stream_1.19')
2423
3401
def test_unlocked_repo(self):
2424
3402
transport_path = 'quack'
2425
3403
repo, client = self.setup_fake_client_and_repository(transport_path)
2426
3404
client.add_expected_call(
2427
'Repository.insert_stream_1.19', ('quack/', ''),
2428
'unknown', ('Repository.insert_stream_1.19',))
2429
client.add_expected_call(
2430
'Repository.insert_stream', ('quack/', ''),
2432
client.add_expected_call(
2433
'Repository.insert_stream', ('quack/', ''),
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',))
2435
3413
self.checkInsertEmptyStream(repo, client)
2437
3415
def test_locked_repo_with_no_lock_token(self):
2438
3416
transport_path = 'quack'
2439
3417
repo, client = self.setup_fake_client_and_repository(transport_path)
2440
3418
client.add_expected_call(
2441
'Repository.lock_write', ('quack/', ''),
2442
'success', ('ok', ''))
2443
client.add_expected_call(
2444
'Repository.insert_stream_1.19', ('quack/', ''),
2445
'unknown', ('Repository.insert_stream_1.19',))
2446
client.add_expected_call(
2447
'Repository.insert_stream', ('quack/', ''),
2449
client.add_expected_call(
2450
'Repository.insert_stream', ('quack/', ''),
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',))
2452
3430
repo.lock_write()
2453
3431
self.checkInsertEmptyStream(repo, client)
2479
3457
transport_path = 'quack'
2480
3458
repo, client = self.setup_fake_client_and_repository(transport_path)
2481
3459
client.add_expected_call(
2482
'Repository.insert_stream_1.19', ('quack/', ''),
2483
'unknown', ('Repository.insert_stream_1.19',))
2484
client.add_expected_call(
2485
'Repository.insert_stream', ('quack/', ''),
2487
client.add_expected_call(
2488
'Repository.insert_stream', ('quack/', ''),
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',))
2490
3468
# Create a fake real repository for insert_stream to fall back on, so
2491
3469
# that we can directly see the records the RemoteSink passes to the
2493
3472
class FakeRealSink:
2494
3473
def __init__(self):
2495
3474
self.records = []
2496
3476
def insert_stream(self, stream, src_format, resume_tokens):
2497
3477
for substream_kind, substream in stream:
2498
3478
self.records.append(
2499
3479
(substream_kind, [record.key for record in substream]))
2500
return ['fake tokens'], ['fake missing keys']
3480
return [b'fake tokens'], [b'fake missing keys']
2501
3481
fake_real_sink = FakeRealSink()
2502
3483
class FakeRealRepository:
2503
3484
def _get_sink(self):
2504
3485
return fake_real_sink
2505
3487
def is_in_write_group(self):
2507
3490
def refresh_data(self):
2509
3492
repo._real_repository = FakeRealRepository()
2510
3493
sink = repo._get_sink()
2511
fmt = repository.RepositoryFormat.get_default_format()
3494
fmt = repository.format_registry.get_default()
2512
3495
stream = self.make_stream_with_inv_deltas(fmt)
2513
3496
resume_tokens, missing_keys = sink.insert_stream(stream, fmt, [])
2514
3497
# Every record from the first inventory delta should have been sent to
2515
3498
# the VFS sink.
2516
3499
expected_records = [
2517
('inventory-deltas', [('rev2',), ('rev3',)]),
2518
('texts', [('some-rev', 'some-file')])]
3500
('inventory-deltas', [(b'rev2',), (b'rev3',)]),
3501
('texts', [(b'some-rev', b'some-file')])]
2519
3502
self.assertEqual(expected_records, fake_real_sink.records)
2520
3503
# The return values from the real sink's insert_stream are propagated
2521
3504
# back to the original caller.
2522
self.assertEqual(['fake tokens'], resume_tokens)
2523
self.assertEqual(['fake missing keys'], missing_keys)
3505
self.assertEqual([b'fake tokens'], resume_tokens)
3506
self.assertEqual([b'fake missing keys'], missing_keys)
2524
3507
self.assertFinished(client)
2526
3509
def make_stream_with_inv_deltas(self, fmt):
2534
3517
* texts substream: (some-rev, some-file)
2536
3519
# Define a stream using generators so that it isn't rewindable.
2537
inv = inventory.Inventory(revision_id='rev1')
2538
inv.root.revision = 'rev1'
3520
inv = inventory.Inventory(revision_id=b'rev1')
3521
inv.root.revision = b'rev1'
2539
3523
def stream_with_inv_delta():
2540
3524
yield ('inventories', inventories_substream())
2541
3525
yield ('inventory-deltas', inventory_delta_substream())
2542
3526
yield ('texts', [
2543
3527
versionedfile.FulltextContentFactory(
2544
('some-rev', 'some-file'), (), None, 'content')])
3528
(b'some-rev', b'some-file'), (), None, b'content')])
2545
3530
def inventories_substream():
2546
3531
# An empty inventory fulltext. This will be streamed normally.
2547
text = fmt._serializer.write_inventory_to_string(inv)
2548
yield versionedfile.FulltextContentFactory(
2549
('rev1',), (), None, text)
3532
chunks = fmt._serializer.write_inventory_to_lines(inv)
3533
yield versionedfile.ChunkedContentFactory(
3534
(b'rev1',), (), None, chunks, chunks_are_lines=True)
2550
3536
def inventory_delta_substream():
2551
3537
# An inventory delta. This can't be streamed via this verb, so it
2552
3538
# will trigger a fallback to VFS insert_stream.
2553
3539
entry = inv.make_entry(
2554
'directory', 'newdir', inv.root.file_id, 'newdir-id')
2555
entry.revision = 'ghost'
2556
delta = [(None, 'newdir', 'newdir-id', entry)]
3540
'directory', 'newdir', inv.root.file_id, b'newdir-id')
3541
entry.revision = b'ghost'
3542
delta = [(None, 'newdir', b'newdir-id', entry)]
2557
3543
serializer = inventory_delta.InventoryDeltaSerializer(
2558
3544
versioned_root=True, tree_references=False)
2559
lines = serializer.delta_to_lines('rev1', 'rev2', delta)
3545
lines = serializer.delta_to_lines(b'rev1', b'rev2', delta)
2560
3546
yield versionedfile.ChunkedContentFactory(
2561
('rev2',), (('rev1',)), None, lines)
3547
(b'rev2',), ((b'rev1',)), None, lines)
2562
3548
# Another delta.
2563
lines = serializer.delta_to_lines('rev1', 'rev3', delta)
3549
lines = serializer.delta_to_lines(b'rev1', b'rev3', delta)
2564
3550
yield versionedfile.ChunkedContentFactory(
2565
('rev3',), (('rev1',)), None, lines)
3551
(b'rev3',), ((b'rev1',)), None, lines)
2566
3552
return stream_with_inv_delta()
2784
3784
def test_NoSuchRevision(self):
2785
3785
branch = self.make_branch('')
2787
3787
translated_error = self.translateTuple(
2788
('NoSuchRevision', revid), branch=branch)
3788
(b'NoSuchRevision', revid), branch=branch)
2789
3789
expected_error = errors.NoSuchRevision(branch, revid)
2790
3790
self.assertEqual(expected_error, translated_error)
2792
3792
def test_nosuchrevision(self):
2793
3793
repository = self.make_repository('')
2795
3795
translated_error = self.translateTuple(
2796
('nosuchrevision', revid), repository=repository)
3796
(b'nosuchrevision', revid), repository=repository)
2797
3797
expected_error = errors.NoSuchRevision(repository, revid)
2798
3798
self.assertEqual(expected_error, translated_error)
2800
3800
def test_nobranch(self):
2801
bzrdir = self.make_bzrdir('')
2802
translated_error = self.translateTuple(('nobranch',), bzrdir=bzrdir)
3801
bzrdir = self.make_controldir('')
3802
translated_error = self.translateTuple((b'nobranch',), bzrdir=bzrdir)
2803
3803
expected_error = errors.NotBranchError(path=bzrdir.root_transport.base)
2804
3804
self.assertEqual(expected_error, translated_error)
2806
3806
def test_nobranch_one_arg(self):
2807
bzrdir = self.make_bzrdir('')
3807
bzrdir = self.make_controldir('')
2808
3808
translated_error = self.translateTuple(
2809
('nobranch', 'extra detail'), bzrdir=bzrdir)
3809
(b'nobranch', b'extra detail'), bzrdir=bzrdir)
2810
3810
expected_error = errors.NotBranchError(
2811
3811
path=bzrdir.root_transport.base,
2812
3812
detail='extra detail')
2813
3813
self.assertEqual(expected_error, translated_error)
3815
def test_norepository(self):
3816
bzrdir = self.make_controldir('')
3817
translated_error = self.translateTuple((b'norepository',),
3819
expected_error = errors.NoRepositoryPresent(bzrdir)
3820
self.assertEqual(expected_error, translated_error)
2815
3822
def test_LockContention(self):
2816
translated_error = self.translateTuple(('LockContention',))
3823
translated_error = self.translateTuple((b'LockContention',))
2817
3824
expected_error = errors.LockContention('(remote lock)')
2818
3825
self.assertEqual(expected_error, translated_error)
2820
3827
def test_UnlockableTransport(self):
2821
bzrdir = self.make_bzrdir('')
3828
bzrdir = self.make_controldir('')
2822
3829
translated_error = self.translateTuple(
2823
('UnlockableTransport',), bzrdir=bzrdir)
3830
(b'UnlockableTransport',), bzrdir=bzrdir)
2824
3831
expected_error = errors.UnlockableTransport(bzrdir.root_transport)
2825
3832
self.assertEqual(expected_error, translated_error)
2827
3834
def test_LockFailed(self):
2828
3835
lock = 'str() of a server lock'
2829
3836
why = 'str() of why'
2830
translated_error = self.translateTuple(('LockFailed', lock, why))
3837
translated_error = self.translateTuple(
3838
(b'LockFailed', lock.encode('ascii'), why.encode('ascii')))
2831
3839
expected_error = errors.LockFailed(lock, why)
2832
3840
self.assertEqual(expected_error, translated_error)
2834
3842
def test_TokenMismatch(self):
2835
3843
token = 'a lock token'
2836
translated_error = self.translateTuple(('TokenMismatch',), token=token)
3844
translated_error = self.translateTuple(
3845
(b'TokenMismatch',), token=token)
2837
3846
expected_error = errors.TokenMismatch(token, '(remote token)')
2838
3847
self.assertEqual(expected_error, translated_error)
2841
3850
branch = self.make_branch('a')
2842
3851
other_branch = self.make_branch('b')
2843
3852
translated_error = self.translateTuple(
2844
('Diverged',), branch=branch, other_branch=other_branch)
3853
(b'Diverged',), branch=branch, other_branch=other_branch)
2845
3854
expected_error = errors.DivergedBranches(branch, other_branch)
2846
3855
self.assertEqual(expected_error, translated_error)
3857
def test_NotStacked(self):
3858
branch = self.make_branch('')
3859
translated_error = self.translateTuple((b'NotStacked',), branch=branch)
3860
expected_error = errors.NotStacked(branch)
3861
self.assertEqual(expected_error, translated_error)
2848
3863
def test_ReadError_no_args(self):
2849
3864
path = 'a path'
2850
translated_error = self.translateTuple(('ReadError',), path=path)
3865
translated_error = self.translateTuple((b'ReadError',), path=path)
2851
3866
expected_error = errors.ReadError(path)
2852
3867
self.assertEqual(expected_error, translated_error)
2854
3869
def test_ReadError(self):
2855
3870
path = 'a path'
2856
translated_error = self.translateTuple(('ReadError', path))
3871
translated_error = self.translateTuple(
3872
(b'ReadError', path.encode('utf-8')))
2857
3873
expected_error = errors.ReadError(path)
2858
3874
self.assertEqual(expected_error, translated_error)
2860
3876
def test_IncompatibleRepositories(self):
2861
translated_error = self.translateTuple(('IncompatibleRepositories',
2862
"repo1", "repo2", "details here"))
3877
translated_error = self.translateTuple((b'IncompatibleRepositories',
3878
b"repo1", b"repo2", b"details here"))
2863
3879
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")
2865
3887
self.assertEqual(expected_error, translated_error)
2867
3889
def test_PermissionDenied_no_args(self):
2868
3890
path = 'a path'
2869
translated_error = self.translateTuple(('PermissionDenied',), path=path)
3891
translated_error = self.translateTuple((b'PermissionDenied',),
2870
3893
expected_error = errors.PermissionDenied(path)
2871
3894
self.assertEqual(expected_error, translated_error)
2873
3896
def test_PermissionDenied_one_arg(self):
2874
3897
path = 'a path'
2875
translated_error = self.translateTuple(('PermissionDenied', path))
3898
translated_error = self.translateTuple(
3899
(b'PermissionDenied', path.encode('utf-8')))
2876
3900
expected_error = errors.PermissionDenied(path)
2877
3901
self.assertEqual(expected_error, translated_error)
2891
3915
path = 'a path'
2892
3916
extra = 'a string with extra info'
2893
3917
translated_error = self.translateTuple(
2894
('PermissionDenied', path, extra))
3918
(b'PermissionDenied', path.encode('utf-8'), extra.encode('utf-8')))
2895
3919
expected_error = errors.PermissionDenied(path, extra)
2896
3920
self.assertEqual(expected_error, translated_error)
3922
# GZ 2011-03-02: TODO test for PermissionDenied with non-ascii 'extra'
3924
def test_NoSuchFile_context_path(self):
3925
local_path = "local path"
3926
translated_error = self.translateTuple((b'ReadError', b"remote path"),
3928
expected_error = errors.ReadError(local_path)
3929
self.assertEqual(expected_error, translated_error)
3931
def test_NoSuchFile_without_context(self):
3932
remote_path = "remote path"
3933
translated_error = self.translateTuple(
3934
(b'ReadError', remote_path.encode('utf-8')))
3935
expected_error = errors.ReadError(remote_path)
3936
self.assertEqual(expected_error, translated_error)
3938
def test_ReadOnlyError(self):
3939
translated_error = self.translateTuple((b'ReadOnlyError',))
3940
expected_error = errors.TransportNotPossible("readonly transport")
3941
self.assertEqual(expected_error, translated_error)
3943
def test_MemoryError(self):
3944
translated_error = self.translateTuple((b'MemoryError',))
3945
self.assertStartsWith(str(translated_error),
3946
"remote server out of memory")
3948
def test_generic_IndexError_no_classname(self):
3949
err = errors.ErrorFromSmartServer(
3950
(b'error', b"list index out of range"))
3951
translated_error = self.translateErrorFromSmartServer(err)
3952
expected_error = errors.UnknownErrorFromSmartServer(err)
3953
self.assertEqual(expected_error, translated_error)
3955
# GZ 2011-03-02: TODO test generic non-ascii error string
3957
def test_generic_KeyError(self):
3958
err = errors.ErrorFromSmartServer((b'error', b'KeyError', b"1"))
3959
translated_error = self.translateErrorFromSmartServer(err)
3960
expected_error = errors.UnknownErrorFromSmartServer(err)
3961
self.assertEqual(expected_error, translated_error)
3963
def test_RevnoOutOfBounds(self):
3964
translated_error = self.translateTuple(
3965
((b'revno-outofbounds', 5, 0, 3)), path=b'path')
3966
expected_error = errors.RevnoOutOfBounds(5, (0, 3))
3967
self.assertEqual(expected_error, translated_error)
2899
3970
class TestErrorTranslationRobustness(TestErrorTranslationBase):
2900
"""Unit tests for bzrlib.remote._translate_error's robustness.
3971
"""Unit tests for breezy.bzr.remote._translate_error's robustness.
2902
3973
TestErrorTranslationSuccess is for cases where _translate_error can
2903
3974
translate successfully. This class about how _translate_err behaves when
3143
4214
def test_copy_content_into_avoids_revision_history(self):
3144
4215
local = self.make_branch('local')
3145
remote_backing_tree = self.make_branch_and_tree('remote')
3146
remote_backing_tree.commit("Commit.")
4216
builder = self.make_branch_builder('remote')
4217
builder.build_commit(message="Commit.")
3147
4218
remote_branch_url = self.smart_server.get_url() + 'remote'
3148
4219
remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
3149
4220
local.repository.fetch(remote_branch.repository)
3150
4221
self.hpss_calls = []
3151
4222
remote_branch.copy_content_into(local)
3152
self.assertFalse('Branch.revision_history' in self.hpss_calls)
4223
self.assertFalse(b'Branch.revision_history' in self.hpss_calls)
4225
def test_fetch_everything_needs_just_one_call(self):
4226
local = self.make_branch('local')
4227
builder = self.make_branch_builder('remote')
4228
builder.build_commit(message="Commit.")
4229
remote_branch_url = self.smart_server.get_url() + 'remote'
4230
remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
4231
self.hpss_calls = []
4232
local.repository.fetch(
4233
remote_branch.repository,
4234
fetch_spec=vf_search.EverythingResult(remote_branch.repository))
4235
self.assertEqual([b'Repository.get_stream_1.19'], self.hpss_calls)
4237
def override_verb(self, verb_name, verb):
4238
request_handlers = request.request_handlers
4239
orig_verb = request_handlers.get(verb_name)
4240
orig_info = request_handlers.get_info(verb_name)
4241
request_handlers.register(verb_name, verb, override_existing=True)
4242
self.addCleanup(request_handlers.register, verb_name, orig_verb,
4243
override_existing=True, info=orig_info)
4245
def test_fetch_everything_backwards_compat(self):
4246
"""Can fetch with EverythingResult even with pre 2.4 servers.
4248
Pre-2.4 do not support 'everything' searches with the
4249
Repository.get_stream_1.19 verb.
4253
class OldGetStreamVerb(SmartServerRepositoryGetStream_1_19):
4254
"""A version of the Repository.get_stream_1.19 verb patched to
4255
reject 'everything' searches the way 2.3 and earlier do.
4258
def recreate_search(self, repository, search_bytes,
4259
discard_excess=False):
4260
verb_log.append(search_bytes.split(b'\n', 1)[0])
4261
if search_bytes == b'everything':
4263
request.FailedSmartServerResponse((b'BadSearch',)))
4264
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)
4268
local = self.make_branch('local')
4269
builder = self.make_branch_builder('remote')
4270
builder.build_commit(message="Commit.")
4271
remote_branch_url = self.smart_server.get_url() + 'remote'
4272
remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
4273
self.hpss_calls = []
4274
local.repository.fetch(
4275
remote_branch.repository,
4276
fetch_spec=vf_search.EverythingResult(remote_branch.repository))
4277
# make sure the overridden verb was used
4278
self.assertLength(1, verb_log)
4279
# more than one HPSS call is needed, but because it's a VFS callback
4280
# its hard to predict exactly how many.
4281
self.assertTrue(len(self.hpss_calls) > 1)
4284
class TestUpdateBoundBranchWithModifiedBoundLocation(
4285
tests.TestCaseWithTransport):
4286
"""Ensure correct handling of bound_location modifications.
4288
This is tested against a smart server as http://pad.lv/786980 was about a
4289
ReadOnlyError (write attempt during a read-only transaction) which can only
4290
happen in this context.
4294
super(TestUpdateBoundBranchWithModifiedBoundLocation, self).setUp()
4295
self.transport_server = test_server.SmartTCPServer_for_testing
4297
def make_master_and_checkout(self, master_name, checkout_name):
4298
# Create the master branch and its associated checkout
4299
self.master = self.make_branch_and_tree(master_name)
4300
self.checkout = self.master.branch.create_checkout(checkout_name)
4301
# Modify the master branch so there is something to update
4302
self.master.commit('add stuff')
4303
self.last_revid = self.master.commit('even more stuff')
4304
self.bound_location = self.checkout.branch.get_bound_location()
4306
def assertUpdateSucceeds(self, new_location):
4307
self.checkout.branch.set_bound_location(new_location)
4308
self.checkout.update()
4309
self.assertEqual(self.last_revid, self.checkout.last_revision())
4311
def test_without_final_slash(self):
4312
self.make_master_and_checkout('master', 'checkout')
4313
# For unclear reasons some users have a bound_location without a final
4314
# '/', simulate that by forcing such a value
4315
self.assertEndsWith(self.bound_location, '/')
4316
self.assertUpdateSucceeds(self.bound_location.rstrip('/'))
4318
def test_plus_sign(self):
4319
self.make_master_and_checkout('+master', 'checkout')
4320
self.assertUpdateSucceeds(self.bound_location.replace('%2B', '+', 1))
4322
def test_tilda(self):
4323
# Embed ~ in the middle of the path just to avoid any $HOME
4325
self.make_master_and_checkout('mas~ter', 'checkout')
4326
self.assertUpdateSucceeds(self.bound_location.replace('%2E', '~', 1))
4329
class TestWithCustomErrorHandler(RemoteBranchTestCase):
4331
def test_no_context(self):
4332
class OutOfCoffee(errors.BzrError):
4333
"""A dummy exception for testing."""
4335
def __init__(self, urgency):
4336
self.urgency = urgency
4337
remote.no_context_error_translators.register(b"OutOfCoffee",
4338
lambda err: OutOfCoffee(err.error_args[0]))
4339
transport = MemoryTransport()
4340
client = FakeClient(transport.base)
4341
client.add_expected_call(
4342
b'Branch.get_stacked_on_url', (b'quack/',),
4343
b'error', (b'NotStacked',))
4344
client.add_expected_call(
4345
b'Branch.last_revision_info',
4347
b'error', (b'OutOfCoffee', b'low'))
4348
transport.mkdir('quack')
4349
transport = transport.clone('quack')
4350
branch = self.make_remote_branch(transport, client)
4351
self.assertRaises(OutOfCoffee, branch.last_revision_info)
4352
self.assertFinished(client)
4354
def test_with_context(self):
4355
class OutOfTea(errors.BzrError):
4356
def __init__(self, branch, urgency):
4357
self.branch = branch
4358
self.urgency = urgency
4359
remote.error_translators.register(b"OutOfTea",
4360
lambda err, find, path: OutOfTea(
4361
err.error_args[0].decode(
4364
transport = MemoryTransport()
4365
client = FakeClient(transport.base)
4366
client.add_expected_call(
4367
b'Branch.get_stacked_on_url', (b'quack/',),
4368
b'error', (b'NotStacked',))
4369
client.add_expected_call(
4370
b'Branch.last_revision_info',
4372
b'error', (b'OutOfTea', b'low'))
4373
transport.mkdir('quack')
4374
transport = transport.clone('quack')
4375
branch = self.make_remote_branch(transport, client)
4376
self.assertRaises(OutOfTea, branch.last_revision_info)
4377
self.assertFinished(client)
4380
class TestRepositoryPack(TestRemoteRepository):
4382
def test_pack(self):
4383
transport_path = 'quack'
4384
repo, client = self.setup_fake_client_and_repository(transport_path)
4385
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', ))
4396
def test_pack_with_hint(self):
4397
transport_path = 'quack'
4398
repo, client = self.setup_fake_client_and_repository(transport_path)
4399
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', ))
4408
repo.pack(['hinta', 'hintb'])
4411
class TestRepositoryIterInventories(TestRemoteRepository):
4412
"""Test Repository.iter_inventories."""
4414
def _serialize_inv_delta(self, old_name, new_name, delta):
4415
serializer = inventory_delta.InventoryDeltaSerializer(True, False)
4416
return b"".join(serializer.delta_to_lines(old_name, new_name, delta))
4418
def test_single_empty(self):
4419
transport_path = 'quack'
4420
repo, client = self.setup_fake_client_and_repository(transport_path)
4421
fmt = controldir.format_registry.get('2a')().repository_format
4423
stream = [('inventory-deltas', [
4424
versionedfile.FulltextContentFactory(b'somerevid', None, None,
4425
self._serialize_inv_delta(b'null:', b'somerevid', []))])]
4426
client.add_expected_call(
4427
b'VersionedFileRepository.get_inventories', (
4428
b'quack/', b'unordered'),
4429
b'success', (b'ok', ),
4430
_stream_to_byte_stream(stream, fmt))
4431
ret = list(repo.iter_inventories([b"somerevid"]))
4432
self.assertLength(1, ret)
4434
self.assertEqual(b"somerevid", inv.revision_id)
4436
def test_empty(self):
4437
transport_path = 'quack'
4438
repo, client = self.setup_fake_client_and_repository(transport_path)
4439
ret = list(repo.iter_inventories([]))
4440
self.assertEqual(ret, [])
4442
def test_missing(self):
4443
transport_path = 'quack'
4444
repo, client = self.setup_fake_client_and_repository(transport_path)
4445
client.add_expected_call(
4446
b'VersionedFileRepository.get_inventories', (
4447
b'quack/', b'unordered'),
4448
b'success', (b'ok', ), iter([]))
4449
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)