~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_remote.py

  • Committer: Martin Pool
  • Date: 2009-10-29 06:11:23 UTC
  • mto: This revision was merged to the branch mainline in revision 4776.
  • Revision ID: mbp@sourcefrog.net-20091029061123-vyjm0si2r97rgsp2
one more the the

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2011 Canonical Ltd
 
1
# Copyright (C) 2006, 2007, 2008, 2009 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
27
27
from cStringIO import StringIO
28
28
 
29
29
from bzrlib import (
30
 
    branch,
31
30
    bzrdir,
32
31
    config,
33
 
    controldir,
34
32
    errors,
35
 
    graph as _mod_graph,
 
33
    graph,
36
34
    inventory,
37
35
    inventory_delta,
 
36
    pack,
38
37
    remote,
39
38
    repository,
 
39
    smart,
40
40
    tests,
41
 
    transport,
42
41
    treebuilder,
 
42
    urlutils,
43
43
    versionedfile,
44
44
    )
45
45
from bzrlib.branch import Branch
46
 
from bzrlib.bzrdir import (
47
 
    BzrDir,
48
 
    BzrDirFormat,
49
 
    RemoteBzrProber,
50
 
    )
 
46
from bzrlib.bzrdir import BzrDir, BzrDirFormat
51
47
from bzrlib.remote import (
52
48
    RemoteBranch,
53
49
    RemoteBranchFormat,
56
52
    RemoteRepository,
57
53
    RemoteRepositoryFormat,
58
54
    )
59
 
from bzrlib.repofmt import groupcompress_repo, knitpack_repo
 
55
from bzrlib.repofmt import groupcompress_repo, pack_repo
60
56
from bzrlib.revision import NULL_REVISION
61
 
from bzrlib.smart import medium, request
 
57
from bzrlib.smart import server, medium
62
58
from bzrlib.smart.client import _SmartClient
63
 
from bzrlib.smart.repository import (
64
 
    SmartServerRepositoryGetParentMap,
65
 
    SmartServerRepositoryGetStream_1_19,
66
 
    )
 
59
from bzrlib.smart.repository import SmartServerRepositoryGetParentMap
67
60
from bzrlib.tests import (
68
 
    test_server,
 
61
    condition_isinstance,
 
62
    split_suite_by_condition,
 
63
    multiply_tests,
 
64
    KnownFailure,
69
65
    )
70
 
from bzrlib.tests.scenarios import load_tests_apply_scenarios
 
66
from bzrlib.transport import get_transport, http
71
67
from bzrlib.transport.memory import MemoryTransport
72
68
from bzrlib.transport.remote import (
73
69
    RemoteTransport,
74
70
    RemoteSSHTransport,
75
71
    RemoteTCPTransport,
76
 
    )
77
 
 
78
 
 
79
 
load_tests = load_tests_apply_scenarios
80
 
 
81
 
 
82
 
class BasicRemoteObjectTests(tests.TestCaseWithTransport):
83
 
 
84
 
    scenarios = [
 
72
)
 
73
 
 
74
def load_tests(standard_tests, module, loader):
 
75
    to_adapt, result = split_suite_by_condition(
 
76
        standard_tests, condition_isinstance(BasicRemoteObjectTests))
 
77
    smart_server_version_scenarios = [
85
78
        ('HPSS-v2',
86
 
            {'transport_server': test_server.SmartTCPServer_for_testing_v2_only}),
 
79
            {'transport_server': server.SmartTCPServer_for_testing_v2_only}),
87
80
        ('HPSS-v3',
88
 
            {'transport_server': test_server.SmartTCPServer_for_testing})]
89
 
 
 
81
            {'transport_server': server.SmartTCPServer_for_testing})]
 
82
    return multiply_tests(to_adapt, smart_server_version_scenarios, result)
 
83
 
 
84
 
 
85
class BasicRemoteObjectTests(tests.TestCaseWithTransport):
90
86
 
91
87
    def setUp(self):
92
88
        super(BasicRemoteObjectTests, self).setUp()
93
89
        self.transport = self.get_transport()
94
90
        # make a branch that can be opened over the smart transport
95
91
        self.local_wt = BzrDir.create_standalone_workingtree('.')
96
 
        self.addCleanup(self.transport.disconnect)
 
92
 
 
93
    def tearDown(self):
 
94
        self.transport.disconnect()
 
95
        tests.TestCaseWithTransport.tearDown(self)
97
96
 
98
97
    def test_create_remote_bzrdir(self):
99
 
        b = remote.RemoteBzrDir(self.transport, RemoteBzrDirFormat())
 
98
        b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
100
99
        self.assertIsInstance(b, BzrDir)
101
100
 
102
101
    def test_open_remote_branch(self):
103
102
        # open a standalone branch in the working directory
104
 
        b = remote.RemoteBzrDir(self.transport, RemoteBzrDirFormat())
 
103
        b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
105
104
        branch = b.open_branch()
106
105
        self.assertIsInstance(branch, Branch)
107
106
 
123
122
    def test_find_correct_format(self):
124
123
        """Should open a RemoteBzrDir over a RemoteTransport"""
125
124
        fmt = BzrDirFormat.find_format(self.transport)
126
 
        self.assertTrue(bzrdir.RemoteBzrProber
127
 
                        in controldir.ControlDirFormat._server_probers)
128
 
        self.assertIsInstance(fmt, RemoteBzrDirFormat)
 
125
        self.assertTrue(RemoteBzrDirFormat
 
126
                        in BzrDirFormat._control_server_formats)
 
127
        self.assertIsInstance(fmt, remote.RemoteBzrDirFormat)
129
128
 
130
129
    def test_open_detected_smart_format(self):
131
130
        fmt = BzrDirFormat.find_format(self.transport)
136
135
        b = BzrDir.open_from_transport(self.transport).open_branch()
137
136
        self.assertStartsWith(str(b), 'RemoteBranch(')
138
137
 
139
 
    def test_remote_bzrdir_repr(self):
140
 
        b = BzrDir.open_from_transport(self.transport)
141
 
        self.assertStartsWith(str(b), 'RemoteBzrDir(')
142
 
 
143
138
    def test_remote_branch_format_supports_stacking(self):
144
139
        t = self.transport
145
140
        self.make_branch('unstackable', format='pack-0.92')
360
355
        a given client_base and transport_base.
361
356
        """
362
357
        client_medium = medium.SmartClientMedium(client_base)
363
 
        t = transport.get_transport(transport_base)
364
 
        result = client_medium.remote_path_from_transport(t)
 
358
        transport = get_transport(transport_base)
 
359
        result = client_medium.remote_path_from_transport(transport)
365
360
        self.assertEqual(expected, result)
366
361
 
367
362
    def test_remote_path_from_transport(self):
378
373
        a given transport_base and relpath of that transport.  (Note that
379
374
        HttpTransportBase is a subclass of SmartClientMedium)
380
375
        """
381
 
        base_transport = transport.get_transport(transport_base)
 
376
        base_transport = get_transport(transport_base)
382
377
        client_medium = base_transport.get_smart_medium()
383
378
        cloned_transport = base_transport.clone(relpath)
384
379
        result = client_medium.remote_path_from_transport(cloned_transport)
