445
431
def test_backwards_compat(self):
446
432
self.setup_smart_server_with_call_log()
447
a_dir = self.make_controldir('.')
433
a_dir = self.make_bzrdir('.')
448
434
self.reset_smart_call_log()
449
verb = b'BzrDir.cloning_metadir'
435
verb = 'BzrDir.cloning_metadir'
450
436
self.disable_verb(verb)
451
a_dir.cloning_metadir()
437
format = a_dir.cloning_metadir()
452
438
call_count = len([call for call in self.hpss_calls if
453
call.call.method == verb])
439
call.call.method == verb])
454
440
self.assertEqual(1, call_count)
456
442
def test_branch_reference(self):
457
443
transport = self.get_transport('quack')
458
444
referenced = self.make_branch('referenced')
459
expected = referenced.controldir.cloning_metadir()
445
expected = referenced.bzrdir.cloning_metadir()
460
446
client = FakeClient(transport.base)
461
447
client.add_expected_call(
462
b'BzrDir.cloning_metadir', (b'quack/', b'False'),
463
b'error', (b'BranchReference',)),
448
'BzrDir.cloning_metadir', ('quack/', 'False'),
449
'error', ('BranchReference',)),
464
450
client.add_expected_call(
465
b'BzrDir.open_branchV3', (b'quack/',),
466
b'success', (b'ref', self.get_url('referenced').encode('utf-8'))),
467
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
469
result = a_controldir.cloning_metadir()
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()
470
456
# We should have got a control dir matching the referenced branch.
471
457
self.assertEqual(bzrdir.BzrDirMetaFormat1, type(result))
472
self.assertEqual(expected._repository_format,
473
result._repository_format)
458
self.assertEqual(expected._repository_format, result._repository_format)
474
459
self.assertEqual(expected._branch_format, result._branch_format)
475
460
self.assertFinished(client)
477
462
def test_current_server(self):
478
463
transport = self.get_transport('.')
479
464
transport = transport.clone('quack')
480
self.make_controldir('quack')
465
self.make_bzrdir('quack')
481
466
client = FakeClient(transport.base)
482
reference_bzrdir_format = controldir.format_registry.get('default')()
467
reference_bzrdir_format = bzrdir.format_registry.get('default')()
483
468
control_name = reference_bzrdir_format.network_name()
484
469
client.add_expected_call(
485
b'BzrDir.cloning_metadir', (b'quack/', b'False'),
486
b'success', (control_name, b'', (b'branch', b''))),
487
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
489
result = a_controldir.cloning_metadir()
470
'BzrDir.cloning_metadir', ('quack/', 'False'),
471
'success', (control_name, '', ('branch', ''))),
472
a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
474
result = a_bzrdir.cloning_metadir()
490
475
# We should have got a reference control dir with default branch and
491
476
# repository formats.
492
477
# This pokes a little, just to be sure.
495
480
self.assertEqual(None, result._branch_format)
496
481
self.assertFinished(client)
498
def test_unknown(self):
499
transport = self.get_transport('quack')
500
referenced = self.make_branch('referenced')
501
referenced.controldir.cloning_metadir()
502
client = FakeClient(transport.base)
503
client.add_expected_call(
504
b'BzrDir.cloning_metadir', (b'quack/', b'False'),
505
b'success', (b'unknown', b'unknown', (b'branch', b''))),
506
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
508
self.assertRaises(errors.UnknownFormatError,
509
a_controldir.cloning_metadir)
512
class TestBzrDirCheckoutMetaDir(TestRemote):
514
def test__get_checkout_format(self):
515
transport = MemoryTransport()
516
client = FakeClient(transport.base)
517
reference_bzrdir_format = controldir.format_registry.get('default')()
518
control_name = reference_bzrdir_format.network_name()
519
client.add_expected_call(
520
b'BzrDir.checkout_metadir', (b'quack/', ),
521
b'success', (control_name, b'', b''))
522
transport.mkdir('quack')
523
transport = transport.clone('quack')
524
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
526
result = a_controldir.checkout_metadir()
527
# We should have got a reference control dir with default branch and
528
# repository formats.
529
self.assertEqual(bzrdir.BzrDirMetaFormat1, type(result))
530
self.assertEqual(None, result._repository_format)
531
self.assertEqual(None, result._branch_format)
532
self.assertFinished(client)
534
def test_unknown_format(self):
535
transport = MemoryTransport()
536
client = FakeClient(transport.base)
537
client.add_expected_call(
538
b'BzrDir.checkout_metadir', (b'quack/',),
539
b'success', (b'dontknow', b'', b''))
540
transport.mkdir('quack')
541
transport = transport.clone('quack')
542
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
544
self.assertRaises(errors.UnknownFormatError,
545
a_controldir.checkout_metadir)
546
self.assertFinished(client)
549
class TestBzrDirGetBranches(TestRemote):
551
def test_get_branches(self):
552
transport = MemoryTransport()
553
client = FakeClient(transport.base)
554
reference_bzrdir_format = controldir.format_registry.get('default')()
555
branch_name = reference_bzrdir_format.get_branch_format().network_name()
556
client.add_success_response_with_body(
558
b"foo": (b"branch", branch_name),
559
b"": (b"branch", branch_name)}), b"success")
560
client.add_success_response(
561
b'ok', b'', b'no', b'no', b'no',
562
reference_bzrdir_format.repository_format.network_name())
563
client.add_error_response(b'NotStacked')
564
client.add_success_response(
565
b'ok', b'', b'no', b'no', b'no',
566
reference_bzrdir_format.repository_format.network_name())
567
client.add_error_response(b'NotStacked')
568
transport.mkdir('quack')
569
transport = transport.clone('quack')
570
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
572
result = a_controldir.get_branches()
573
self.assertEqual({"", "foo"}, set(result.keys()))
575
[('call_expecting_body', b'BzrDir.get_branches', (b'quack/',)),
576
('call', b'BzrDir.find_repositoryV3', (b'quack/', )),
577
('call', b'Branch.get_stacked_on_url', (b'quack/', )),
578
('call', b'BzrDir.find_repositoryV3', (b'quack/', )),
579
('call', b'Branch.get_stacked_on_url', (b'quack/', ))],
583
class TestBzrDirDestroyBranch(TestRemote):
585
def test_destroy_default(self):
586
transport = self.get_transport('quack')
587
self.make_branch('referenced')
588
client = FakeClient(transport.base)
589
client.add_expected_call(
590
b'BzrDir.destroy_branch', (b'quack/', ),
591
b'success', (b'ok',)),
592
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
594
a_controldir.destroy_branch()
595
self.assertFinished(client)
598
class TestBzrDirHasWorkingTree(TestRemote):
600
def test_has_workingtree(self):
601
transport = self.get_transport('quack')
602
client = FakeClient(transport.base)
603
client.add_expected_call(
604
b'BzrDir.has_workingtree', (b'quack/',),
605
b'success', (b'yes',)),
606
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
608
self.assertTrue(a_controldir.has_workingtree())
609
self.assertFinished(client)
611
def test_no_workingtree(self):
612
transport = self.get_transport('quack')
613
client = FakeClient(transport.base)
614
client.add_expected_call(
615
b'BzrDir.has_workingtree', (b'quack/',),
616
b'success', (b'no',)),
617
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
619
self.assertFalse(a_controldir.has_workingtree())
620
self.assertFinished(client)
623
class TestBzrDirDestroyRepository(TestRemote):
625
def test_destroy_repository(self):
626
transport = self.get_transport('quack')
627
client = FakeClient(transport.base)
628
client.add_expected_call(
629
b'BzrDir.destroy_repository', (b'quack/',),
630
b'success', (b'ok',)),
631
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
633
a_controldir.destroy_repository()
634
self.assertFinished(client)
637
484
class TestBzrDirOpen(TestRemote):
790
632
network_name = reference_format.network_name()
791
633
branch_network_name = self.get_branch_format().network_name()
792
634
client.add_expected_call(
793
b'BzrDir.open_branchV3', (b'~hello/',),
794
b'success', (b'branch', branch_network_name))
795
client.add_expected_call(
796
b'BzrDir.find_repositoryV3', (b'~hello/',),
797
b'success', (b'ok', b'', b'no', b'no', b'no', network_name))
798
client.add_expected_call(
799
b'Branch.get_stacked_on_url', (b'~hello/',),
800
b'error', (b'NotStacked',))
801
bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
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()
804
646
self.assertFinished(client)
806
def check_open_repository(self, rich_root, subtrees,
807
external_lookup=b'no'):
648
def check_open_repository(self, rich_root, subtrees, external_lookup='no'):
808
649
reference_format = self.get_repo_format()
809
650
network_name = reference_format.network_name()
810
651
transport = MemoryTransport()
811
652
transport.mkdir('quack')
812
653
transport = transport.clone('quack')
814
rich_response = b'yes'
655
rich_response = 'yes'
816
rich_response = b'no'
818
subtree_response = b'yes'
659
subtree_response = 'yes'
820
subtree_response = b'no'
661
subtree_response = 'no'
821
662
client = FakeClient(transport.base)
822
663
client.add_success_response(
823
b'ok', b'', rich_response, subtree_response, external_lookup,
664
'ok', '', rich_response, subtree_response, external_lookup,
825
bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
666
bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
827
668
result = bzrdir.open_repository()
828
669
self.assertEqual(
829
[('call', b'BzrDir.find_repositoryV3', (b'quack/',))],
670
[('call', 'BzrDir.find_repositoryV3', ('quack/',))],
831
672
self.assertIsInstance(result, RemoteRepository)
832
self.assertEqual(bzrdir, result.controldir)
673
self.assertEqual(bzrdir, result.bzrdir)
833
674
self.assertEqual(rich_root, result._format.rich_root_data)
834
675
self.assertEqual(subtrees, result._format.supports_tree_reference)
867
706
transport = transport.clone('quack')
868
707
self.make_repository('quack')
869
708
client = FakeClient(transport.base)
870
reference_bzrdir_format = controldir.format_registry.get('default')()
871
reference_format = reference_bzrdir_format.get_branch_format()
872
network_name = reference_format.network_name()
873
reference_repo_fmt = reference_bzrdir_format.repository_format
874
reference_repo_name = reference_repo_fmt.network_name()
875
client.add_expected_call(
876
b'BzrDir.create_branch', (b'quack/', network_name),
877
b'success', (b'ok', network_name, b'', b'no', b'no', b'yes',
878
reference_repo_name))
879
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
881
branch = a_controldir.create_branch()
882
# We should have got a remote branch
883
self.assertIsInstance(branch, remote.RemoteBranch)
884
# its format should have the settings from the response
885
format = branch._format
886
self.assertEqual(network_name, format.network_name())
888
def test_already_open_repo_and_reused_medium(self):
889
"""Bug 726584: create_branch(..., repository=repo) should work
890
regardless of what the smart medium's base URL is.
892
self.transport_server = test_server.SmartTCPServer_for_testing
893
transport = self.get_transport('.')
894
repo = self.make_repository('quack')
895
# Client's medium rooted a transport root (not at the bzrdir)
896
client = FakeClient(transport.base)
897
transport = transport.clone('quack')
898
reference_bzrdir_format = controldir.format_registry.get('default')()
899
reference_format = reference_bzrdir_format.get_branch_format()
900
network_name = reference_format.network_name()
901
reference_repo_fmt = reference_bzrdir_format.repository_format
902
reference_repo_name = reference_repo_fmt.network_name()
903
client.add_expected_call(
904
b'BzrDir.create_branch', (b'extra/quack/', network_name),
905
b'success', (b'ok', network_name, b'', b'no', b'no', b'yes',
906
reference_repo_name))
907
a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
909
branch = a_controldir.create_branch(repository=repo)
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()
910
721
# We should have got a remote branch
911
722
self.assertIsInstance(branch, remote.RemoteBranch)
912
723
# its format should have the settings from the response
961
772
server_url = 'bzr://example.com/'
962
773
self.permit_url(server_url)
963
774
client = FakeClient(server_url)
964
client.add_unknown_method_response(b'BzrDir.find_repositoryV3')
965
client.add_unknown_method_response(b'BzrDir.find_repositoryV2')
966
client.add_success_response(b'ok', b'', b'no', b'no')
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')
967
778
# A real repository instance will be created to determine the network
969
780
client.add_success_response_with_body(
970
b"Bazaar-NG meta directory, format 1\n", b'ok')
971
client.add_success_response(b'stat', b'0', b'65535')
781
"Bazaar-NG meta directory, format 1\n", 'ok')
972
782
client.add_success_response_with_body(
973
reference_format.get_format_string(), b'ok')
783
reference_format.get_format_string(), 'ok')
974
784
# PackRepository wants to do a stat
975
client.add_success_response(b'stat', b'0', b'65535')
785
client.add_success_response('stat', '0', '65535')
976
786
remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
978
bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
788
bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
980
790
repo = bzrdir.open_repository()
981
791
self.assertEqual(
982
[('call', b'BzrDir.find_repositoryV3', (b'quack/',)),
983
('call', b'BzrDir.find_repositoryV2', (b'quack/',)),
984
('call', b'BzrDir.find_repository', (b'quack/',)),
985
('call_expecting_body', b'get', (b'/quack/.bzr/branch-format',)),
986
('call', b'stat', (b'/quack/.bzr',)),
987
('call_expecting_body', b'get', (b'/quack/.bzr/repository/format',)),
988
('call', b'stat', (b'/quack/.bzr/repository',)),
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',)),
991
800
self.assertEqual(network_name, repo._format.network_name())
997
806
server_url = 'bzr://example.com/'
998
807
self.permit_url(server_url)
999
808
client = FakeClient(server_url)
1000
client.add_unknown_method_response(b'BzrDir.find_repositoryV3')
1001
client.add_success_response(b'ok', b'', b'no', b'no', b'no')
809
client.add_unknown_method_response('BzrDir.find_repositoryV3')
810
client.add_success_response('ok', '', 'no', 'no', 'no')
1002
811
# A real repository instance will be created to determine the network
1004
813
client.add_success_response_with_body(
1005
b"Bazaar-NG meta directory, format 1\n", b'ok')
1006
client.add_success_response(b'stat', b'0', b'65535')
814
"Bazaar-NG meta directory, format 1\n", 'ok')
1007
815
client.add_success_response_with_body(
1008
reference_format.get_format_string(), b'ok')
816
reference_format.get_format_string(), 'ok')
1009
817
# PackRepository wants to do a stat
1010
client.add_success_response(b'stat', b'0', b'65535')
818
client.add_success_response('stat', '0', '65535')
1011
819
remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
1013
bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
821
bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
1015
823
repo = bzrdir.open_repository()
1016
824
self.assertEqual(
1017
[('call', b'BzrDir.find_repositoryV3', (b'quack/',)),
1018
('call', b'BzrDir.find_repositoryV2', (b'quack/',)),
1019
('call_expecting_body', b'get', (b'/quack/.bzr/branch-format',)),
1020
('call', b'stat', (b'/quack/.bzr',)),
1021
('call_expecting_body', b'get',
1022
(b'/quack/.bzr/repository/format',)),
1023
('call', b'stat', (b'/quack/.bzr/repository',)),
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',)),
1026
832
self.assertEqual(network_name, repo._format.network_name())
1048
853
def test_success(self):
1049
854
"""Simple test for typical successful call."""
1050
fmt = RemoteBzrDirFormat()
855
fmt = bzrdir.RemoteBzrDirFormat()
1051
856
default_format_name = BzrDirFormat.get_default_format().network_name()
1052
857
transport = self.get_transport()
1053
858
client = FakeClient(transport.base)
1054
859
client.add_expected_call(
1055
b'BzrDirFormat.initialize_ex_1.16',
1056
(default_format_name, b'path', b'False', b'False', b'False', b'',
1057
b'', b'', b'', b'False'),
1059
(b'.', b'no', b'no', b'yes', b'repo fmt', b'repo bzrdir fmt',
1060
b'bzrdir fmt', b'False', b'', b'', b'repo lock token'))
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'))
1061
866
# XXX: It would be better to call fmt.initialize_on_transport_ex, but
1062
867
# it's currently hard to test that without supplying a real remote
1063
868
# transport connected to a real server.
1064
fmt._initialize_on_transport_ex_rpc(
1065
client, b'path', transport, False, False, False, None, None, None,
869
result = fmt._initialize_on_transport_ex_rpc(client, 'path',
870
transport, False, False, False, None, None, None, None, False)
1067
871
self.assertFinished(client)
1069
873
def test_error(self):
1070
874
"""Error responses are translated, e.g. 'PermissionDenied' raises the
1071
875
corresponding error from the client.
1073
fmt = RemoteBzrDirFormat()
877
fmt = bzrdir.RemoteBzrDirFormat()
1074
878
default_format_name = BzrDirFormat.get_default_format().network_name()
1075
879
transport = self.get_transport()
1076
880
client = FakeClient(transport.base)
1077
881
client.add_expected_call(
1078
b'BzrDirFormat.initialize_ex_1.16',
1079
(default_format_name, b'path', b'False', b'False', b'False', b'',
1080
b'', b'', b'', b'False'),
1082
(b'PermissionDenied', b'path', b'extra info'))
882
'BzrDirFormat.initialize_ex_1.16',
883
(default_format_name, 'path', 'False', 'False', 'False', '',
884
'', '', '', 'False'),
886
('PermissionDenied', 'path', 'extra info'))
1083
887
# XXX: It would be better to call fmt.initialize_on_transport_ex, but
1084
888
# it's currently hard to test that without supplying a real remote
1085
889
# transport connected to a real server.
1086
err = self.assertRaises(
1087
errors.PermissionDenied,
1088
fmt._initialize_on_transport_ex_rpc, client, b'path', transport,
890
err = self.assertRaises(errors.PermissionDenied,
891
fmt._initialize_on_transport_ex_rpc, client, 'path', transport,
1089
892
False, False, False, None, None, None, None, False)
1090
893
self.assertEqual('path', err.path)
1091
894
self.assertEqual(': extra info', err.extra)
1352
1101
transport = MemoryTransport()
1353
1102
client = FakeClient(transport.base)
1354
1103
client.add_expected_call(
1355
b'Branch.get_stacked_on_url', (b'quack/',),
1356
b'error', (b'NotStacked',))
1104
'Branch.get_stacked_on_url', ('quack/',),
1105
'error', ('NotStacked',))
1357
1106
client.add_expected_call(
1358
b'Branch.set_tags_bytes', (b'quack/',
1359
b'branch token', b'repo token'),
1107
'Branch.set_tags_bytes', ('quack/', 'branch token', 'repo token'),
1361
1109
transport.mkdir('quack')
1362
1110
transport = transport.clone('quack')
1363
1111
branch = self.make_remote_branch(transport, client)
1364
1112
self.lock_remote_branch(branch)
1365
branch._set_tags_bytes(b'tags bytes')
1113
branch._set_tags_bytes('tags bytes')
1366
1114
self.assertFinished(client)
1367
self.assertEqual(b'tags bytes', client._calls[-1][-1])
1115
self.assertEqual('tags bytes', client._calls[-1][-1])
1369
1117
def test_backwards_compatible(self):
1370
1118
transport = MemoryTransport()
1371
1119
client = FakeClient(transport.base)
1372
1120
client.add_expected_call(
1373
b'Branch.get_stacked_on_url', (b'quack/',),
1374
b'error', (b'NotStacked',))
1121
'Branch.get_stacked_on_url', ('quack/',),
1122
'error', ('NotStacked',))
1375
1123
client.add_expected_call(
1376
b'Branch.set_tags_bytes', (b'quack/',
1377
b'branch token', b'repo token'),
1378
b'unknown', (b'Branch.set_tags_bytes',))
1124
'Branch.set_tags_bytes', ('quack/', 'branch token', 'repo token'),
1125
'unknown', ('Branch.set_tags_bytes',))
1379
1126
transport.mkdir('quack')
1380
1127
transport = transport.clone('quack')
1381
1128
branch = self.make_remote_branch(transport, client)
1382
1129
self.lock_remote_branch(branch)
1384
1130
class StubRealBranch(object):
1385
1131
def __init__(self):
1386
1132
self.calls = []
1388
1133
def _set_tags_bytes(self, bytes):
1389
1134
self.calls.append(('set_tags_bytes', bytes))
1390
1135
real_branch = StubRealBranch()
1391
1136
branch._real_branch = real_branch
1392
branch._set_tags_bytes(b'tags bytes')
1137
branch._set_tags_bytes('tags bytes')
1393
1138
# Call a second time, to exercise the 'remote version already inferred'
1395
branch._set_tags_bytes(b'tags bytes')
1396
self.assertFinished(client)
1398
[('set_tags_bytes', b'tags bytes')] * 2, real_branch.calls)
1401
class TestBranchHeadsToFetch(RemoteBranchTestCase):
1403
def test_uses_last_revision_info_and_tags_by_default(self):
1404
transport = MemoryTransport()
1405
client = FakeClient(transport.base)
1406
client.add_expected_call(
1407
b'Branch.get_stacked_on_url', (b'quack/',),
1408
b'error', (b'NotStacked',))
1409
client.add_expected_call(
1410
b'Branch.last_revision_info', (b'quack/',),
1411
b'success', (b'ok', b'1', b'rev-tip'))
1412
client.add_expected_call(
1413
b'Branch.get_config_file', (b'quack/',),
1414
b'success', (b'ok',), b'')
1415
transport.mkdir('quack')
1416
transport = transport.clone('quack')
1417
branch = self.make_remote_branch(transport, client)
1418
result = branch.heads_to_fetch()
1419
self.assertFinished(client)
1420
self.assertEqual(({b'rev-tip'}, set()), result)
1422
def test_uses_last_revision_info_and_tags_when_set(self):
1423
transport = MemoryTransport()
1424
client = FakeClient(transport.base)
1425
client.add_expected_call(
1426
b'Branch.get_stacked_on_url', (b'quack/',),
1427
b'error', (b'NotStacked',))
1428
client.add_expected_call(
1429
b'Branch.last_revision_info', (b'quack/',),
1430
b'success', (b'ok', b'1', b'rev-tip'))
1431
client.add_expected_call(
1432
b'Branch.get_config_file', (b'quack/',),
1433
b'success', (b'ok',), b'branch.fetch_tags = True')
1434
# XXX: this will break if the default format's serialization of tags
1435
# changes, or if the RPC for fetching tags changes from get_tags_bytes.
1436
client.add_expected_call(
1437
b'Branch.get_tags_bytes', (b'quack/',),
1438
b'success', (b'd5:tag-17:rev-foo5:tag-27:rev-bare',))
1439
transport.mkdir('quack')
1440
transport = transport.clone('quack')
1441
branch = self.make_remote_branch(transport, client)
1442
result = branch.heads_to_fetch()
1443
self.assertFinished(client)
1445
({b'rev-tip'}, {b'rev-foo', b'rev-bar'}), result)
1447
def test_uses_rpc_for_formats_with_non_default_heads_to_fetch(self):
1448
transport = MemoryTransport()
1449
client = FakeClient(transport.base)
1450
client.add_expected_call(
1451
b'Branch.get_stacked_on_url', (b'quack/',),
1452
b'error', (b'NotStacked',))
1453
client.add_expected_call(
1454
b'Branch.heads_to_fetch', (b'quack/',),
1455
b'success', ([b'tip'], [b'tagged-1', b'tagged-2']))
1456
transport.mkdir('quack')
1457
transport = transport.clone('quack')
1458
branch = self.make_remote_branch(transport, client)
1459
branch._format._use_default_local_heads_to_fetch = lambda: False
1460
result = branch.heads_to_fetch()
1461
self.assertFinished(client)
1462
self.assertEqual(({b'tip'}, {b'tagged-1', b'tagged-2'}), result)
1464
def make_branch_with_tags(self):
1465
self.setup_smart_server_with_call_log()
1466
# Make a branch with a single revision.
1467
builder = self.make_branch_builder('foo')
1468
builder.start_series()
1469
builder.build_snapshot(None, [
1470
('add', ('', b'root-id', 'directory', ''))],
1472
builder.finish_series()
1473
branch = builder.get_branch()
1474
# Add two tags to that branch
1475
branch.tags.set_tag('tag-1', b'rev-1')
1476
branch.tags.set_tag('tag-2', b'rev-2')
1479
def test_backwards_compatible(self):
1480
br = self.make_branch_with_tags()
1481
br.get_config_stack().set('branch.fetch_tags', True)
1482
self.addCleanup(br.lock_read().unlock)
1483
# Disable the heads_to_fetch verb
1484
verb = b'Branch.heads_to_fetch'
1485
self.disable_verb(verb)
1486
self.reset_smart_call_log()
1487
result = br.heads_to_fetch()
1488
self.assertEqual(({b'tip'}, {b'rev-1', b'rev-2'}), result)
1490
[b'Branch.last_revision_info', b'Branch.get_tags_bytes'],
1491
[call.call.method for call in self.hpss_calls])
1493
def test_backwards_compatible_no_tags(self):
1494
br = self.make_branch_with_tags()
1495
br.get_config_stack().set('branch.fetch_tags', False)
1496
self.addCleanup(br.lock_read().unlock)
1497
# Disable the heads_to_fetch verb
1498
verb = b'Branch.heads_to_fetch'
1499
self.disable_verb(verb)
1500
self.reset_smart_call_log()
1501
result = br.heads_to_fetch()
1502
self.assertEqual(({b'tip'}, set()), result)
1504
[b'Branch.last_revision_info'],
1505
[call.call.method for call in self.hpss_calls])
1140
branch._set_tags_bytes('tags bytes')
1141
self.assertFinished(client)
1143
[('set_tags_bytes', 'tags bytes')] * 2, real_branch.calls)
1508
1146
class TestBranchLastRevisionInfo(RemoteBranchTestCase):
1552
1190
# doesn't just open in - this test probably needs to be rewritten using
1553
1191
# a spawn()ed server.
1554
1192
stacked_branch = self.make_branch('stacked', format='1.9')
1555
self.make_branch('base', format='1.9')
1193
memory_branch = self.make_branch('base', format='1.9')
1556
1194
vfs_url = self.get_vfs_only_url('base')
1557
1195
stacked_branch.set_stacked_on_url(vfs_url)
1558
transport = stacked_branch.controldir.root_transport
1196
transport = stacked_branch.bzrdir.root_transport
1559
1197
client = FakeClient(transport.base)
1560
1198
client.add_expected_call(
1561
b'Branch.get_stacked_on_url', (b'stacked/',),
1562
b'success', (b'ok', vfs_url.encode('utf-8')))
1199
'Branch.get_stacked_on_url', ('stacked/',),
1200
'success', ('ok', vfs_url))
1563
1201
# XXX: Multiple calls are bad, this second call documents what is
1565
1203
client.add_expected_call(
1566
b'Branch.get_stacked_on_url', (b'stacked/',),
1567
b'success', (b'ok', vfs_url.encode('utf-8')))
1568
bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1204
'Branch.get_stacked_on_url', ('stacked/',),
1205
'success', ('ok', vfs_url))
1206
bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1570
1208
repo_fmt = remote.RemoteRepositoryFormat()
1571
1209
repo_fmt._custom_format = stacked_branch.repository._format
1572
1210
branch = RemoteBranch(bzrdir, RemoteRepository(bzrdir, repo_fmt),
1574
1212
result = branch.get_stacked_on_url()
1575
1213
self.assertEqual(vfs_url, result)
1577
1215
def test_backwards_compatible(self):
1578
1216
# like with bzr1.6 with no Branch.get_stacked_on_url rpc
1579
self.make_branch('base', format='1.6')
1217
base_branch = self.make_branch('base', format='1.6')
1580
1218
stacked_branch = self.make_branch('stacked', format='1.6')
1581
1219
stacked_branch.set_stacked_on_url('../base')
1582
1220
client = FakeClient(self.get_url())
1583
1221
branch_network_name = self.get_branch_format().network_name()
1584
1222
client.add_expected_call(
1585
b'BzrDir.open_branchV3', (b'stacked/',),
1586
b'success', (b'branch', branch_network_name))
1223
'BzrDir.open_branchV3', ('stacked/',),
1224
'success', ('branch', branch_network_name))
1587
1225
client.add_expected_call(
1588
b'BzrDir.find_repositoryV3', (b'stacked/',),
1589
b'success', (b'ok', b'', b'no', b'no', b'yes',
1590
stacked_branch.repository._format.network_name()))
1226
'BzrDir.find_repositoryV3', ('stacked/',),
1227
'success', ('ok', '', 'no', 'no', 'yes',
1228
stacked_branch.repository._format.network_name()))
1591
1229
# called twice, once from constructor and then again by us
1592
1230
client.add_expected_call(
1593
b'Branch.get_stacked_on_url', (b'stacked/',),
1594
b'unknown', (b'Branch.get_stacked_on_url',))
1231
'Branch.get_stacked_on_url', ('stacked/',),
1232
'unknown', ('Branch.get_stacked_on_url',))
1595
1233
client.add_expected_call(
1596
b'Branch.get_stacked_on_url', (b'stacked/',),
1597
b'unknown', (b'Branch.get_stacked_on_url',))
1234
'Branch.get_stacked_on_url', ('stacked/',),
1235
'unknown', ('Branch.get_stacked_on_url',))
1598
1236
# this will also do vfs access, but that goes direct to the transport
1599
1237
# and isn't seen by the FakeClient.
1600
1238
bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1601
RemoteBzrDirFormat(), _client=client)
1239
remote.RemoteBzrDirFormat(), _client=client)
1602
1240
branch = bzrdir.open_branch()
1603
1241
result = branch.get_stacked_on_url()
1604
1242
self.assertEqual('../base', result)
1654
1292
client = FakeClient(transport.base)
1655
1293
client.add_expected_call(
1656
b'Branch.get_stacked_on_url', (b'branch/',),
1657
b'error', (b'NotStacked',))
1658
client.add_expected_call(
1659
b'Branch.lock_write', (b'branch/', b'', b''),
1660
b'success', (b'ok', b'branch token', b'repo token'))
1661
client.add_expected_call(
1662
b'Branch.last_revision_info',
1664
b'success', (b'ok', b'0', b'null:'))
1665
client.add_expected_call(
1666
b'Branch.set_last_revision', (b'branch/',
1667
b'branch token', b'repo token', b'null:',),
1668
b'success', (b'ok',))
1669
client.add_expected_call(
1670
b'Branch.unlock', (b'branch/', b'branch token', b'repo token'),
1671
b'success', (b'ok',))
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'),
1672
1309
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
1673
1313
branch.lock_write()
1674
result = branch._set_last_revision(NULL_REVISION)
1314
result = branch.set_revision_history([])
1675
1315
branch.unlock()
1676
1316
self.assertEqual(None, result)
1677
1317
self.assertFinished(client)
1679
1319
def test_set_nonempty(self):
1680
# set_last_revision_info(N, rev-idN) is translated to calling
1320
# set_revision_history([rev-id1, ..., rev-idN]) is translated to calling
1681
1321
# Branch.set_last_revision(path, rev-idN) on the wire.
1682
1322
transport = MemoryTransport()
1683
1323
transport.mkdir('branch')
1686
1326
client = FakeClient(transport.base)
1687
1327
client.add_expected_call(
1688
b'Branch.get_stacked_on_url', (b'branch/',),
1689
b'error', (b'NotStacked',))
1690
client.add_expected_call(
1691
b'Branch.lock_write', (b'branch/', b'', b''),
1692
b'success', (b'ok', b'branch token', b'repo token'))
1693
client.add_expected_call(
1694
b'Branch.last_revision_info',
1696
b'success', (b'ok', b'0', b'null:'))
1697
lines = [b'rev-id2']
1698
encoded_body = bz2.compress(b'\n'.join(lines))
1699
client.add_success_response_with_body(encoded_body, b'ok')
1700
client.add_expected_call(
1701
b'Branch.set_last_revision', (b'branch/',
1702
b'branch token', b'repo token', b'rev-id2',),
1703
b'success', (b'ok',))
1704
client.add_expected_call(
1705
b'Branch.unlock', (b'branch/', b'branch token', b'repo token'),
1706
b'success', (b'ok',))
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'),
1707
1346
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
1708
1350
# Lock the branch, reset the record of remote calls.
1709
1351
branch.lock_write()
1710
result = branch._set_last_revision(b'rev-id2')
1352
result = branch.set_revision_history(['rev-id1', 'rev-id2'])
1711
1353
branch.unlock()
1712
1354
self.assertEqual(None, result)
1713
1355
self.assertFinished(client)
1719
1361
# A response of 'NoSuchRevision' is translated into an exception.
1720
1362
client = FakeClient(transport.base)
1721
1363
client.add_expected_call(
1722
b'Branch.get_stacked_on_url', (b'branch/',),
1723
b'error', (b'NotStacked',))
1724
client.add_expected_call(
1725
b'Branch.lock_write', (b'branch/', b'', b''),
1726
b'success', (b'ok', b'branch token', b'repo token'))
1727
client.add_expected_call(
1728
b'Branch.last_revision_info',
1730
b'success', (b'ok', b'0', b'null:'))
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:'))
1731
1373
# get_graph calls to construct the revision history, for the set_rh
1734
encoded_body = bz2.compress(b'\n'.join(lines))
1735
client.add_success_response_with_body(encoded_body, b'ok')
1736
client.add_expected_call(
1737
b'Branch.set_last_revision', (b'branch/',
1738
b'branch token', b'repo token', b'rev-id',),
1739
b'error', (b'NoSuchRevision', b'rev-id'))
1740
client.add_expected_call(
1741
b'Branch.unlock', (b'branch/', b'branch token', b'repo token'),
1742
b'success', (b'ok',))
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'),
1744
1385
branch = self.make_remote_branch(transport, client)
1745
1386
branch.lock_write()
1746
1387
self.assertRaises(
1747
errors.NoSuchRevision, branch._set_last_revision, b'rev-id')
1388
errors.NoSuchRevision, branch.set_revision_history, ['rev-id'])
1748
1389
branch.unlock()
1749
1390
self.assertFinished(client)
1759
1400
rejection_msg_unicode = u'rejection message\N{INTERROBANG}'
1760
1401
rejection_msg_utf8 = rejection_msg_unicode.encode('utf8')
1761
1402
client.add_expected_call(
1762
b'Branch.get_stacked_on_url', (b'branch/',),
1763
b'error', (b'NotStacked',))
1764
client.add_expected_call(
1765
b'Branch.lock_write', (b'branch/', b'', b''),
1766
b'success', (b'ok', b'branch token', b'repo token'))
1767
client.add_expected_call(
1768
b'Branch.last_revision_info',
1770
b'success', (b'ok', b'0', b'null:'))
1772
encoded_body = bz2.compress(b'\n'.join(lines))
1773
client.add_success_response_with_body(encoded_body, b'ok')
1774
client.add_expected_call(
1775
b'Branch.set_last_revision', (b'branch/',
1776
b'branch token', b'repo token', b'rev-id',),
1777
b'error', (b'TipChangeRejected', rejection_msg_utf8))
1778
client.add_expected_call(
1779
b'Branch.unlock', (b'branch/', b'branch token', b'repo token'),
1780
b'success', (b'ok',))
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'),
1781
1421
branch = self.make_remote_branch(transport, client)
1422
branch._ensure_real = lambda: None
1782
1423
branch.lock_write()
1783
1424
# The 'TipChangeRejected' error response triggered by calling
1784
# set_last_revision_info causes a TipChangeRejected exception.
1425
# set_revision_history causes a TipChangeRejected exception.
1785
1426
err = self.assertRaises(
1786
errors.TipChangeRejected,
1787
branch._set_last_revision, b'rev-id')
1427
errors.TipChangeRejected, branch.set_revision_history, ['rev-id'])
1788
1428
# The UTF-8 message from the response has been decoded into a unicode
1790
self.assertIsInstance(err.msg, text_type)
1430
self.assertIsInstance(err.msg, unicode)
1791
1431
self.assertEqual(rejection_msg_unicode, err.msg)
1792
1432
branch.unlock()
1793
1433
self.assertFinished(client)
2015
1652
branch.unlock()
2016
1653
self.assertFinished(client)
2018
def test_set_option_with_dict(self):
2019
client = FakeClient()
2020
client.add_expected_call(
2021
b'Branch.get_stacked_on_url', (b'memory:///',),
2022
b'error', (b'NotStacked',),)
2023
client.add_expected_call(
2024
b'Branch.lock_write', (b'memory:///', b'', b''),
2025
b'success', (b'ok', b'branch token', b'repo token'))
2026
encoded_dict_value = b'd5:ascii1:a11:unicode \xe2\x8c\x9a3:\xe2\x80\xbde'
2027
client.add_expected_call(
2028
b'Branch.set_config_option_dict', (b'memory:///', b'branch token',
2029
b'repo token', encoded_dict_value, b'foo', b''),
2031
client.add_expected_call(
2032
b'Branch.unlock', (b'memory:///', b'branch token', b'repo token'),
2033
b'success', (b'ok',))
2034
transport = MemoryTransport()
2035
branch = self.make_remote_branch(transport, client)
2037
config = branch._get_config()
2039
{'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'},
2042
self.assertFinished(client)
2044
def test_set_option_with_bool(self):
2045
client = FakeClient()
2046
client.add_expected_call(
2047
b'Branch.get_stacked_on_url', (b'memory:///',),
2048
b'error', (b'NotStacked',),)
2049
client.add_expected_call(
2050
b'Branch.lock_write', (b'memory:///', b'', b''),
2051
b'success', (b'ok', b'branch token', b'repo token'))
2052
client.add_expected_call(
2053
b'Branch.set_config_option', (b'memory:///', b'branch token',
2054
b'repo token', b'True', b'foo', b''),
2056
client.add_expected_call(
2057
b'Branch.unlock', (b'memory:///', b'branch token', b'repo token'),
2058
b'success', (b'ok',))
2059
transport = MemoryTransport()
2060
branch = self.make_remote_branch(transport, client)
2062
config = branch._get_config()
2063
config.set_option(True, 'foo')
2065
self.assertFinished(client)
2067
1655
def test_backwards_compat_set_option(self):
2068
1656
self.setup_smart_server_with_call_log()
2069
1657
branch = self.make_branch('.')
2070
verb = b'Branch.set_config_option'
1658
verb = 'Branch.set_config_option'
2071
1659
self.disable_verb(verb)
2072
1660
branch.lock_write()
2073
1661
self.addCleanup(branch.unlock)
2074
1662
self.reset_smart_call_log()
2075
1663
branch._get_config().set_option('value', 'name')
2076
self.assertLength(11, self.hpss_calls)
1664
self.assertLength(10, self.hpss_calls)
2077
1665
self.assertEqual('value', branch._get_config().get_option('name'))
2079
def test_backwards_compat_set_option_with_dict(self):
2080
self.setup_smart_server_with_call_log()
2081
branch = self.make_branch('.')
2082
verb = b'Branch.set_config_option_dict'
2083
self.disable_verb(verb)
2085
self.addCleanup(branch.unlock)
2086
self.reset_smart_call_log()
2087
config = branch._get_config()
2088
value_dict = {'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'}
2089
config.set_option(value_dict, 'name')
2090
self.assertLength(11, self.hpss_calls)
2091
self.assertEqual(value_dict, branch._get_config().get_option('name'))
2094
class TestBranchGetPutConfigStore(RemoteBranchTestCase):
2096
def test_get_branch_conf(self):
2097
# in an empty branch we decode the response properly
2098
client = FakeClient()
2099
client.add_expected_call(
2100
b'Branch.get_stacked_on_url', (b'memory:///',),
2101
b'error', (b'NotStacked',),)
2102
client.add_success_response_with_body(b'# config file body', b'ok')
2103
transport = MemoryTransport()
2104
branch = self.make_remote_branch(transport, client)
2105
config = branch.get_config_stack()
2107
config.get("log_format")
2109
[('call', b'Branch.get_stacked_on_url', (b'memory:///',)),
2110
('call_expecting_body', b'Branch.get_config_file', (b'memory:///',))],
2113
def test_set_branch_conf(self):
2114
client = FakeClient()
2115
client.add_expected_call(
2116
b'Branch.get_stacked_on_url', (b'memory:///',),
2117
b'error', (b'NotStacked',),)
2118
client.add_expected_call(
2119
b'Branch.lock_write', (b'memory:///', b'', b''),
2120
b'success', (b'ok', b'branch token', b'repo token'))
2121
client.add_expected_call(
2122
b'Branch.get_config_file', (b'memory:///', ),
2123
b'success', (b'ok', ), b"# line 1\n")
2124
client.add_expected_call(
2125
b'Branch.get_config_file', (b'memory:///', ),
2126
b'success', (b'ok', ), b"# line 1\n")
2127
client.add_expected_call(
2128
b'Branch.put_config_file', (b'memory:///', b'branch token',
2130
b'success', (b'ok',))
2131
client.add_expected_call(
2132
b'Branch.unlock', (b'memory:///', b'branch token', b'repo token'),
2133
b'success', (b'ok',))
2134
transport = MemoryTransport()
2135
branch = self.make_remote_branch(transport, client)
2137
config = branch.get_config_stack()
2138
config.set('email', 'The Dude <lebowski@example.com>')
2140
self.assertFinished(client)
2142
[('call', b'Branch.get_stacked_on_url', (b'memory:///',)),
2143
('call', b'Branch.lock_write', (b'memory:///', b'', b'')),
2144
('call_expecting_body', b'Branch.get_config_file',
2146
('call_expecting_body', b'Branch.get_config_file',
2148
('call_with_body_bytes_expecting_body', b'Branch.put_config_file',
2149
(b'memory:///', b'branch token', b'repo token'),
2150
b'# line 1\nemail = The Dude <lebowski@example.com>\n'),
2151
('call', b'Branch.unlock',
2152
(b'memory:///', b'branch token', b'repo token'))],
2156
1668
class TestBranchLockWrite(RemoteBranchTestCase):
2171
1683
self.assertFinished(client)
2174
class TestBranchRevisionIdToRevno(RemoteBranchTestCase):
2176
def test_simple(self):
2177
transport = MemoryTransport()
2178
client = FakeClient(transport.base)
2179
client.add_expected_call(
2180
b'Branch.get_stacked_on_url', (b'quack/',),
2181
b'error', (b'NotStacked',),)
2182
client.add_expected_call(
2183
b'Branch.revision_id_to_revno', (b'quack/', b'null:'),
2184
b'success', (b'ok', b'0',),)
2185
client.add_expected_call(
2186
b'Branch.revision_id_to_revno', (b'quack/', b'unknown'),
2187
b'error', (b'NoSuchRevision', b'unknown',),)
2188
transport.mkdir('quack')
2189
transport = transport.clone('quack')
2190
branch = self.make_remote_branch(transport, client)
2191
self.assertEqual(0, branch.revision_id_to_revno(b'null:'))
2192
self.assertRaises(errors.NoSuchRevision,
2193
branch.revision_id_to_revno, b'unknown')
2194
self.assertFinished(client)
2196
def test_dotted(self):
2197
transport = MemoryTransport()
2198
client = FakeClient(transport.base)
2199
client.add_expected_call(
2200
b'Branch.get_stacked_on_url', (b'quack/',),
2201
b'error', (b'NotStacked',),)
2202
client.add_expected_call(
2203
b'Branch.revision_id_to_revno', (b'quack/', b'null:'),
2204
b'success', (b'ok', b'0',),)
2205
client.add_expected_call(
2206
b'Branch.revision_id_to_revno', (b'quack/', b'unknown'),
2207
b'error', (b'NoSuchRevision', b'unknown',),)
2208
transport.mkdir('quack')
2209
transport = transport.clone('quack')
2210
branch = self.make_remote_branch(transport, client)
2211
self.assertEqual((0, ), branch.revision_id_to_dotted_revno(b'null:'))
2212
self.assertRaises(errors.NoSuchRevision,
2213
branch.revision_id_to_dotted_revno, b'unknown')
2214
self.assertFinished(client)
2216
def test_ghost_revid(self):
2217
transport = MemoryTransport()
2218
client = FakeClient(transport.base)
2219
client.add_expected_call(
2220
b'Branch.get_stacked_on_url', (b'quack/',),
2221
b'error', (b'NotStacked',),)
2222
# Some older versions of bzr/brz didn't explicitly return
2223
# GhostRevisionsHaveNoRevno
2224
client.add_expected_call(
2225
b'Branch.revision_id_to_revno', (b'quack/', b'revid'),
2226
b'error', (b'error', b'GhostRevisionsHaveNoRevno',
2227
b'The reivison {revid} was not found because there was '
2228
b'a ghost at {ghost-revid}'))
2229
client.add_expected_call(
2230
b'Branch.revision_id_to_revno', (b'quack/', b'revid'),
2231
b'error', (b'GhostRevisionsHaveNoRevno', b'revid', b'ghost-revid',))
2232
transport.mkdir('quack')
2233
transport = transport.clone('quack')
2234
branch = self.make_remote_branch(transport, client)
2235
self.assertRaises(errors.GhostRevisionsHaveNoRevno,
2236
branch.revision_id_to_dotted_revno, b'revid')
2237
self.assertRaises(errors.GhostRevisionsHaveNoRevno,
2238
branch.revision_id_to_dotted_revno, b'revid')
2239
self.assertFinished(client)
2241
def test_dotted_no_smart_verb(self):
2242
self.setup_smart_server_with_call_log()
2243
branch = self.make_branch('.')
2244
self.disable_verb(b'Branch.revision_id_to_revno')
2245
self.reset_smart_call_log()
2246
self.assertEqual((0, ),
2247
branch.revision_id_to_dotted_revno(b'null:'))
2248
self.assertLength(8, self.hpss_calls)
2251
1686
class TestBzrDirGetSetConfig(RemoteBzrDirTestCase):
2253
1688
def test__get_config(self):
2254
1689
client = FakeClient()
2255
client.add_success_response_with_body(b'default_stack_on = /\n', b'ok')
1690
client.add_success_response_with_body('default_stack_on = /\n', 'ok')
2256
1691
transport = MemoryTransport()
2257
1692
bzrdir = self.make_remote_bzrdir(transport, client)
2258
1693
config = bzrdir.get_config()
2259
1694
self.assertEqual('/', config.get_default_stack_on())
2260
1695
self.assertEqual(
2261
[('call_expecting_body', b'BzrDir.get_config_file',
1696
[('call_expecting_body', 'BzrDir.get_config_file', ('memory:///',))],
2265
1699
def test_set_option_uses_vfs(self):
2266
1700
self.setup_smart_server_with_call_log()
2267
bzrdir = self.make_controldir('.')
1701
bzrdir = self.make_bzrdir('.')
2268
1702
self.reset_smart_call_log()
2269
1703
config = bzrdir.get_config()
2270
1704
config.set_default_stack_on('/')
2271
self.assertLength(4, self.hpss_calls)
1705
self.assertLength(3, self.hpss_calls)
2273
1707
def test_backwards_compat_get_option(self):
2274
1708
self.setup_smart_server_with_call_log()
2275
bzrdir = self.make_controldir('.')
2276
verb = b'BzrDir.get_config_file'
1709
bzrdir = self.make_bzrdir('.')
1710
verb = 'BzrDir.get_config_file'
2277
1711
self.disable_verb(verb)
2278
1712
self.reset_smart_call_log()
2279
1713
self.assertEqual(None,
2280
bzrdir._get_config().get_option('default_stack_on'))
2281
self.assertLength(4, self.hpss_calls)
1714
bzrdir._get_config().get_option('default_stack_on'))
1715
self.assertLength(3, self.hpss_calls)
2284
1718
class TestTransportIsReadonly(tests.TestCase):
2286
1720
def test_true(self):
2287
1721
client = FakeClient()
2288
client.add_success_response(b'yes')
1722
client.add_success_response('yes')
2289
1723
transport = RemoteTransport('bzr://example.com/', medium=False,
2290
1724
_client=client)
2291
1725
self.assertEqual(True, transport.is_readonly())
2292
1726
self.assertEqual(
2293
[('call', b'Transport.is_readonly', ())],
1727
[('call', 'Transport.is_readonly', ())],
2296
1730
def test_false(self):
2297
1731
client = FakeClient()
2298
client.add_success_response(b'no')
1732
client.add_success_response('no')
2299
1733
transport = RemoteTransport('bzr://example.com/', medium=False,
2300
1734
_client=client)
2301
1735
self.assertEqual(False, transport.is_readonly())
2302
1736
self.assertEqual(
2303
[('call', b'Transport.is_readonly', ())],
1737
[('call', 'Transport.is_readonly', ())],
2306
1740
def test_error_from_old_server(self):
2445
1852
transport_path = 'quack'
2446
1853
repo, client = self.setup_fake_client_and_repository(transport_path)
2447
1854
client.add_success_response_with_body(
2448
b'revisions: 2\nsize: 18\n', b'ok')
1855
'revisions: 2\nsize: 18\n', 'ok')
2449
1856
result = repo.gather_stats(None)
2450
1857
self.assertEqual(
2451
[('call_expecting_body', b'Repository.gather_stats',
2452
(b'quack/', b'', b'no'))],
1858
[('call_expecting_body', 'Repository.gather_stats',
1859
('quack/','','no'))],
2454
1861
self.assertEqual({'revisions': 2, 'size': 18}, result)
2456
1863
def test_revid_no_committers(self):
2457
1864
# ('ok',), body without committers
2458
body = (b'firstrev: 123456.300 3600\n'
2459
b'latestrev: 654231.400 0\n'
1865
body = ('firstrev: 123456.300 3600\n'
1866
'latestrev: 654231.400 0\n'
2462
1869
transport_path = 'quick'
2463
1870
revid = u'\xc8'.encode('utf8')
2464
1871
repo, client = self.setup_fake_client_and_repository(transport_path)
2465
client.add_success_response_with_body(body, b'ok')
1872
client.add_success_response_with_body(body, 'ok')
2466
1873
result = repo.gather_stats(revid)
2467
1874
self.assertEqual(
2468
[('call_expecting_body', b'Repository.gather_stats',
2469
(b'quick/', revid, b'no'))],
1875
[('call_expecting_body', 'Repository.gather_stats',
1876
('quick/', revid, 'no'))],
2471
1878
self.assertEqual({'revisions': 2, 'size': 18,
2472
1879
'firstrev': (123456.300, 3600),
2473
'latestrev': (654231.400, 0), },
1880
'latestrev': (654231.400, 0),},
2476
1883
def test_revid_with_committers(self):
2477
1884
# ('ok',), body with committers
2478
body = (b'committers: 128\n'
2479
b'firstrev: 123456.300 3600\n'
2480
b'latestrev: 654231.400 0\n'
1885
body = ('committers: 128\n'
1886
'firstrev: 123456.300 3600\n'
1887
'latestrev: 654231.400 0\n'
2483
1890
transport_path = 'buick'
2484
1891
revid = u'\xc8'.encode('utf8')
2485
1892
repo, client = self.setup_fake_client_and_repository(transport_path)
2486
client.add_success_response_with_body(body, b'ok')
1893
client.add_success_response_with_body(body, 'ok')
2487
1894
result = repo.gather_stats(revid, True)
2488
1895
self.assertEqual(
2489
[('call_expecting_body', b'Repository.gather_stats',
2490
(b'buick/', revid, b'yes'))],
1896
[('call_expecting_body', 'Repository.gather_stats',
1897
('buick/', revid, 'yes'))],
2492
1899
self.assertEqual({'revisions': 2, 'size': 18,
2493
1900
'committers': 128,
2494
1901
'firstrev': (123456.300, 3600),
2495
'latestrev': (654231.400, 0), },
1902
'latestrev': (654231.400, 0),},
2499
class TestRepositoryBreakLock(TestRemoteRepository):
2501
def test_break_lock(self):
2502
transport_path = 'quack'
2503
repo, client = self.setup_fake_client_and_repository(transport_path)
2504
client.add_success_response(b'ok')
2507
[('call', b'Repository.break_lock', (b'quack/',))],
2511
class TestRepositoryGetSerializerFormat(TestRemoteRepository):
2513
def test_get_serializer_format(self):
2514
transport_path = 'hill'
2515
repo, client = self.setup_fake_client_and_repository(transport_path)
2516
client.add_success_response(b'ok', b'7')
2517
self.assertEqual(b'7', repo.get_serializer_format())
2519
[('call', b'VersionedFileRepository.get_serializer_format',
2524
class TestRepositoryReconcile(TestRemoteRepository):
2526
def test_reconcile(self):
2527
transport_path = 'hill'
2528
repo, client = self.setup_fake_client_and_repository(transport_path)
2529
body = (b"garbage_inventories: 2\n"
2530
b"inconsistent_parents: 3\n")
2531
client.add_expected_call(
2532
b'Repository.lock_write', (b'hill/', b''),
2533
b'success', (b'ok', b'a token'))
2534
client.add_success_response_with_body(body, b'ok')
2535
reconciler = repo.reconcile()
2537
[('call', b'Repository.lock_write', (b'hill/', b'')),
2538
('call_expecting_body', b'Repository.reconcile',
2539
(b'hill/', b'a token'))],
2541
self.assertEqual(2, reconciler.garbage_inventories)
2542
self.assertEqual(3, reconciler.inconsistent_parents)
2545
class TestRepositoryGetRevisionSignatureText(TestRemoteRepository):
2547
def test_text(self):
2548
# ('ok',), body with signature text
2549
transport_path = 'quack'
2550
repo, client = self.setup_fake_client_and_repository(transport_path)
2551
client.add_success_response_with_body(
2553
self.assertEqual(b"THETEXT", repo.get_signature_text(b"revid"))
2555
[('call_expecting_body', b'Repository.get_revision_signature_text',
2556
(b'quack/', b'revid'))],
2559
def test_no_signature(self):
2560
transport_path = 'quick'
2561
repo, client = self.setup_fake_client_and_repository(transport_path)
2562
client.add_error_response(b'nosuchrevision', b'unknown')
2563
self.assertRaises(errors.NoSuchRevision, repo.get_signature_text,
2566
[('call_expecting_body', b'Repository.get_revision_signature_text',
2567
(b'quick/', b'unknown'))],
2571
1906
class TestRepositoryGetGraph(TestRemoteRepository):
2573
1908
def test_get_graph(self):
3048
2257
self.setup_smart_server_with_call_log()
3049
2258
tree = self.make_branch_and_memory_tree('.')
3050
2259
tree.lock_write()
3052
2260
rev1 = tree.commit('First')
3053
tree.commit('Second')
2261
rev2 = tree.commit('Second')
3055
2263
branch = tree.branch
3056
2264
self.assertFalse(branch.is_locked())
3057
2265
self.reset_smart_call_log()
3058
verb = b'Repository.get_rev_id_for_revno'
2266
verb = 'Repository.get_rev_id_for_revno'
3059
2267
self.disable_verb(verb)
3060
2268
self.assertEqual(rev1, branch.get_rev_id(1))
3061
2269
self.assertLength(1, [call for call in self.hpss_calls if
3062
2270
call.call.method == verb])
3065
class TestRepositoryHasSignatureForRevisionId(TestRemoteRepository):
3067
def test_has_signature_for_revision_id(self):
3068
# ('yes', ) for Repository.has_signature_for_revision_id -> 'True'.
3069
transport_path = 'quack'
3070
repo, client = self.setup_fake_client_and_repository(transport_path)
3071
client.add_success_response(b'yes')
3072
result = repo.has_signature_for_revision_id(b'A')
3074
[('call', b'Repository.has_signature_for_revision_id',
3075
(b'quack/', b'A'))],
3077
self.assertEqual(True, result)
3079
def test_is_not_shared(self):
3080
# ('no', ) for Repository.has_signature_for_revision_id -> 'False'.
3081
transport_path = 'qwack'
3082
repo, client = self.setup_fake_client_and_repository(transport_path)
3083
client.add_success_response(b'no')
3084
result = repo.has_signature_for_revision_id(b'A')
3086
[('call', b'Repository.has_signature_for_revision_id',
3087
(b'qwack/', b'A'))],
3089
self.assertEqual(False, result)
3092
class TestRepositoryPhysicalLockStatus(TestRemoteRepository):
3094
def test_get_physical_lock_status_yes(self):
3095
transport_path = 'qwack'
3096
repo, client = self.setup_fake_client_and_repository(transport_path)
3097
client.add_success_response(b'yes')
3098
result = repo.get_physical_lock_status()
3100
[('call', b'Repository.get_physical_lock_status',
3103
self.assertEqual(True, result)
3105
def test_get_physical_lock_status_no(self):
3106
transport_path = 'qwack'
3107
repo, client = self.setup_fake_client_and_repository(transport_path)
3108
client.add_success_response(b'no')
3109
result = repo.get_physical_lock_status()
3111
[('call', b'Repository.get_physical_lock_status',
3114
self.assertEqual(False, result)
3117
2273
class TestRepositoryIsShared(TestRemoteRepository):
3119
2275
def test_is_shared(self):
3120
2276
# ('yes', ) for Repository.is_shared -> 'True'.
3121
2277
transport_path = 'quack'
3122
2278
repo, client = self.setup_fake_client_and_repository(transport_path)
3123
client.add_success_response(b'yes')
2279
client.add_success_response('yes')
3124
2280
result = repo.is_shared()
3125
2281
self.assertEqual(
3126
[('call', b'Repository.is_shared', (b'quack/',))],
2282
[('call', 'Repository.is_shared', ('quack/',))],
3128
2284
self.assertEqual(True, result)
3169
2300
def test_lock_write(self):
3170
2301
transport_path = 'quack'
3171
2302
repo, client = self.setup_fake_client_and_repository(transport_path)
3172
client.add_success_response(b'ok', b'a token')
2303
client.add_success_response('ok', 'a token')
3173
2304
token = repo.lock_write().repository_token
3174
2305
self.assertEqual(
3175
[('call', b'Repository.lock_write', (b'quack/', b''))],
2306
[('call', 'Repository.lock_write', ('quack/', ''))],
3177
self.assertEqual(b'a token', token)
2308
self.assertEqual('a token', token)
3179
2310
def test_lock_write_already_locked(self):
3180
2311
transport_path = 'quack'
3181
2312
repo, client = self.setup_fake_client_and_repository(transport_path)
3182
client.add_error_response(b'LockContention')
2313
client.add_error_response('LockContention')
3183
2314
self.assertRaises(errors.LockContention, repo.lock_write)
3184
2315
self.assertEqual(
3185
[('call', b'Repository.lock_write', (b'quack/', b''))],
2316
[('call', 'Repository.lock_write', ('quack/', ''))],
3188
2319
def test_lock_write_unlockable(self):
3189
2320
transport_path = 'quack'
3190
2321
repo, client = self.setup_fake_client_and_repository(transport_path)
3191
client.add_error_response(b'UnlockableTransport')
2322
client.add_error_response('UnlockableTransport')
3192
2323
self.assertRaises(errors.UnlockableTransport, repo.lock_write)
3193
2324
self.assertEqual(
3194
[('call', b'Repository.lock_write', (b'quack/', b''))],
2325
[('call', 'Repository.lock_write', ('quack/', ''))],
3198
class TestRepositoryWriteGroups(TestRemoteRepository):
3200
def test_start_write_group(self):
3201
transport_path = 'quack'
3202
repo, client = self.setup_fake_client_and_repository(transport_path)
3203
client.add_expected_call(
3204
b'Repository.lock_write', (b'quack/', b''),
3205
b'success', (b'ok', b'a token'))
3206
client.add_expected_call(
3207
b'Repository.start_write_group', (b'quack/', b'a token'),
3208
b'success', (b'ok', (b'token1', )))
3210
repo.start_write_group()
3212
def test_start_write_group_unsuspendable(self):
3213
# Some repositories do not support suspending write
3214
# groups. For those, fall back to the "real" repository.
3215
transport_path = 'quack'
3216
repo, client = self.setup_fake_client_and_repository(transport_path)
3218
def stub_ensure_real():
3219
client._calls.append(('_ensure_real',))
3220
repo._real_repository = _StubRealPackRepository(client._calls)
3221
repo._ensure_real = stub_ensure_real
3222
client.add_expected_call(
3223
b'Repository.lock_write', (b'quack/', b''),
3224
b'success', (b'ok', b'a token'))
3225
client.add_expected_call(
3226
b'Repository.start_write_group', (b'quack/', b'a token'),
3227
b'error', (b'UnsuspendableWriteGroup',))
3229
repo.start_write_group()
3230
self.assertEqual(client._calls[-2:], [
3232
('start_write_group',)])
3234
def test_commit_write_group(self):
3235
transport_path = 'quack'
3236
repo, client = self.setup_fake_client_and_repository(transport_path)
3237
client.add_expected_call(
3238
b'Repository.lock_write', (b'quack/', b''),
3239
b'success', (b'ok', b'a token'))
3240
client.add_expected_call(
3241
b'Repository.start_write_group', (b'quack/', b'a token'),
3242
b'success', (b'ok', [b'token1']))
3243
client.add_expected_call(
3244
b'Repository.commit_write_group', (b'quack/',
3245
b'a token', [b'token1']),
3246
b'success', (b'ok',))
3248
repo.start_write_group()
3249
repo.commit_write_group()
3251
def test_abort_write_group(self):
3252
transport_path = 'quack'
3253
repo, client = self.setup_fake_client_and_repository(transport_path)
3254
client.add_expected_call(
3255
b'Repository.lock_write', (b'quack/', b''),
3256
b'success', (b'ok', b'a token'))
3257
client.add_expected_call(
3258
b'Repository.start_write_group', (b'quack/', b'a token'),
3259
b'success', (b'ok', [b'token1']))
3260
client.add_expected_call(
3261
b'Repository.abort_write_group', (b'quack/',
3262
b'a token', [b'token1']),
3263
b'success', (b'ok',))
3265
repo.start_write_group()
3266
repo.abort_write_group(False)
3268
def test_suspend_write_group(self):
3269
transport_path = 'quack'
3270
repo, client = self.setup_fake_client_and_repository(transport_path)
3271
self.assertEqual([], repo.suspend_write_group())
3273
def test_resume_write_group(self):
3274
transport_path = 'quack'
3275
repo, client = self.setup_fake_client_and_repository(transport_path)
3276
client.add_expected_call(
3277
b'Repository.lock_write', (b'quack/', b''),
3278
b'success', (b'ok', b'a token'))
3279
client.add_expected_call(
3280
b'Repository.check_write_group', (b'quack/',
3281
b'a token', [b'token1']),
3282
b'success', (b'ok',))
3284
repo.resume_write_group(['token1'])
3287
2329
class TestRepositorySetMakeWorkingTrees(TestRemoteRepository):
3289
2331
def test_backwards_compat(self):
3290
2332
self.setup_smart_server_with_call_log()
3291
2333
repo = self.make_repository('.')
3292
2334
self.reset_smart_call_log()
3293
verb = b'Repository.set_make_working_trees'
2335
verb = 'Repository.set_make_working_trees'
3294
2336
self.disable_verb(verb)
3295
2337
repo.set_make_working_trees(True)
3296
2338
call_count = len([call for call in self.hpss_calls if
3297
call.call.method == verb])
2339
call.call.method == verb])
3298
2340
self.assertEqual(1, call_count)
3300
2342
def test_current(self):
3301
2343
transport_path = 'quack'
3302
2344
repo, client = self.setup_fake_client_and_repository(transport_path)
3303
2345
client.add_expected_call(
3304
b'Repository.set_make_working_trees', (b'quack/', b'True'),
3305
b'success', (b'ok',))
2346
'Repository.set_make_working_trees', ('quack/', 'True'),
3306
2348
client.add_expected_call(
3307
b'Repository.set_make_working_trees', (b'quack/', b'False'),
3308
b'success', (b'ok',))
2349
'Repository.set_make_working_trees', ('quack/', 'False'),
3309
2351
repo.set_make_working_trees(True)
3310
2352
repo.set_make_working_trees(False)
3404
2419
def setUp(self):
3405
super(TestRepositoryInsertStream, self).setUp()
3406
self.disable_verb(b'Repository.insert_stream_1.19')
2420
TestRemoteRepository.setUp(self)
2421
self.disable_verb('Repository.insert_stream_1.19')
3408
2423
def test_unlocked_repo(self):
3409
2424
transport_path = 'quack'
3410
2425
repo, client = self.setup_fake_client_and_repository(transport_path)
3411
2426
client.add_expected_call(
3412
b'Repository.insert_stream_1.19', (b'quack/', b''),
3413
b'unknown', (b'Repository.insert_stream_1.19',))
3414
client.add_expected_call(
3415
b'Repository.insert_stream', (b'quack/', b''),
3416
b'success', (b'ok',))
3417
client.add_expected_call(
3418
b'Repository.insert_stream', (b'quack/', b''),
3419
b'success', (b'ok',))
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/', ''),
3420
2435
self.checkInsertEmptyStream(repo, client)
3422
2437
def test_locked_repo_with_no_lock_token(self):
3423
2438
transport_path = 'quack'
3424
2439
repo, client = self.setup_fake_client_and_repository(transport_path)
3425
2440
client.add_expected_call(
3426
b'Repository.lock_write', (b'quack/', b''),
3427
b'success', (b'ok', b''))
3428
client.add_expected_call(
3429
b'Repository.insert_stream_1.19', (b'quack/', b''),
3430
b'unknown', (b'Repository.insert_stream_1.19',))
3431
client.add_expected_call(
3432
b'Repository.insert_stream', (b'quack/', b''),
3433
b'success', (b'ok',))
3434
client.add_expected_call(
3435
b'Repository.insert_stream', (b'quack/', b''),
3436
b'success', (b'ok',))
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/', ''),
3437
2452
repo.lock_write()
3438
2453
self.checkInsertEmptyStream(repo, client)
3464
2479
transport_path = 'quack'
3465
2480
repo, client = self.setup_fake_client_and_repository(transport_path)
3466
2481
client.add_expected_call(
3467
b'Repository.insert_stream_1.19', (b'quack/', b''),
3468
b'unknown', (b'Repository.insert_stream_1.19',))
3469
client.add_expected_call(
3470
b'Repository.insert_stream', (b'quack/', b''),
3471
b'success', (b'ok',))
3472
client.add_expected_call(
3473
b'Repository.insert_stream', (b'quack/', b''),
3474
b'success', (b'ok',))
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/', ''),
3475
2490
# Create a fake real repository for insert_stream to fall back on, so
3476
2491
# that we can directly see the records the RemoteSink passes to the
3479
2493
class FakeRealSink:
3480
2494
def __init__(self):
3481
2495
self.records = []
3483
2496
def insert_stream(self, stream, src_format, resume_tokens):
3484
2497
for substream_kind, substream in stream:
3485
2498
self.records.append(
3486
2499
(substream_kind, [record.key for record in substream]))
3487
return [b'fake tokens'], [b'fake missing keys']
2500
return ['fake tokens'], ['fake missing keys']
3488
2501
fake_real_sink = FakeRealSink()
3490
2502
class FakeRealRepository:
3491
2503
def _get_sink(self):
3492
2504
return fake_real_sink
3494
2505
def is_in_write_group(self):
3497
2507
def refresh_data(self):
3499
2509
repo._real_repository = FakeRealRepository()
3500
2510
sink = repo._get_sink()
3501
fmt = repository.format_registry.get_default()
2511
fmt = repository.RepositoryFormat.get_default_format()
3502
2512
stream = self.make_stream_with_inv_deltas(fmt)
3503
2513
resume_tokens, missing_keys = sink.insert_stream(stream, fmt, [])
3504
2514
# Every record from the first inventory delta should have been sent to
3505
2515
# the VFS sink.
3506
2516
expected_records = [
3507
('inventory-deltas', [(b'rev2',), (b'rev3',)]),
3508
('texts', [(b'some-rev', b'some-file')])]
2517
('inventory-deltas', [('rev2',), ('rev3',)]),
2518
('texts', [('some-rev', 'some-file')])]
3509
2519
self.assertEqual(expected_records, fake_real_sink.records)
3510
2520
# The return values from the real sink's insert_stream are propagated
3511
2521
# back to the original caller.
3512
self.assertEqual([b'fake tokens'], resume_tokens)
3513
self.assertEqual([b'fake missing keys'], missing_keys)
2522
self.assertEqual(['fake tokens'], resume_tokens)
2523
self.assertEqual(['fake missing keys'], missing_keys)
3514
2524
self.assertFinished(client)
3516
2526
def make_stream_with_inv_deltas(self, fmt):
3524
2534
* texts substream: (some-rev, some-file)
3526
2536
# Define a stream using generators so that it isn't rewindable.
3527
inv = inventory.Inventory(revision_id=b'rev1')
3528
inv.root.revision = b'rev1'
2537
inv = inventory.Inventory(revision_id='rev1')
2538
inv.root.revision = 'rev1'
3530
2539
def stream_with_inv_delta():
3531
2540
yield ('inventories', inventories_substream())
3532
2541
yield ('inventory-deltas', inventory_delta_substream())
3533
2542
yield ('texts', [
3534
2543
versionedfile.FulltextContentFactory(
3535
(b'some-rev', b'some-file'), (), None, b'content')])
2544
('some-rev', 'some-file'), (), None, 'content')])
3537
2545
def inventories_substream():
3538
2546
# An empty inventory fulltext. This will be streamed normally.
3539
chunks = fmt._serializer.write_inventory_to_lines(inv)
3540
yield versionedfile.ChunkedContentFactory(
3541
(b'rev1',), (), None, chunks, chunks_are_lines=True)
2547
text = fmt._serializer.write_inventory_to_string(inv)
2548
yield versionedfile.FulltextContentFactory(
2549
('rev1',), (), None, text)
3543
2550
def inventory_delta_substream():
3544
2551
# An inventory delta. This can't be streamed via this verb, so it
3545
2552
# will trigger a fallback to VFS insert_stream.
3546
2553
entry = inv.make_entry(
3547
'directory', 'newdir', inv.root.file_id, b'newdir-id')
3548
entry.revision = b'ghost'
3549
delta = [(None, 'newdir', b'newdir-id', entry)]
2554
'directory', 'newdir', inv.root.file_id, 'newdir-id')
2555
entry.revision = 'ghost'
2556
delta = [(None, 'newdir', 'newdir-id', entry)]
3550
2557
serializer = inventory_delta.InventoryDeltaSerializer(
3551
2558
versioned_root=True, tree_references=False)
3552
lines = serializer.delta_to_lines(b'rev1', b'rev2', delta)
2559
lines = serializer.delta_to_lines('rev1', 'rev2', delta)
3553
2560
yield versionedfile.ChunkedContentFactory(
3554
(b'rev2',), ((b'rev1',)), None, lines)
2561
('rev2',), (('rev1',)), None, lines)
3555
2562
# Another delta.
3556
lines = serializer.delta_to_lines(b'rev1', b'rev3', delta)
2563
lines = serializer.delta_to_lines('rev1', 'rev3', delta)
3557
2564
yield versionedfile.ChunkedContentFactory(
3558
(b'rev3',), ((b'rev1',)), None, lines)
2565
('rev3',), (('rev1',)), None, lines)
3559
2566
return stream_with_inv_delta()
3791
2784
def test_NoSuchRevision(self):
3792
2785
branch = self.make_branch('')
3794
2787
translated_error = self.translateTuple(
3795
(b'NoSuchRevision', revid), branch=branch)
2788
('NoSuchRevision', revid), branch=branch)
3796
2789
expected_error = errors.NoSuchRevision(branch, revid)
3797
2790
self.assertEqual(expected_error, translated_error)
3799
2792
def test_nosuchrevision(self):
3800
2793
repository = self.make_repository('')
3802
2795
translated_error = self.translateTuple(
3803
(b'nosuchrevision', revid), repository=repository)
2796
('nosuchrevision', revid), repository=repository)
3804
2797
expected_error = errors.NoSuchRevision(repository, revid)
3805
2798
self.assertEqual(expected_error, translated_error)
3807
2800
def test_nobranch(self):
3808
bzrdir = self.make_controldir('')
3809
translated_error = self.translateTuple((b'nobranch',), bzrdir=bzrdir)
2801
bzrdir = self.make_bzrdir('')
2802
translated_error = self.translateTuple(('nobranch',), bzrdir=bzrdir)
3810
2803
expected_error = errors.NotBranchError(path=bzrdir.root_transport.base)
3811
2804
self.assertEqual(expected_error, translated_error)
3813
2806
def test_nobranch_one_arg(self):
3814
bzrdir = self.make_controldir('')
2807
bzrdir = self.make_bzrdir('')
3815
2808
translated_error = self.translateTuple(
3816
(b'nobranch', b'extra detail'), bzrdir=bzrdir)
2809
('nobranch', 'extra detail'), bzrdir=bzrdir)
3817
2810
expected_error = errors.NotBranchError(
3818
2811
path=bzrdir.root_transport.base,
3819
2812
detail='extra detail')
3820
2813
self.assertEqual(expected_error, translated_error)
3822
def test_norepository(self):
3823
bzrdir = self.make_controldir('')
3824
translated_error = self.translateTuple((b'norepository',),
3826
expected_error = errors.NoRepositoryPresent(bzrdir)
3827
self.assertEqual(expected_error, translated_error)
3829
2815
def test_LockContention(self):
3830
translated_error = self.translateTuple((b'LockContention',))
2816
translated_error = self.translateTuple(('LockContention',))
3831
2817
expected_error = errors.LockContention('(remote lock)')
3832
2818
self.assertEqual(expected_error, translated_error)
3834
2820
def test_UnlockableTransport(self):
3835
bzrdir = self.make_controldir('')
2821
bzrdir = self.make_bzrdir('')
3836
2822
translated_error = self.translateTuple(
3837
(b'UnlockableTransport',), bzrdir=bzrdir)
2823
('UnlockableTransport',), bzrdir=bzrdir)
3838
2824
expected_error = errors.UnlockableTransport(bzrdir.root_transport)
3839
2825
self.assertEqual(expected_error, translated_error)
3841
2827
def test_LockFailed(self):
3842
2828
lock = 'str() of a server lock'
3843
2829
why = 'str() of why'
3844
translated_error = self.translateTuple(
3845
(b'LockFailed', lock.encode('ascii'), why.encode('ascii')))
2830
translated_error = self.translateTuple(('LockFailed', lock, why))
3846
2831
expected_error = errors.LockFailed(lock, why)
3847
2832
self.assertEqual(expected_error, translated_error)
3849
2834
def test_TokenMismatch(self):
3850
2835
token = 'a lock token'
3851
translated_error = self.translateTuple(
3852
(b'TokenMismatch',), token=token)
2836
translated_error = self.translateTuple(('TokenMismatch',), token=token)
3853
2837
expected_error = errors.TokenMismatch(token, '(remote token)')
3854
2838
self.assertEqual(expected_error, translated_error)
3857
2841
branch = self.make_branch('a')
3858
2842
other_branch = self.make_branch('b')
3859
2843
translated_error = self.translateTuple(
3860
(b'Diverged',), branch=branch, other_branch=other_branch)
2844
('Diverged',), branch=branch, other_branch=other_branch)
3861
2845
expected_error = errors.DivergedBranches(branch, other_branch)
3862
2846
self.assertEqual(expected_error, translated_error)
3864
def test_NotStacked(self):
3865
branch = self.make_branch('')
3866
translated_error = self.translateTuple((b'NotStacked',), branch=branch)
3867
expected_error = errors.NotStacked(branch)
3868
self.assertEqual(expected_error, translated_error)
3870
2848
def test_ReadError_no_args(self):
3871
2849
path = 'a path'
3872
translated_error = self.translateTuple((b'ReadError',), path=path)
2850
translated_error = self.translateTuple(('ReadError',), path=path)
3873
2851
expected_error = errors.ReadError(path)
3874
2852
self.assertEqual(expected_error, translated_error)
3876
2854
def test_ReadError(self):
3877
2855
path = 'a path'
3878
translated_error = self.translateTuple(
3879
(b'ReadError', path.encode('utf-8')))
2856
translated_error = self.translateTuple(('ReadError', path))
3880
2857
expected_error = errors.ReadError(path)
3881
2858
self.assertEqual(expected_error, translated_error)
3883
2860
def test_IncompatibleRepositories(self):
3884
translated_error = self.translateTuple((b'IncompatibleRepositories',
3885
b"repo1", b"repo2", b"details here"))
2861
translated_error = self.translateTuple(('IncompatibleRepositories',
2862
"repo1", "repo2", "details here"))
3886
2863
expected_error = errors.IncompatibleRepositories("repo1", "repo2",
3888
self.assertEqual(expected_error, translated_error)
3890
def test_GhostRevisionsHaveNoRevno(self):
3891
translated_error = self.translateTuple((b'GhostRevisionsHaveNoRevno',
3892
b"revid1", b"revid2"))
3893
expected_error = errors.GhostRevisionsHaveNoRevno(b"revid1", b"revid2")
3894
2865
self.assertEqual(expected_error, translated_error)
3896
2867
def test_PermissionDenied_no_args(self):
3897
2868
path = 'a path'
3898
translated_error = self.translateTuple((b'PermissionDenied',),
2869
translated_error = self.translateTuple(('PermissionDenied',), path=path)
3900
2870
expected_error = errors.PermissionDenied(path)
3901
2871
self.assertEqual(expected_error, translated_error)
3903
2873
def test_PermissionDenied_one_arg(self):
3904
2874
path = 'a path'
3905
translated_error = self.translateTuple(
3906
(b'PermissionDenied', path.encode('utf-8')))
2875
translated_error = self.translateTuple(('PermissionDenied', path))
3907
2876
expected_error = errors.PermissionDenied(path)
3908
2877
self.assertEqual(expected_error, translated_error)
3922
2891
path = 'a path'
3923
2892
extra = 'a string with extra info'
3924
2893
translated_error = self.translateTuple(
3925
(b'PermissionDenied', path.encode('utf-8'), extra.encode('utf-8')))
2894
('PermissionDenied', path, extra))
3926
2895
expected_error = errors.PermissionDenied(path, extra)
3927
2896
self.assertEqual(expected_error, translated_error)
3929
# GZ 2011-03-02: TODO test for PermissionDenied with non-ascii 'extra'
3931
def test_NoSuchFile_context_path(self):
3932
local_path = "local path"
3933
translated_error = self.translateTuple((b'ReadError', b"remote path"),
3935
expected_error = errors.ReadError(local_path)
3936
self.assertEqual(expected_error, translated_error)
3938
def test_NoSuchFile_without_context(self):
3939
remote_path = "remote path"
3940
translated_error = self.translateTuple(
3941
(b'ReadError', remote_path.encode('utf-8')))
3942
expected_error = errors.ReadError(remote_path)
3943
self.assertEqual(expected_error, translated_error)
3945
def test_ReadOnlyError(self):
3946
translated_error = self.translateTuple((b'ReadOnlyError',))
3947
expected_error = errors.TransportNotPossible("readonly transport")
3948
self.assertEqual(expected_error, translated_error)
3950
def test_MemoryError(self):
3951
translated_error = self.translateTuple((b'MemoryError',))
3952
self.assertStartsWith(str(translated_error),
3953
"remote server out of memory")
3955
def test_generic_IndexError_no_classname(self):
3956
err = errors.ErrorFromSmartServer(
3957
(b'error', b"list index out of range"))
3958
translated_error = self.translateErrorFromSmartServer(err)
3959
expected_error = errors.UnknownErrorFromSmartServer(err)
3960
self.assertEqual(expected_error, translated_error)
3962
# GZ 2011-03-02: TODO test generic non-ascii error string
3964
def test_generic_KeyError(self):
3965
err = errors.ErrorFromSmartServer((b'error', b'KeyError', b"1"))
3966
translated_error = self.translateErrorFromSmartServer(err)
3967
expected_error = errors.UnknownErrorFromSmartServer(err)
3968
self.assertEqual(expected_error, translated_error)
3970
def test_RevnoOutOfBounds(self):
3971
translated_error = self.translateTuple(
3972
((b'revno-outofbounds', 5, 0, 3)), path=b'path')
3973
expected_error = errors.RevnoOutOfBounds(5, (0, 3))
3974
self.assertEqual(expected_error, translated_error)
3977
2899
class TestErrorTranslationRobustness(TestErrorTranslationBase):
3978
"""Unit tests for breezy.bzr.remote._translate_error's robustness.
2900
"""Unit tests for bzrlib.remote._translate_error's robustness.
3980
2902
TestErrorTranslationSuccess is for cases where _translate_error can
3981
2903
translate successfully. This class about how _translate_err behaves when
4221
3143
def test_copy_content_into_avoids_revision_history(self):
4222
3144
local = self.make_branch('local')
4223
builder = self.make_branch_builder('remote')
4224
builder.build_commit(message="Commit.")
3145
remote_backing_tree = self.make_branch_and_tree('remote')
3146
remote_backing_tree.commit("Commit.")
4225
3147
remote_branch_url = self.smart_server.get_url() + 'remote'
4226
3148
remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
4227
3149
local.repository.fetch(remote_branch.repository)
4228
3150
self.hpss_calls = []
4229
3151
remote_branch.copy_content_into(local)
4230
self.assertFalse(b'Branch.revision_history' in self.hpss_calls)
4232
def test_fetch_everything_needs_just_one_call(self):
4233
local = self.make_branch('local')
4234
builder = self.make_branch_builder('remote')
4235
builder.build_commit(message="Commit.")
4236
remote_branch_url = self.smart_server.get_url() + 'remote'
4237
remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
4238
self.hpss_calls = []
4239
local.repository.fetch(
4240
remote_branch.repository,
4241
fetch_spec=vf_search.EverythingResult(remote_branch.repository))
4242
self.assertEqual([b'Repository.get_stream_1.19'], self.hpss_calls)
4244
def override_verb(self, verb_name, verb):
4245
request_handlers = request.request_handlers
4246
orig_verb = request_handlers.get(verb_name)
4247
orig_info = request_handlers.get_info(verb_name)
4248
request_handlers.register(verb_name, verb, override_existing=True)
4249
self.addCleanup(request_handlers.register, verb_name, orig_verb,
4250
override_existing=True, info=orig_info)
4252
def test_fetch_everything_backwards_compat(self):
4253
"""Can fetch with EverythingResult even with pre 2.4 servers.
4255
Pre-2.4 do not support 'everything' searches with the
4256
Repository.get_stream_1.19 verb.
4260
class OldGetStreamVerb(SmartServerRepositoryGetStream_1_19):
4261
"""A version of the Repository.get_stream_1.19 verb patched to
4262
reject 'everything' searches the way 2.3 and earlier do.
4265
def recreate_search(self, repository, search_bytes,
4266
discard_excess=False):
4267
verb_log.append(search_bytes.split(b'\n', 1)[0])
4268
if search_bytes == b'everything':
4270
request.FailedSmartServerResponse((b'BadSearch',)))
4271
return super(OldGetStreamVerb,
4272
self).recreate_search(repository, search_bytes,
4273
discard_excess=discard_excess)
4274
self.override_verb(b'Repository.get_stream_1.19', OldGetStreamVerb)
4275
local = self.make_branch('local')
4276
builder = self.make_branch_builder('remote')
4277
builder.build_commit(message="Commit.")
4278
remote_branch_url = self.smart_server.get_url() + 'remote'
4279
remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
4280
self.hpss_calls = []
4281
local.repository.fetch(
4282
remote_branch.repository,
4283
fetch_spec=vf_search.EverythingResult(remote_branch.repository))
4284
# make sure the overridden verb was used
4285
self.assertLength(1, verb_log)
4286
# more than one HPSS call is needed, but because it's a VFS callback
4287
# its hard to predict exactly how many.
4288
self.assertTrue(len(self.hpss_calls) > 1)
4291
class TestUpdateBoundBranchWithModifiedBoundLocation(
4292
tests.TestCaseWithTransport):
4293
"""Ensure correct handling of bound_location modifications.
4295
This is tested against a smart server as http://pad.lv/786980 was about a
4296
ReadOnlyError (write attempt during a read-only transaction) which can only
4297
happen in this context.
4301
super(TestUpdateBoundBranchWithModifiedBoundLocation, self).setUp()
4302
self.transport_server = test_server.SmartTCPServer_for_testing
4304
def make_master_and_checkout(self, master_name, checkout_name):
4305
# Create the master branch and its associated checkout
4306
self.master = self.make_branch_and_tree(master_name)
4307
self.checkout = self.master.branch.create_checkout(checkout_name)
4308
# Modify the master branch so there is something to update
4309
self.master.commit('add stuff')
4310
self.last_revid = self.master.commit('even more stuff')
4311
self.bound_location = self.checkout.branch.get_bound_location()
4313
def assertUpdateSucceeds(self, new_location):
4314
self.checkout.branch.set_bound_location(new_location)
4315
self.checkout.update()
4316
self.assertEqual(self.last_revid, self.checkout.last_revision())
4318
def test_without_final_slash(self):
4319
self.make_master_and_checkout('master', 'checkout')
4320
# For unclear reasons some users have a bound_location without a final
4321
# '/', simulate that by forcing such a value
4322
self.assertEndsWith(self.bound_location, '/')
4323
self.assertUpdateSucceeds(self.bound_location.rstrip('/'))
4325
def test_plus_sign(self):
4326
self.make_master_and_checkout('+master', 'checkout')
4327
self.assertUpdateSucceeds(self.bound_location.replace('%2B', '+', 1))
4329
def test_tilda(self):
4330
# Embed ~ in the middle of the path just to avoid any $HOME
4332
self.make_master_and_checkout('mas~ter', 'checkout')
4333
self.assertUpdateSucceeds(self.bound_location.replace('%2E', '~', 1))
4336
class TestWithCustomErrorHandler(RemoteBranchTestCase):
4338
def test_no_context(self):
4339
class OutOfCoffee(errors.BzrError):
4340
"""A dummy exception for testing."""
4342
def __init__(self, urgency):
4343
self.urgency = urgency
4344
remote.no_context_error_translators.register(b"OutOfCoffee",
4345
lambda err: OutOfCoffee(err.error_args[0]))
4346
transport = MemoryTransport()
4347
client = FakeClient(transport.base)
4348
client.add_expected_call(
4349
b'Branch.get_stacked_on_url', (b'quack/',),
4350
b'error', (b'NotStacked',))
4351
client.add_expected_call(
4352
b'Branch.last_revision_info',
4354
b'error', (b'OutOfCoffee', b'low'))
4355
transport.mkdir('quack')
4356
transport = transport.clone('quack')
4357
branch = self.make_remote_branch(transport, client)
4358
self.assertRaises(OutOfCoffee, branch.last_revision_info)
4359
self.assertFinished(client)
4361
def test_with_context(self):
4362
class OutOfTea(errors.BzrError):
4363
def __init__(self, branch, urgency):
4364
self.branch = branch
4365
self.urgency = urgency
4366
remote.error_translators.register(b"OutOfTea",
4367
lambda err, find, path: OutOfTea(
4368
err.error_args[0].decode(
4371
transport = MemoryTransport()
4372
client = FakeClient(transport.base)
4373
client.add_expected_call(
4374
b'Branch.get_stacked_on_url', (b'quack/',),
4375
b'error', (b'NotStacked',))
4376
client.add_expected_call(
4377
b'Branch.last_revision_info',
4379
b'error', (b'OutOfTea', b'low'))
4380
transport.mkdir('quack')
4381
transport = transport.clone('quack')
4382
branch = self.make_remote_branch(transport, client)
4383
self.assertRaises(OutOfTea, branch.last_revision_info)
4384
self.assertFinished(client)
4387
class TestRepositoryPack(TestRemoteRepository):
4389
def test_pack(self):
4390
transport_path = 'quack'
4391
repo, client = self.setup_fake_client_and_repository(transport_path)
4392
client.add_expected_call(
4393
b'Repository.lock_write', (b'quack/', b''),
4394
b'success', (b'ok', b'token'))
4395
client.add_expected_call(
4396
b'Repository.pack', (b'quack/', b'token', b'False'),
4397
b'success', (b'ok',), )
4398
client.add_expected_call(
4399
b'Repository.unlock', (b'quack/', b'token'),
4400
b'success', (b'ok', ))
4403
def test_pack_with_hint(self):
4404
transport_path = 'quack'
4405
repo, client = self.setup_fake_client_and_repository(transport_path)
4406
client.add_expected_call(
4407
b'Repository.lock_write', (b'quack/', b''),
4408
b'success', (b'ok', b'token'))
4409
client.add_expected_call(
4410
b'Repository.pack', (b'quack/', b'token', b'False'),
4411
b'success', (b'ok',), )
4412
client.add_expected_call(
4413
b'Repository.unlock', (b'quack/', b'token', b'False'),
4414
b'success', (b'ok', ))
4415
repo.pack(['hinta', 'hintb'])
4418
class TestRepositoryIterInventories(TestRemoteRepository):
4419
"""Test Repository.iter_inventories."""
4421
def _serialize_inv_delta(self, old_name, new_name, delta):
4422
serializer = inventory_delta.InventoryDeltaSerializer(True, False)
4423
return b"".join(serializer.delta_to_lines(old_name, new_name, delta))
4425
def test_single_empty(self):
4426
transport_path = 'quack'
4427
repo, client = self.setup_fake_client_and_repository(transport_path)
4428
fmt = controldir.format_registry.get('2a')().repository_format
4430
stream = [('inventory-deltas', [
4431
versionedfile.FulltextContentFactory(b'somerevid', None, None,
4432
self._serialize_inv_delta(b'null:', b'somerevid', []))])]
4433
client.add_expected_call(
4434
b'VersionedFileRepository.get_inventories', (
4435
b'quack/', b'unordered'),
4436
b'success', (b'ok', ),
4437
_stream_to_byte_stream(stream, fmt))
4438
ret = list(repo.iter_inventories([b"somerevid"]))
4439
self.assertLength(1, ret)
4441
self.assertEqual(b"somerevid", inv.revision_id)
4443
def test_empty(self):
4444
transport_path = 'quack'
4445
repo, client = self.setup_fake_client_and_repository(transport_path)
4446
ret = list(repo.iter_inventories([]))
4447
self.assertEqual(ret, [])
4449
def test_missing(self):
4450
transport_path = 'quack'
4451
repo, client = self.setup_fake_client_and_repository(transport_path)
4452
client.add_expected_call(
4453
b'VersionedFileRepository.get_inventories', (
4454
b'quack/', b'unordered'),
4455
b'success', (b'ok', ), iter([]))
4456
self.assertRaises(errors.NoSuchRevision, list, repo.iter_inventories(
4460
class TestRepositoryRevisionTreeArchive(TestRemoteRepository):
4461
"""Test Repository.iter_inventories."""
4463
def _serialize_inv_delta(self, old_name, new_name, delta):
4464
serializer = inventory_delta.InventoryDeltaSerializer(True, False)
4465
return b"".join(serializer.delta_to_lines(old_name, new_name, delta))
4467
def test_simple(self):
4468
transport_path = 'quack'
4469
repo, client = self.setup_fake_client_and_repository(transport_path)
4470
fmt = controldir.format_registry.get('2a')().repository_format
4472
stream = [('inventory-deltas', [
4473
versionedfile.FulltextContentFactory(b'somerevid', None, None,
4474
self._serialize_inv_delta(b'null:', b'somerevid', []))])]
4475
client.add_expected_call(
4476
b'VersionedFileRepository.get_inventories', (
4477
b'quack/', b'unordered'),
4478
b'success', (b'ok', ),
4479
_stream_to_byte_stream(stream, fmt))
4481
with tarfile.open(mode='w', fileobj=f) as tf:
4482
info = tarfile.TarInfo('somefile')
4484
contents = b'some data'
4485
info.type = tarfile.REGTYPE
4487
info.size = len(contents)
4488
tf.addfile(info, BytesIO(contents))
4489
client.add_expected_call(
4490
b'Repository.revision_archive', (b'quack/',
4491
b'somerevid', b'tar', b'foo.tar', b'', b'', None),
4492
b'success', (b'ok', ),
4494
tree = repo.revision_tree(b'somerevid')
4495
self.assertEqual(f.getvalue(), b''.join(
4496
tree.archive('tar', 'foo.tar')))
4499
class TestRepositoryAnnotate(TestRemoteRepository):
4500
"""Test RemoteRevisionTree.annotate.."""
4502
def _serialize_inv_delta(self, old_name, new_name, delta):
4503
serializer = inventory_delta.InventoryDeltaSerializer(True, False)
4504
return b"".join(serializer.delta_to_lines(old_name, new_name, delta))
4506
def test_simple(self):
4507
transport_path = 'quack'
4508
repo, client = self.setup_fake_client_and_repository(transport_path)
4509
fmt = controldir.format_registry.get('2a')().repository_format
4512
('inventory-deltas', [
4513
versionedfile.FulltextContentFactory(
4514
b'somerevid', None, None,
4515
self._serialize_inv_delta(b'null:', b'somerevid', []))])]
4516
client.add_expected_call(
4517
b'VersionedFileRepository.get_inventories', (
4518
b'quack/', b'unordered'),
4519
b'success', (b'ok', ),
4520
_stream_to_byte_stream(stream, fmt))
4521
client.add_expected_call(
4522
b'Repository.annotate_file_revision',
4523
(b'quack/', b'somerevid', b'filename', b'', b'current:'),
4524
b'success', (b'ok', ),
4525
bencode.bencode([[b'baserevid', b'line 1\n'],
4526
[b'somerevid', b'line2\n']]))
4527
tree = repo.revision_tree(b'somerevid')
4529
(b'baserevid', b'line 1\n'),
4530
(b'somerevid', b'line2\n')],
4531
list(tree.annotate_iter('filename')))
4534
class TestBranchGetAllReferenceInfo(RemoteBranchTestCase):
4536
def test_get_all_reference_info(self):
4537
transport = MemoryTransport()
4538
client = FakeClient(transport.base)
4539
client.add_expected_call(
4540
b'Branch.get_stacked_on_url', (b'quack/',),
4541
b'error', (b'NotStacked',))
4542
client.add_expected_call(
4543
b'Branch.get_all_reference_info', (b'quack/',),
4544
b'success', (b'ok',), bencode.bencode([
4545
(b'file-id', b'https://www.example.com/', b'')]))
4546
transport.mkdir('quack')
4547
transport = transport.clone('quack')
4548
branch = self.make_remote_branch(transport, client)
4549
result = branch._get_all_reference_info()
4550
self.assertFinished(client)
4551
self.assertEqual({b'file-id': ('https://www.example.com/', None)}, result)
3152
self.assertFalse('Branch.revision_history' in self.hpss_calls)