419
414
        # Calling _remember_remote_is_before again with a lower value works.
420
415
        client_medium._remember_remote_is_before((1, 5))
421
416
        self.assertTrue(client_medium._is_remote_before((1, 5)))
422
 
        # If you call _remember_remote_is_before with a higher value it logs a
423
 
        # warning, and continues to remember the lower value.
424
 
        self.assertNotContainsRe(self.get_log(), '_remember_remote_is_before')
425
 
        client_medium._remember_remote_is_before((1, 9))
426
 
        self.assertContainsRe(self.get_log(), '_remember_remote_is_before')
427
 
        self.assertTrue(client_medium._is_remote_before((1, 5)))
 
417
        # You cannot call _remember_remote_is_before with a larger value.
 
418
        self.assertRaises(
 
419
            AssertionError, client_medium._remember_remote_is_before, (1, 9))
428
420
 
429
421
 
430
422
class TestBzrDirCloningMetaDir(TestRemote):
449
441
            'BzrDir.cloning_metadir', ('quack/', 'False'),
450
442
            'error', ('BranchReference',)),
451
443
        client.add_expected_call(
452
 
            'BzrDir.open_branchV3', ('quack/',),
 
444
            'BzrDir.open_branchV2', ('quack/',),
453
445
            'success', ('ref', self.get_url('referenced'))),
454
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
446
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
455
447
            _client=client)
456
448
        result = a_bzrdir.cloning_metadir()
457
449
        # We should have got a control dir matching the referenced branch.
470
462
        client.add_expected_call(
471
463
            'BzrDir.cloning_metadir', ('quack/', 'False'),
472
464
            'success', (control_name, '', ('branch', ''))),
473
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
465
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
474
466
            _client=client)
475
467
        result = a_bzrdir.cloning_metadir()
476
468
        # We should have got a reference control dir with default branch and
496
488
        client.add_expected_call(
497
489
            'BzrDir.open_2.1', ('quack/',), 'success', ('no',))
498
490
        self.assertRaises(errors.NotBranchError, RemoteBzrDir, transport,
499
 
                RemoteBzrDirFormat(), _client=client, _force_probe=True)
 
491
                remote.RemoteBzrDirFormat(), _client=client, _force_probe=True)
500
492
        self.assertFinished(client)
501
493
 
502
494
    def test_present_without_workingtree(self):
503
495
        client, transport = self.make_fake_client_and_transport()
504
496
        client.add_expected_call(
505
497
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'no'))
506
 
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
498
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
507
499
            _client=client, _force_probe=True)
508
500
        self.assertIsInstance(bd, RemoteBzrDir)
509
501
        self.assertFalse(bd.has_workingtree())
514
506
        client, transport = self.make_fake_client_and_transport()
515
507
        client.add_expected_call(
516
508
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'yes'))
517
 
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
509
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
518
510
            _client=client, _force_probe=True)
519
511
        self.assertIsInstance(bd, RemoteBzrDir)
520
512
        self.assertTrue(bd.has_workingtree())
527
519
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
528
520
        client.add_expected_call(
529
521
            'BzrDir.open', ('quack/',), 'success', ('yes',))
530
 
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
531
 
            _client=client, _force_probe=True)
532
 
        self.assertIsInstance(bd, RemoteBzrDir)
533
 
        self.assertFinished(client)
534
 
 
535
 
    def test_backwards_compat_hpss_v2(self):
536
 
        client, transport = self.make_fake_client_and_transport()
537
 
        # Monkey-patch fake client to simulate real-world behaviour with v2
538
 
        # server: upon first RPC call detect the protocol version, and because
539
 
        # the version is 2 also do _remember_remote_is_before((1, 6)) before
540
 
        # continuing with the RPC.
541
 
        orig_check_call = client._check_call
542
 
        def check_call(method, args):
543
 
            client._medium._protocol_version = 2
544
 
            client._medium._remember_remote_is_before((1, 6))
545
 
            client._check_call = orig_check_call
546
 
            client._check_call(method, args)
547
 
        client._check_call = check_call
548
 
        client.add_expected_call(
549
 
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
550
 
        client.add_expected_call(
551
 
            'BzrDir.open', ('quack/',), 'success', ('yes',))
552
 
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
522
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
553
523
            _client=client, _force_probe=True)
554
524
        self.assertIsInstance(bd, RemoteBzrDir)
555
525
        self.assertFinished(client)
562
532
        self.make_branch('.')
563
533
        a_dir = BzrDir.open(self.get_url('.'))
564
534
        self.reset_smart_call_log()
565
 
        verb = 'BzrDir.open_branchV3'
 
535
        verb = 'BzrDir.open_branchV2'
566
536
        self.disable_verb(verb)
567
537
        format = a_dir.open_branch()
568
538
        call_count = len([call for call in self.hpss_calls if
578
548
        transport = transport.clone('quack')
579
549
        client = FakeClient(transport.base)
580
550
        client.add_expected_call(
581
 
            'BzrDir.open_branchV3', ('quack/',),
 
551
            'BzrDir.open_branchV2', ('quack/',),
582
552
            'success', ('branch', branch_network_name))
583
553
        client.add_expected_call(
584
554
            'BzrDir.find_repositoryV3', ('quack/',),
586
556
        client.add_expected_call(
587
557
            'Branch.get_stacked_on_url', ('quack/',),
588
558
            'error', ('NotStacked',))
589
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
559
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
590
560
            _client=client)
591
561
        result = bzrdir.open_branch()
592
562
        self.assertIsInstance(result, RemoteBranch)
599
569
        transport = transport.clone('quack')
600
570
        client = FakeClient(transport.base)
601
571
        client.add_error_response('nobranch')
602
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
572
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
603
573
            _client=client)
604
574
        self.assertRaises(errors.NotBranchError, bzrdir.open_branch)
605
575
        self.assertEqual(
606
 
            [('call', 'BzrDir.open_branchV3', ('quack/',))],
 
576
            [('call', 'BzrDir.open_branchV2', ('quack/',))],
607
577
            client._calls)
608
578
 
609
579
    def test__get_tree_branch(self):
610
580
        # _get_tree_branch is a form of open_branch, but it should only ask for
611
581
        # branch opening, not any other network requests.
612
582
        calls = []
613
 
        def open_branch(name=None):
 
583
        def open_branch():
614
584
            calls.append("Called")
615
585
            return "a-branch"
616
586
        transport = MemoryTransport()
617
587
        # no requests on the network - catches other api calls being made.
618
588
        client = FakeClient(transport.base)
619
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
589
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
620
590
            _client=client)
621
591
        # patch the open_branch call to record that it was called.
622
592
        bzrdir.open_branch = open_branch
633
603
        network_name = reference_format.network_name()
634
604
        branch_network_name = self.get_branch_format().network_name()
635
605
        client.add_expected_call(
636
 
            'BzrDir.open_branchV3', ('~hello/',),
 
606
            'BzrDir.open_branchV2', ('~hello/',),
637
607
            'success', ('branch', branch_network_name))
638
608
        client.add_expected_call(
639
609
            'BzrDir.find_repositoryV3', ('~hello/',),
641
611
        client.add_expected_call(
642
612
            'Branch.get_stacked_on_url', ('~hello/',),
643
613
            'error', ('NotStacked',))
644
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
614
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
645
615
            _client=client)
646
616
        result = bzrdir.open_branch()
647
617
        self.assertFinished(client)
664
634
        client.add_success_response(
665
635
            'ok', '', rich_response, subtree_response, external_lookup,
666
636
            network_name)
667
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
637
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
668
638
            _client=client)
669
639
        result = bzrdir.open_repository()
670
640
        self.assertEqual(
687
657
        old.
688
658
        """
689
659
        self.assertRaises(errors.NotBranchError,
690
 
            RemoteBzrProber.probe_transport, OldServerTransport())
 
660
            RemoteBzrDirFormat.probe_transport, OldServerTransport())
691
661
 
692
662
 
693
663
class TestBzrDirCreateBranch(TestRemote):
716
686
            'BzrDir.create_branch', ('quack/', network_name),
717
687
            'success', ('ok', network_name, '', 'no', 'no', 'yes',
718
688
            reference_repo_name))
719
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
689
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
720
690
            _client=client)
721
691
        branch = a_bzrdir.create_branch()
722
692
        # We should have got a remote branch
725
695
        format = branch._format
726
696
        self.assertEqual(network_name, format.network_name())
727
697
 
728
 
    def test_already_open_repo_and_reused_medium(self):
729
 
        """Bug 726584: create_branch(..., repository=repo) should work
730
 
        regardless of what the smart medium's base URL is.
731
 
        """
732
 
        self.transport_server = test_server.SmartTCPServer_for_testing
733
 
        transport = self.get_transport('.')
734
 
        repo = self.make_repository('quack')
735
 
        # Client's medium rooted a transport root (not at the bzrdir)
736
 
        client = FakeClient(transport.base)
737
 
        transport = transport.clone('quack')
738
 
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
739
 
        reference_format = reference_bzrdir_format.get_branch_format()
740
 
        network_name = reference_format.network_name()
741
 
        reference_repo_fmt = reference_bzrdir_format.repository_format
742
 
        reference_repo_name = reference_repo_fmt.network_name()
743
 
        client.add_expected_call(
744
 
            'BzrDir.create_branch', ('extra/quack/', network_name),
745
 
            'success', ('ok', network_name, '', 'no', 'no', 'yes',
746
 
            reference_repo_name))
747
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
748
 
            _client=client)
749
 
        branch = a_bzrdir.create_branch(repository=repo)
750
 
        # We should have got a remote branch
751
 
        self.assertIsInstance(branch, remote.RemoteBranch)
752
 
        # its format should have the settings from the response
753
 
        format = branch._format
754
 
        self.assertEqual(network_name, format.network_name())
755
 
 
756
698
 
757
699
class TestBzrDirCreateRepository(TestRemote):
758
700
 
779
721
                'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
780
722
                'False'),
781
723
            'success', ('ok', 'yes', 'yes', 'yes', network_name))
782
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
724
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
783
725
            _client=client)
784
726
        repo = a_bzrdir.create_repository()
785
727
        # We should have got a remote repository
814
756
        client.add_success_response('stat', '0', '65535')
815
757
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
816
758
            _client=client)
817
 
        bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
 
759
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
818
760
            _client=client)
819
761
        repo = bzrdir.open_repository()
820
762
        self.assertEqual(
847
789
        client.add_success_response('stat', '0', '65535')
848
790
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
849
791
            _client=client)
850
 
        bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
 
792
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
851
793
            _client=client)
852
794
        repo = bzrdir.open_repository()
853
795
        self.assertEqual(
868
810
        transport = transport.clone('quack')
869
811
        client = FakeClient(transport.base)
870
812
        client.add_success_response('ok', '', 'no', 'no', 'no', network_name)
871
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
813
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
872
814
            _client=client)
873
815
        repo = bzrdir.open_repository()
874
816
        self.assertEqual(
881
823
 
882
824
    def test_success(self):
883
825
        """Simple test for typical successful call."""
884
 
        fmt = RemoteBzrDirFormat()
 
826
        fmt = bzrdir.RemoteBzrDirFormat()
885
827
        default_format_name = BzrDirFormat.get_default_format().network_name()
886
828
        transport = self.get_transport()
887
829
        client = FakeClient(transport.base)
903
845
        """Error responses are translated, e.g. 'PermissionDenied' raises the
904
846
        corresponding error from the client.
905
847
        """
906
 
        fmt = RemoteBzrDirFormat()
 
848
        fmt = bzrdir.RemoteBzrDirFormat()
907
849
        default_format_name = BzrDirFormat.get_default_format().network_name()
908
850
        transport = self.get_transport()
909
851
        client = FakeClient(transport.base)
927
869
        """Integration test for error translation."""
928
870
        transport = self.make_smart_server('foo')
929
871
        transport = transport.clone('no-such-path')
930
 
        fmt = RemoteBzrDirFormat()
 
872
        fmt = bzrdir.RemoteBzrDirFormat()
931
873
        err = self.assertRaises(errors.NoSuchFile,
932
874
            fmt.initialize_on_transport_ex, transport, create_prefix=False)
933
875
 
964
906
 
965
907
    def make_remote_bzrdir(self, transport, client):
966
908
        """Make a RemotebzrDir using 'client' as the _client."""
967
 
        return RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
909
        return RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
968
910
            _client=client)
969
911
 
970
912
 
1172
1114
            [('set_tags_bytes', 'tags bytes')] * 2, real_branch.calls)
1173
1115
 
1174
1116
 
1175
 
class TestBranchHeadsToFetch(RemoteBranchTestCase):
1176
 
 
1177
 
    def test_uses_last_revision_info_and_tags_by_default(self):
1178
 
        transport = MemoryTransport()
1179
 
        client = FakeClient(transport.base)
1180
 
        client.add_expected_call(
1181
 
            'Branch.get_stacked_on_url', ('quack/',),
1182
 
            'error', ('NotStacked',))
1183
 
        client.add_expected_call(
1184
 
            'Branch.last_revision_info', ('quack/',),
1185
 
            'success', ('ok', '1', 'rev-tip'))
1186
 
        client.add_expected_call(
1187
 
            'Branch.get_config_file', ('quack/',),
1188
 
            'success', ('ok',), '')
1189
 
        transport.mkdir('quack')
1190
 
        transport = transport.clone('quack')
1191
 
        branch = self.make_remote_branch(transport, client)
1192
 
        result = branch.heads_to_fetch()
1193
 
        self.assertFinished(client)
1194
 
        self.assertEqual((set(['rev-tip']), set()), result)
1195
 
 
1196
 
    def test_uses_last_revision_info_and_tags_when_set(self):
1197
 
        transport = MemoryTransport()
1198
 
        client = FakeClient(transport.base)
1199
 
        client.add_expected_call(
1200
 
            'Branch.get_stacked_on_url', ('quack/',),
1201
 
            'error', ('NotStacked',))
1202
 
        client.add_expected_call(
1203
 
            'Branch.last_revision_info', ('quack/',),
1204
 
            'success', ('ok', '1', 'rev-tip'))
1205
 
        client.add_expected_call(
1206
 
            'Branch.get_config_file', ('quack/',),
1207
 
            'success', ('ok',), 'branch.fetch_tags = True')
1208
 
        # XXX: this will break if the default format's serialization of tags
1209
 
        # changes, or if the RPC for fetching tags changes from get_tags_bytes.
1210
 
        client.add_expected_call(
1211
 
            'Branch.get_tags_bytes', ('quack/',),
1212
 
            'success', ('d5:tag-17:rev-foo5:tag-27:rev-bare',))
1213
 
        transport.mkdir('quack')
1214
 
        transport = transport.clone('quack')
1215
 
        branch = self.make_remote_branch(transport, client)
1216
 
        result = branch.heads_to_fetch()
1217
 
        self.assertFinished(client)
1218
 
        self.assertEqual(
1219
 
            (set(['rev-tip']), set(['rev-foo', 'rev-bar'])), result)
1220
 
 
1221
 
    def test_uses_rpc_for_formats_with_non_default_heads_to_fetch(self):
1222
 
        transport = MemoryTransport()
1223
 
        client = FakeClient(transport.base)
1224
 
        client.add_expected_call(
1225
 
            'Branch.get_stacked_on_url', ('quack/',),
1226
 
            'error', ('NotStacked',))
1227
 
        client.add_expected_call(
1228
 
            'Branch.heads_to_fetch', ('quack/',),
1229
 
            'success', (['tip'], ['tagged-1', 'tagged-2']))
1230
 
        transport.mkdir('quack')
1231
 
        transport = transport.clone('quack')
1232
 
        branch = self.make_remote_branch(transport, client)
1233
 
        branch._format._use_default_local_heads_to_fetch = lambda: False
1234
 
        result = branch.heads_to_fetch()
1235
 
        self.assertFinished(client)
1236
 
        self.assertEqual((set(['tip']), set(['tagged-1', 'tagged-2'])), result)
1237
 
 
1238
 
    def make_branch_with_tags(self):
1239
 
        self.setup_smart_server_with_call_log()
1240
 
        # Make a branch with a single revision.
1241
 
        builder = self.make_branch_builder('foo')
1242
 
        builder.start_series()
1243
 
        builder.build_snapshot('tip', None, [
1244
 
            ('add', ('', 'root-id', 'directory', ''))])
1245
 
        builder.finish_series()
1246
 
        branch = builder.get_branch()
1247
 
        # Add two tags to that branch
1248
 
        branch.tags.set_tag('tag-1', 'rev-1')
1249
 
        branch.tags.set_tag('tag-2', 'rev-2')
1250
 
        return branch
1251
 
 
1252
 
    def test_backwards_compatible(self):
1253
 
        branch = self.make_branch_with_tags()
1254
 
        c = branch.get_config()
1255
 
        c.set_user_option('branch.fetch_tags', 'True')
1256
 
        self.addCleanup(branch.lock_read().unlock)
1257
 
        # Disable the heads_to_fetch verb
1258
 
        verb = 'Branch.heads_to_fetch'
1259
 
        self.disable_verb(verb)
1260
 
        self.reset_smart_call_log()
1261
 
        result = branch.heads_to_fetch()
1262
 
        self.assertEqual((set(['tip']), set(['rev-1', 'rev-2'])), result)
1263
 
        self.assertEqual(
1264
 
            ['Branch.last_revision_info', 'Branch.get_config_file',
1265
 
             'Branch.get_tags_bytes'],
1266
 
            [call.call.method for call in self.hpss_calls])
1267
 
 
1268
 
    def test_backwards_compatible_no_tags(self):
1269
 
        branch = self.make_branch_with_tags()
1270
 
        c = branch.get_config()
1271
 
        c.set_user_option('branch.fetch_tags', 'False')
1272
 
        self.addCleanup(branch.lock_read().unlock)
1273
 
        # Disable the heads_to_fetch verb
1274
 
        verb = 'Branch.heads_to_fetch'
1275
 
        self.disable_verb(verb)
1276
 
        self.reset_smart_call_log()
1277
 
        result = branch.heads_to_fetch()
1278
 
        self.assertEqual((set(['tip']), set()), result)
1279
 
        self.assertEqual(
1280
 
            ['Branch.last_revision_info', 'Branch.get_config_file'],
1281
 
            [call.call.method for call in self.hpss_calls])
1282
 
 
1283
 
 
1284
1117
class TestBranchLastRevisionInfo(RemoteBranchTestCase):
1285
1118
 
1286
1119
    def test_empty_branch(self):
1341
1174
        client.add_expected_call(
1342
1175
            'Branch.get_stacked_on_url', ('stacked/',),
1343
1176
            'success', ('ok', vfs_url))
1344
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
1177
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1345
1178
            _client=client)
1346
1179
        repo_fmt = remote.RemoteRepositoryFormat()
1347
1180
        repo_fmt._custom_format = stacked_branch.repository._format
1358
1191
        client = FakeClient(self.get_url())
1359
1192
        branch_network_name = self.get_branch_format().network_name()
1360
1193
        client.add_expected_call(
1361
 
            'BzrDir.open_branchV3', ('stacked/',),
 
1194
            'BzrDir.open_branchV2', ('stacked/',),
1362
1195
            'success', ('branch', branch_network_name))
1363
1196
        client.add_expected_call(
1364
1197
            'BzrDir.find_repositoryV3', ('stacked/',),
1374
1207
        # this will also do vfs access, but that goes direct to the transport
1375
1208
        # and isn't seen by the FakeClient.
1376
1209
        bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1377
 
            RemoteBzrDirFormat(), _client=client)
 
1210
            remote.RemoteBzrDirFormat(), _client=client)
1378
1211
        branch = bzrdir.open_branch()
1379
1212
        result = branch.get_stacked_on_url()
1380
1213
        self.assertEqual('../base', result)
1386
1219
            len(branch.repository._real_repository._fallback_repositories))
1387
1220
 
1388
1221
    def test_get_stacked_on_real_branch(self):
1389
 
        base_branch = self.make_branch('base')
1390
 
        stacked_branch = self.make_branch('stacked')
 
1222
        base_branch = self.make_branch('base', format='1.6')
 
1223
        stacked_branch = self.make_branch('stacked', format='1.6')
1391
1224
        stacked_branch.set_stacked_on_url('../base')
1392
1225
        reference_format = self.get_repo_format()
1393
1226
        network_name = reference_format.network_name()
1394
1227
        client = FakeClient(self.get_url())
1395
1228
        branch_network_name = self.get_branch_format().network_name()
1396
1229
        client.add_expected_call(
1397
 
            'BzrDir.open_branchV3', ('stacked/',),
 
1230
            'BzrDir.open_branchV2', ('stacked/',),
1398
1231
            'success', ('branch', branch_network_name))
1399
1232
        client.add_expected_call(
1400
1233
            'BzrDir.find_repositoryV3', ('stacked/',),
1401
 
            'success', ('ok', '', 'yes', 'no', 'yes', network_name))
 
1234
            'success', ('ok', '', 'no', 'no', 'yes', network_name))
1402
1235
        # called twice, once from constructor and then again by us
1403
1236
        client.add_expected_call(
1404
1237
            'Branch.get_stacked_on_url', ('stacked/',),
1407
1240
            'Branch.get_stacked_on_url', ('stacked/',),
1408
1241
            'success', ('ok', '../base'))
1409
1242
        bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1410
 
            RemoteBzrDirFormat(), _client=client)
 
1243
            remote.RemoteBzrDirFormat(), _client=client)
1411
1244
        branch = bzrdir.open_branch()
1412
1245
        result = branch.get_stacked_on_url()
1413
1246
        self.assertEqual('../base', result)
1421
1254
class TestBranchSetLastRevision(RemoteBranchTestCase):
1422
1255
 
1423
1256
    def test_set_empty(self):
1424
 
        # _set_last_revision_info('null:') is translated to calling
 
1257
        # set_revision_history([]) is translated to calling
1425
1258
        # Branch.set_last_revision(path, '') on the wire.
1426
1259
        transport = MemoryTransport()
1427
1260
        transport.mkdir('branch')
1449
1282
        # unnecessarily invokes _ensure_real upon a call to lock_write.
1450
1283
        branch._ensure_real = lambda: None
1451
1284
        branch.lock_write()
1452
 
        result = branch._set_last_revision(NULL_REVISION)
 
1285
        result = branch.set_revision_history([])
1453
1286
        branch.unlock()
1454
1287
        self.assertEqual(None, result)
1455
1288
        self.assertFinished(client)
1456
1289
 
1457
1290
    def test_set_nonempty(self):
1458
 
        # set_last_revision_info(N, rev-idN) is translated to calling
 
1291
        # set_revision_history([rev-id1, ..., rev-idN]) is translated to calling
1459
1292
        # Branch.set_last_revision(path, rev-idN) on the wire.
1460
1293
        transport = MemoryTransport()
1461
1294
        transport.mkdir('branch')
1487
1320
        branch._ensure_real = lambda: None
1488
1321
        # Lock the branch, reset the record of remote calls.
1489
1322
        branch.lock_write()
1490
 
        result = branch._set_last_revision('rev-id2')
 
1323
        result = branch.set_revision_history(['rev-id1', 'rev-id2'])
1491
1324
        branch.unlock()
1492
1325
        self.assertEqual(None, result)
1493
1326
        self.assertFinished(client)
1523
1356
        branch = self.make_remote_branch(transport, client)
1524
1357
        branch.lock_write()
1525
1358
        self.assertRaises(
1526
 
            errors.NoSuchRevision, branch._set_last_revision, 'rev-id')
 
1359
            errors.NoSuchRevision, branch.set_revision_history, ['rev-id'])
1527
1360
        branch.unlock()
1528
1361
        self.assertFinished(client)
1529
1362
 
1560
1393
        branch._ensure_real = lambda: None
1561
1394
        branch.lock_write()
1562
1395
        # The 'TipChangeRejected' error response triggered by calling
1563
 
        # set_last_revision_info causes a TipChangeRejected exception.
 
1396
        # set_revision_history causes a TipChangeRejected exception.
1564
1397
        err = self.assertRaises(
1565
 
            errors.TipChangeRejected,
1566
 
            branch._set_last_revision, 'rev-id')
 
1398
            errors.TipChangeRejected, branch.set_revision_history, ['rev-id'])
1567
1399
        # The UTF-8 message from the response has been decoded into a unicode
1568
1400
        # object.
1569
1401
        self.assertIsInstance(err.msg, unicode)
1757
1589
    def test_get_multi_line_branch_conf(self):
1758
1590
        # Make sure that multiple-line branch.conf files are supported
1759
1591
        #
1760
 
        # https://bugs.launchpad.net/bzr/+bug/354075
 
1592
        # https://bugs.edge.launchpad.net/bzr/+bug/354075
1761
1593
        client = FakeClient()
1762
1594
        client.add_expected_call(
1763
1595
            'Branch.get_stacked_on_url', ('memory:///',),
1791
1623
        branch.unlock()
1792
1624
        self.assertFinished(client)
1793
1625
 
1794
 
    def test_set_option_with_dict(self):
1795
 
        client = FakeClient()
1796
 
        client.add_expected_call(
1797
 
            'Branch.get_stacked_on_url', ('memory:///',),
1798
 
            'error', ('NotStacked',),)
1799
 
        client.add_expected_call(
1800
 
            'Branch.lock_write', ('memory:///', '', ''),
1801
 
            'success', ('ok', 'branch token', 'repo token'))
1802
 
        encoded_dict_value = 'd5:ascii1:a11:unicode \xe2\x8c\x9a3:\xe2\x80\xbde'
1803
 
        client.add_expected_call(
1804
 
            'Branch.set_config_option_dict', ('memory:///', 'branch token',
1805
 
            'repo token', encoded_dict_value, 'foo', ''),
1806
 
            'success', ())
1807
 
        client.add_expected_call(
1808
 
            'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
1809
 
            'success', ('ok',))
1810
 
        transport = MemoryTransport()
1811
 
        branch = self.make_remote_branch(transport, client)
1812
 
        branch.lock_write()
1813
 
        config = branch._get_config()
1814
 
        config.set_option(
1815
 
            {'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'},
1816
 
            'foo')
1817
 
        branch.unlock()
1818
 
        self.assertFinished(client)
1819
 
 
1820
1626
    def test_backwards_compat_set_option(self):
1821
1627
        self.setup_smart_server_with_call_log()
1822
1628
        branch = self.make_branch('.')
1829
1635
        self.assertLength(10, self.hpss_calls)
1830
1636
        self.assertEqual('value', branch._get_config().get_option('name'))
1831
1637
 
1832
 
    def test_backwards_compat_set_option_with_dict(self):
1833
 
        self.setup_smart_server_with_call_log()
1834
 
        branch = self.make_branch('.')
1835
 
        verb = 'Branch.set_config_option_dict'
1836
 
        self.disable_verb(verb)
1837
 
        branch.lock_write()
1838
 
        self.addCleanup(branch.unlock)
1839
 
        self.reset_smart_call_log()
1840
 
        config = branch._get_config()
1841
 
        value_dict = {'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'}
1842
 
        config.set_option(value_dict, 'name')
1843
 
        self.assertLength(10, self.hpss_calls)
1844
 
        self.assertEqual(value_dict, branch._get_config().get_option('name'))
1845
 
 
1846
1638
 
1847
1639
class TestBranchLockWrite(RemoteBranchTestCase):
1848
1640
 
1984
1776
        client = FakeClient(transport.base)
1985
1777
        transport = transport.clone(transport_path)
1986
1778
        # we do not want bzrdir to make any remote calls
1987
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
1779
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1988
1780
            _client=False)
1989
1781
        repo = RemoteRepository(bzrdir, None, _client=client)
1990
1782
        return repo, client
1991
1783
 
1992
1784
 
1993
 
def remoted_description(format):
1994
 
    return 'Remote: ' + format.get_format_description()
1995
 
 
1996
 
 
1997
 
class TestBranchFormat(tests.TestCase):
1998
 
 
1999
 
    def test_get_format_description(self):
2000
 
        remote_format = RemoteBranchFormat()
2001
 
        real_format = branch.format_registry.get_default()
2002
 
        remote_format._network_name = real_format.network_name()
2003
 
        self.assertEqual(remoted_description(real_format),
2004
 
            remote_format.get_format_description())
2005
 
 
2006
 
 
2007
1785
class TestRepositoryFormat(TestRemoteRepository):
2008
1786
 
2009
1787
    def test_fast_delta(self):
2010
 
        true_name = groupcompress_repo.RepositoryFormat2a().network_name()
 
1788
        true_name = groupcompress_repo.RepositoryFormatCHK1().network_name()
2011
1789
        true_format = RemoteRepositoryFormat()
2012
1790
        true_format._network_name = true_name
2013
1791
        self.assertEqual(True, true_format.fast_deltas)
2014
 
        false_name = knitpack_repo.RepositoryFormatKnitPack1().network_name()
 
1792
        false_name = pack_repo.RepositoryFormatKnitPack1().network_name()
2015
1793
        false_format = RemoteRepositoryFormat()
2016
1794
        false_format._network_name = false_name
2017
1795
        self.assertEqual(False, false_format.fast_deltas)
2018
1796
 
2019
 
    def test_get_format_description(self):
2020
 
        remote_repo_format = RemoteRepositoryFormat()
2021
 
        real_format = repository.format_registry.get_default()
2022
 
        remote_repo_format._network_name = real_format.network_name()
2023
 
        self.assertEqual(remoted_description(real_format),
2024
 
            remote_repo_format.get_format_description())
2025
 
 
2026
1797
 
2027
1798
class TestRepositoryGatherStats(TestRemoteRepository):
2028
1799
 
2213
1984
        self.assertLength(1, self.hpss_calls)
2214
1985
 
2215
1986
    def disableExtraResults(self):
2216
 
        self.overrideAttr(SmartServerRepositoryGetParentMap,
2217
 
                          'no_extra_results', True)
 
1987
        old_flag = SmartServerRepositoryGetParentMap.no_extra_results
 
1988
        SmartServerRepositoryGetParentMap.no_extra_results = True
 
1989
        def reset_values():
 
1990
            SmartServerRepositoryGetParentMap.no_extra_results = old_flag
 
1991
        self.addCleanup(reset_values)
2218
1992
 
2219
1993
    def test_null_cached_missing_and_stop_key(self):
2220
1994
        self.setup_smart_server_with_call_log()
2279
2053
 
2280
2054
    def test_allows_new_revisions(self):
2281
2055
        """get_parent_map's results can be updated by commit."""
2282
 
        smart_server = test_server.SmartTCPServer_for_testing()
 
2056
        smart_server = server.SmartTCPServer_for_testing()
2283
2057
        self.start_server(smart_server)
2284
2058
        self.make_branch('branch')
2285
2059
        branch = Branch.open(smart_server.get_url() + '/branch')
2395
2169
        """
2396
2170
        # Make a repo with a fallback repo, both using a FakeClient.
2397
2171
        format = remote.response_tuple_to_repo_format(
2398
 
            ('yes', 'no', 'yes', self.get_repo_format().network_name()))
 
2172
            ('yes', 'no', 'yes', 'fake-network-name'))
2399
2173
        repo, client = self.setup_fake_client_and_repository('quack')
2400
2174
        repo._format = format
2401
2175
        fallback_repo, ignored = self.setup_fake_client_and_repository(
2402
2176
            'fallback')
2403
2177
        fallback_repo._client = client
2404
 
        fallback_repo._format = format
2405
2178
        repo.add_fallback_repository(fallback_repo)
2406
2179
        # First the client should ask the primary repo
2407
2180
        client.add_expected_call(
2436
2209
        self.setup_smart_server_with_call_log()
2437
2210
        tree = self.make_branch_and_memory_tree('.')
2438
2211
        tree.lock_write()
2439
 
        tree.add('')
2440
2212
        rev1 = tree.commit('First')
2441
2213
        rev2 = tree.commit('Second')
2442
2214
        tree.unlock()
2481
2253
        transport_path = 'quack'
2482
2254
        repo, client = self.setup_fake_client_and_repository(transport_path)
2483
2255
        client.add_success_response('ok', 'a token')
2484
 
        token = repo.lock_write().repository_token
 
2256
        result = repo.lock_write()
2485
2257
        self.assertEqual(
2486
2258
            [('call', 'Repository.lock_write', ('quack/', ''))],
2487
2259
            client._calls)
2488
 
        self.assertEqual('a token', token)
 
2260
        self.assertEqual('a token', result)
2489
2261
 
2490
2262
    def test_lock_write_already_locked(self):
2491
2263
        transport_path = 'quack'
2582
2354
        the client is finished.
2583
2355
        """
2584
2356
        sink = repo._get_sink()
2585
 
        fmt = repository.format_registry.get_default()
 
2357
        fmt = repository.RepositoryFormat.get_default_format()
2586
2358
        resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
2587
2359
        self.assertEqual([], resume_tokens)
2588
2360
        self.assertEqual(set(), missing_keys)
2688
2460
                return True
2689
2461
        repo._real_repository = FakeRealRepository()
2690
2462
        sink = repo._get_sink()
2691
 
        fmt = repository.format_registry.get_default()
 
2463
        fmt = repository.RepositoryFormat.get_default_format()
2692
2464
        stream = self.make_stream_with_inv_deltas(fmt)
2693
2465
        resume_tokens, missing_keys = sink.insert_stream(stream, fmt, [])
2694
2466
        # Every record from the first inventory delta should have been sent to
2829
2601
    """RemoteRepository.copy_content_into optimizations"""
2830
2602
 
2831
2603
    def test_copy_content_remote_to_local(self):
2832
 
        self.transport_server = test_server.SmartTCPServer_for_testing
 
2604
        self.transport_server = server.SmartTCPServer_for_testing
2833
2605
        src_repo = self.make_repository('repo1')
2834
2606
        src_repo = repository.Repository.open(self.get_url('repo1'))
2835
2607
        # At the moment the tarball-based copy_content_into can't write back
2914
2686
             ('pack collection autopack',)],
2915
2687
            client._calls)
2916
2688
 
2917
 
    def test_oom_error_reporting(self):
2918
 
        """An out-of-memory condition on the server is reported clearly"""
2919
 
        transport_path = 'quack'
2920
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2921
 
        client.add_expected_call(
2922
 
            'PackRepository.autopack', ('quack/',),
2923
 
            'error', ('MemoryError',))
2924
 
        err = self.assertRaises(errors.BzrError, repo.autopack)
2925
 
        self.assertContainsRe(str(err), "^remote server out of mem")
2926
 
 
2927
2689
 
2928
2690
class TestErrorTranslationBase(tests.TestCaseWithMemoryTransport):
2929
2691
    """Base class for unit tests for bzrlib.remote._translate_error."""
2993
2755
        expected_error = errors.NotBranchError(path=bzrdir.root_transport.base)
2994
2756
        self.assertEqual(expected_error, translated_error)
2995
2757
 
2996
 
    def test_nobranch_one_arg(self):
2997
 
        bzrdir = self.make_bzrdir('')
2998
 
        translated_error = self.translateTuple(
2999
 
            ('nobranch', 'extra detail'), bzrdir=bzrdir)
3000
 
        expected_error = errors.NotBranchError(
3001
 
            path=bzrdir.root_transport.base,
3002
 
            detail='extra detail')
3003
 
        self.assertEqual(expected_error, translated_error)
3004
 
 
3005
 
    def test_norepository(self):
3006
 
        bzrdir = self.make_bzrdir('')
3007
 
        translated_error = self.translateTuple(('norepository',),
3008
 
            bzrdir=bzrdir)
3009
 
        expected_error = errors.NoRepositoryPresent(bzrdir)
3010
 
        self.assertEqual(expected_error, translated_error)
3011
 
 
3012
2758
    def test_LockContention(self):
3013
2759
        translated_error = self.translateTuple(('LockContention',))
3014
2760
        expected_error = errors.LockContention('(remote lock)')
3042
2788
        expected_error = errors.DivergedBranches(branch, other_branch)
3043
2789
        self.assertEqual(expected_error, translated_error)
3044
2790
 
3045
 
    def test_NotStacked(self):
3046
 
        branch = self.make_branch('')
3047
 
        translated_error = self.translateTuple(('NotStacked',), branch=branch)
3048
 
        expected_error = errors.NotStacked(branch)
3049
 
        self.assertEqual(expected_error, translated_error)
3050
 
 
3051
2791
    def test_ReadError_no_args(self):
3052
2792
        path = 'a path'
3053
2793
        translated_error = self.translateTuple(('ReadError',), path=path)
3069
2809
 
3070
2810
    def test_PermissionDenied_no_args(self):
3071
2811
        path = 'a path'
3072
 
        translated_error = self.translateTuple(('PermissionDenied',),
3073
 
            path=path)
 
2812
        translated_error = self.translateTuple(('PermissionDenied',), path=path)
3074
2813
        expected_error = errors.PermissionDenied(path)
3075
2814
        self.assertEqual(expected_error, translated_error)
3076
2815
 
3099
2838
        expected_error = errors.PermissionDenied(path, extra)
3100
2839
        self.assertEqual(expected_error, translated_error)
3101
2840
 
3102
 
    # GZ 2011-03-02: TODO test for PermissionDenied with non-ascii 'extra'
3103
 
 
3104
 
    def test_NoSuchFile_context_path(self):
3105
 
        local_path = "local path"
3106
 
        translated_error = self.translateTuple(('ReadError', "remote path"),
3107
 
            path=local_path)
3108
 
        expected_error = errors.ReadError(local_path)
3109
 
        self.assertEqual(expected_error, translated_error)
3110
 
 
3111
 
    def test_NoSuchFile_without_context(self):
3112
 
        remote_path = "remote path"
3113
 
        translated_error = self.translateTuple(('ReadError', remote_path))
3114
 
        expected_error = errors.ReadError(remote_path)
3115
 
        self.assertEqual(expected_error, translated_error)
3116
 
 
3117
 
    def test_ReadOnlyError(self):
3118
 
        translated_error = self.translateTuple(('ReadOnlyError',))
3119
 
        expected_error = errors.TransportNotPossible("readonly transport")
3120
 
        self.assertEqual(expected_error, translated_error)
3121
 
 
3122
 
    def test_MemoryError(self):
3123
 
        translated_error = self.translateTuple(('MemoryError',))
3124
 
        self.assertStartsWith(str(translated_error),
3125
 
            "remote server out of memory")
3126
 
 
3127
 
    def test_generic_IndexError_no_classname(self):
3128
 
        err = errors.ErrorFromSmartServer(('error', "list index out of range"))
3129
 
        translated_error = self.translateErrorFromSmartServer(err)
3130
 
        expected_error = errors.UnknownErrorFromSmartServer(err)
3131
 
        self.assertEqual(expected_error, translated_error)
3132
 
 
3133
 
    # GZ 2011-03-02: TODO test generic non-ascii error string
3134
 
 
3135
 
    def test_generic_KeyError(self):
3136
 
        err = errors.ErrorFromSmartServer(('error', 'KeyError', "1"))
3137
 
        translated_error = self.translateErrorFromSmartServer(err)
3138
 
        expected_error = errors.UnknownErrorFromSmartServer(err)
3139
 
        self.assertEqual(expected_error, translated_error)
3140
 
 
3141
2841
 
3142
2842
class TestErrorTranslationRobustness(TestErrorTranslationBase):
3143
2843
    """Unit tests for bzrlib.remote._translate_error's robustness.
3173
2873
        # In addition to re-raising ErrorFromSmartServer, some debug info has
3174
2874
        # been muttered to the log file for developer to look at.
3175
2875
        self.assertContainsRe(
3176
 
            self.get_log(),
 
2876
            self._get_log(keep_log_file=True),
3177
2877
            "Missing key 'branch' in context")
3178
2878
 
3179
2879
    def test_path_missing(self):
3187
2887
        self.assertEqual(server_error, translated_error)
3188
2888
        # In addition to re-raising ErrorFromSmartServer, some debug info has
3189
2889
        # been muttered to the log file for developer to look at.
3190
 
        self.assertContainsRe(self.get_log(), "Missing key 'path' in context")
 
2890
        self.assertContainsRe(
 
2891
            self._get_log(keep_log_file=True), "Missing key 'path' in context")
3191
2892
 
3192
2893
 
3193
2894
class TestStacking(tests.TestCaseWithTransport):
3211
2912
        stacked_branch = self.make_branch('stacked', format='1.9')
3212
2913
        stacked_branch.set_stacked_on_url('../base')
3213
2914
        # start a server looking at this
3214
 
        smart_server = test_server.SmartTCPServer_for_testing()
 
2915
        smart_server = server.SmartTCPServer_for_testing()
3215
2916
        self.start_server(smart_server)
3216
2917
        remote_bzrdir = BzrDir.open(smart_server.get_url() + '/stacked')
3217
2918
        # can get its branch and repository
3288
2989
        _, stacked = branch_factory()
3289
2990
        source = stacked.repository._get_source(target_repository_format)
3290
2991
        tip = stacked.last_revision()
3291
 
        stacked.repository._ensure_real()
3292
 
        graph = stacked.repository.get_graph()
3293
 
        revs = [r for (r,ps) in graph.iter_ancestry([tip])
3294
 
                if r != NULL_REVISION]
3295
 
        revs.reverse()
3296
 
        search = _mod_graph.PendingAncestryResult([tip], stacked.repository)
 
2992
        revs = stacked.repository.get_ancestry(tip)
 
2993
        search = graph.PendingAncestryResult([tip], stacked.repository)
3297
2994
        self.reset_smart_call_log()
3298
2995
        stream = source.get_stream(search)
 
2996
        if None in revs:
 
2997
            revs.remove(None)
3299
2998
        # We trust that if a revision is in the stream the rest of the new
3300
2999
        # content for it is too, as per our main fetch tests; here we are
3301
3000
        # checking that the revisions are actually included at all, and their
3323
3022
            local_tree.commit('more local changes are better')
3324
3023
            branch = Branch.open(self.get_url('tree3'))
3325
3024
            branch.lock_read()
3326
 
            self.addCleanup(branch.unlock)
3327
3025
            return None, branch
3328
3026
        rev_ord, expected_revs = self.get_ordered_revs('1.9', 'unordered',
3329
3027
            branch_factory=make_stacked_stacked)
3340
3038
        self.assertEqual(expected_revs, rev_ord)
3341
3039
        # Getting topological sort requires VFS calls still - one of which is
3342
3040
        # pushing up from the bound branch.
3343
 
        self.assertLength(14, self.hpss_calls)
 
3041
        self.assertLength(13, self.hpss_calls)
3344
3042
 
3345
3043
    def test_stacked_get_stream_groupcompress(self):
3346
3044
        # Repository._get_source.get_stream() from a stacked repository with
3375
3073
        super(TestRemoteBranchEffort, self).setUp()
3376
3074
        # Create a smart server that publishes whatever the backing VFS server
3377
3075
        # does.
3378
 
        self.smart_server = test_server.SmartTCPServer_for_testing()
 
3076
        self.smart_server = server.SmartTCPServer_for_testing()
3379
3077
        self.start_server(self.smart_server, self.get_server())
3380
3078
        # Log all HPSS calls into self.hpss_calls.
3381
3079
        _SmartClient.hooks.install_named_hook(
3387
3085
 
3388
3086
    def test_copy_content_into_avoids_revision_history(self):
3389
3087
        local = self.make_branch('local')
3390
 
        builder = self.make_branch_builder('remote')
3391
 
        builder.build_commit(message="Commit.")
 
3088
        remote_backing_tree = self.make_branch_and_tree('remote')
 
3089
        remote_backing_tree.commit("Commit.")
3392
3090
        remote_branch_url = self.smart_server.get_url() + 'remote'
3393
3091
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
3394
3092
        local.repository.fetch(remote_branch.repository)
3395
3093
        self.hpss_calls = []
3396
3094
        remote_branch.copy_content_into(local)
3397
3095
        self.assertFalse('Branch.revision_history' in self.hpss_calls)
3398
 
 
3399
 
    def test_fetch_everything_needs_just_one_call(self):
3400
 
        local = self.make_branch('local')
3401
 
        builder = self.make_branch_builder('remote')
3402
 
        builder.build_commit(message="Commit.")
3403
 
        remote_branch_url = self.smart_server.get_url() + 'remote'
3404
 
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
3405
 
        self.hpss_calls = []
3406
 
        local.repository.fetch(
3407
 
            remote_branch.repository,
3408
 
            fetch_spec=_mod_graph.EverythingResult(remote_branch.repository))
3409
 
        self.assertEqual(['Repository.get_stream_1.19'], self.hpss_calls)
3410
 
 
3411
 
    def override_verb(self, verb_name, verb):
3412
 
        request_handlers = request.request_handlers
3413
 
        orig_verb = request_handlers.get(verb_name)
3414
 
        request_handlers.register(verb_name, verb, override_existing=True)
3415
 
        self.addCleanup(request_handlers.register, verb_name, orig_verb,
3416
 
                override_existing=True)
3417
 
 
3418
 
    def test_fetch_everything_backwards_compat(self):
3419
 
        """Can fetch with EverythingResult even with pre 2.4 servers.
3420
 
        
3421
 
        Pre-2.4 do not support 'everything' searches with the
3422
 
        Repository.get_stream_1.19 verb.
3423
 
        """
3424
 
        verb_log = []
3425
 
        class OldGetStreamVerb(SmartServerRepositoryGetStream_1_19):
3426
 
            """A version of the Repository.get_stream_1.19 verb patched to
3427
 
            reject 'everything' searches the way 2.3 and earlier do.
3428
 
            """
3429
 
            def recreate_search(self, repository, search_bytes,
3430
 
                                discard_excess=False):
3431
 
                verb_log.append(search_bytes.split('\n', 1)[0])
3432
 
                if search_bytes == 'everything':
3433
 
                    return (None,
3434
 
                            request.FailedSmartServerResponse(('BadSearch',)))
3435
 
                return super(OldGetStreamVerb,
3436
 
                        self).recreate_search(repository, search_bytes,
3437
 
                            discard_excess=discard_excess)
3438
 
        self.override_verb('Repository.get_stream_1.19', OldGetStreamVerb)
3439
 
        local = self.make_branch('local')
3440
 
        builder = self.make_branch_builder('remote')
3441
 
        builder.build_commit(message="Commit.")
3442
 
        remote_branch_url = self.smart_server.get_url() + 'remote'
3443
 
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
3444
 
        self.hpss_calls = []
3445
 
        local.repository.fetch(
3446
 
            remote_branch.repository,
3447
 
            fetch_spec=_mod_graph.EverythingResult(remote_branch.repository))
3448
 
        # make sure the overridden verb was used
3449
 
        self.assertLength(1, verb_log)
3450
 
        # more than one HPSS call is needed, but because it's a VFS callback
3451
 
        # its hard to predict exactly how many.
3452
 
        self.assertTrue(len(self.hpss_calls) > 1)
3453
 
 
3454
 
 
3455
 
class TestUpdateBoundBranchWithModifiedBoundLocation(
3456
 
    tests.TestCaseWithTransport):
3457
 
    """Ensure correct handling of bound_location modifications.
3458
 
 
3459
 
    This is tested against a smart server as http://pad.lv/786980 was about a
3460
 
    ReadOnlyError (write attempt during a read-only transaction) which can only
3461
 
    happen in this context.
3462
 
    """
3463
 
 
3464
 
    def setUp(self):
3465
 
        super(TestUpdateBoundBranchWithModifiedBoundLocation, self).setUp()
3466
 
        self.transport_server = test_server.SmartTCPServer_for_testing
3467
 
 
3468
 
    def make_master_and_checkout(self, master_name, checkout_name):
3469
 
        # Create the master branch and its associated checkout
3470
 
        self.master = self.make_branch_and_tree(master_name)
3471
 
        self.checkout = self.master.branch.create_checkout(checkout_name)
3472
 
        # Modify the master branch so there is something to update
3473
 
        self.master.commit('add stuff')
3474
 
        self.last_revid = self.master.commit('even more stuff')
3475
 
        self.bound_location = self.checkout.branch.get_bound_location()
3476
 
 
3477
 
    def assertUpdateSucceeds(self, new_location):
3478
 
        self.checkout.branch.set_bound_location(new_location)
3479
 
        self.checkout.update()
3480
 
        self.assertEquals(self.last_revid, self.checkout.last_revision())
3481
 
 
3482
 
    def test_without_final_slash(self):
3483
 
        self.make_master_and_checkout('master', 'checkout')
3484
 
        # For unclear reasons some users have a bound_location without a final
3485
 
        # '/', simulate that by forcing such a value
3486
 
        self.assertEndsWith(self.bound_location, '/')
3487
 
        self.assertUpdateSucceeds(self.bound_location.rstrip('/'))
3488
 
 
3489
 
    def test_plus_sign(self):
3490
 
        self.make_master_and_checkout('+master', 'checkout')
3491
 
        self.assertUpdateSucceeds(self.bound_location.replace('%2B', '+', 1))
3492
 
 
3493
 
    def test_tilda(self):
3494
 
        # Embed ~ in the middle of the path just to avoid any $HOME
3495
 
        # interpretation
3496
 
        self.make_master_and_checkout('mas~ter', 'checkout')
3497
 
        self.assertUpdateSucceeds(self.bound_location.replace('%2E', '~', 1))