~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_remote.py

  • Committer: Martin Pool
  • Date: 2010-06-02 05:03:31 UTC
  • mto: This revision was merged to the branch mainline in revision 5279.
  • Revision ID: mbp@canonical.com-20100602050331-n2p1qt8hfsahspnv
Correct more sloppy use of the term 'Linux'

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2011 Canonical Ltd
 
1
# Copyright (C) 2006-2010 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
25
25
 
26
26
import bz2
27
27
from cStringIO import StringIO
28
 
import zlib
29
28
 
30
29
from bzrlib import (
31
30
    branch,
32
31
    bzrdir,
33
32
    config,
34
 
    controldir,
35
33
    errors,
36
 
    graph as _mod_graph,
 
34
    graph,
37
35
    inventory,
38
36
    inventory_delta,
 
37
    pack,
39
38
    remote,
40
39
    repository,
41
40
    tests,
42
 
    transport,
43
41
    treebuilder,
 
42
    urlutils,
44
43
    versionedfile,
45
 
    vf_search,
46
44
    )
47
45
from bzrlib.branch import Branch
48
 
from bzrlib.bzrdir import (
49
 
    BzrDir,
50
 
    BzrDirFormat,
51
 
    RemoteBzrProber,
52
 
    )
53
 
from bzrlib.chk_serializer import chk_bencode_serializer
 
46
from bzrlib.bzrdir import BzrDir, BzrDirFormat
54
47
from bzrlib.remote import (
55
48
    RemoteBranch,
56
49
    RemoteBranchFormat,
59
52
    RemoteRepository,
60
53
    RemoteRepositoryFormat,
61
54
    )
62
 
from bzrlib.repofmt import groupcompress_repo, knitpack_repo
63
 
from bzrlib.revision import (
64
 
    NULL_REVISION,
65
 
    Revision,
66
 
    )
67
 
from bzrlib.smart import medium, request
 
55
from bzrlib.repofmt import groupcompress_repo, pack_repo
 
56
from bzrlib.revision import NULL_REVISION
 
57
from bzrlib.smart import medium
68
58
from bzrlib.smart.client import _SmartClient
69
 
from bzrlib.smart.repository import (
70
 
    SmartServerRepositoryGetParentMap,
71
 
    SmartServerRepositoryGetStream_1_19,
72
 
    _stream_to_byte_stream,
73
 
    )
74
 
from bzrlib.symbol_versioning import deprecated_in
 
59
from bzrlib.smart.repository import SmartServerRepositoryGetParentMap
75
60
from bzrlib.tests import (
 
61
    condition_isinstance,
 
62
    split_suite_by_condition,
 
63
    multiply_tests,
76
64
    test_server,
77
65
    )
78
 
from bzrlib.tests.scenarios import load_tests_apply_scenarios
 
66
from bzrlib.transport import get_transport
79
67
from bzrlib.transport.memory import MemoryTransport
80
68
from bzrlib.transport.remote import (
81
69
    RemoteTransport,
82
70
    RemoteSSHTransport,
83
71
    RemoteTCPTransport,
84
 
    )
85
 
 
86
 
 
87
 
load_tests = load_tests_apply_scenarios
88
 
 
89
 
 
90
 
class BasicRemoteObjectTests(tests.TestCaseWithTransport):
91
 
 
92
 
    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 = [
93
78
        ('HPSS-v2',
94
 
            {'transport_server': test_server.SmartTCPServer_for_testing_v2_only}),
 
79
         {'transport_server': test_server.SmartTCPServer_for_testing_v2_only}),
95
80
        ('HPSS-v3',
96
 
            {'transport_server': test_server.SmartTCPServer_for_testing})]
97
 
 
 
81
         {'transport_server': test_server.SmartTCPServer_for_testing})]
 
82
    return multiply_tests(to_adapt, smart_server_version_scenarios, result)
 
83
 
 
84
 
 
85
class BasicRemoteObjectTests(tests.TestCaseWithTransport):
98
86
 
99
87
    def setUp(self):
100
88
        super(BasicRemoteObjectTests, self).setUp()
101
89
        self.transport = self.get_transport()
102
90
        # make a branch that can be opened over the smart transport
103
91
        self.local_wt = BzrDir.create_standalone_workingtree('.')
104
 
        self.addCleanup(self.transport.disconnect)
 
92
 
 
93
    def tearDown(self):
 
94
        self.transport.disconnect()
 
95
        tests.TestCaseWithTransport.tearDown(self)
105
96
 
106
97
    def test_create_remote_bzrdir(self):
107
 
        b = remote.RemoteBzrDir(self.transport, RemoteBzrDirFormat())
 
98
        b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
108
99
        self.assertIsInstance(b, BzrDir)
109
100
 
110
101
    def test_open_remote_branch(self):
111
102
        # open a standalone branch in the working directory
112
 
        b = remote.RemoteBzrDir(self.transport, RemoteBzrDirFormat())
 
103
        b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
113
104
        branch = b.open_branch()
114
105
        self.assertIsInstance(branch, Branch)
115
106
 
123
114
 
124
115
    def test_remote_branch_revision_history(self):
125
116
        b = BzrDir.open_from_transport(self.transport).open_branch()
126
 
        self.assertEqual([],
127
 
            self.applyDeprecated(deprecated_in((2, 5, 0)), b.revision_history))
 
117
        self.assertEqual([], b.revision_history())
128
118
        r1 = self.local_wt.commit('1st commit')
129
119
        r2 = self.local_wt.commit('1st commit', rev_id=u'\xc8'.encode('utf8'))
130
 
        self.assertEqual([r1, r2],
131
 
            self.applyDeprecated(deprecated_in((2, 5, 0)), b.revision_history))
 
120
        self.assertEqual([r1, r2], b.revision_history())
132
121
 
133
122
    def test_find_correct_format(self):
134
123
        """Should open a RemoteBzrDir over a RemoteTransport"""
135
124
        fmt = BzrDirFormat.find_format(self.transport)
136
 
        self.assertTrue(bzrdir.RemoteBzrProber
137
 
                        in controldir.ControlDirFormat._server_probers)
138
 
        self.assertIsInstance(fmt, RemoteBzrDirFormat)
 
125
        self.assertTrue(RemoteBzrDirFormat
 
126
                        in BzrDirFormat._control_server_formats)
 
127
        self.assertIsInstance(fmt, remote.RemoteBzrDirFormat)
139
128
 
140
129
    def test_open_detected_smart_format(self):
141
130
        fmt = BzrDirFormat.find_format(self.transport)
175
164
    def test_remote_branch_set_append_revisions_only(self):
176
165
        # Make a format 1.9 branch, which supports append_revisions_only
177
166
        branch = self.make_branch('branch', format='1.9')
 
167
        config = branch.get_config()
178
168
        branch.set_append_revisions_only(True)
179
 
        config = branch.get_config_stack()
180
169
        self.assertEqual(
181
 
            True, config.get('append_revisions_only'))
 
170
            'True', config.get_user_option('append_revisions_only'))
182
171
        branch.set_append_revisions_only(False)
183
 
        config = branch.get_config_stack()
184
172
        self.assertEqual(
185
 
            False, config.get('append_revisions_only'))
 
173
            'False', config.get_user_option('append_revisions_only'))
186
174
 
187
175
    def test_remote_branch_set_append_revisions_only_upgrade_reqd(self):
188
176
        branch = self.make_branch('branch', format='knit')
 
177
        config = branch.get_config()
189
178
        self.assertRaises(
190
179
            errors.UpgradeRequired, branch.set_append_revisions_only, True)
191
180
 
370
359
        a given client_base and transport_base.
371
360
        """
372
361
        client_medium = medium.SmartClientMedium(client_base)
373
 
        t = transport.get_transport(transport_base)
374
 
        result = client_medium.remote_path_from_transport(t)
 
362
        transport = get_transport(transport_base)
 
363
        result = client_medium.remote_path_from_transport(transport)
375
364
        self.assertEqual(expected, result)
376
365
 
377
366
    def test_remote_path_from_transport(self):
388
377
        a given transport_base and relpath of that transport.  (Note that
389
378
        HttpTransportBase is a subclass of SmartClientMedium)
390
379
        """
391
 
        base_transport = transport.get_transport(transport_base)
 
380
        base_transport = get_transport(transport_base)
392
381
        client_medium = base_transport.get_smart_medium()
393
382
        cloned_transport = base_transport.clone(relpath)
394
383
        result = client_medium.remote_path_from_transport(cloned_transport)
461
450
        client.add_expected_call(
462
451
            'BzrDir.open_branchV3', ('quack/',),
463
452
            'success', ('ref', self.get_url('referenced'))),
464
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
453
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
465
454
            _client=client)
466
455
        result = a_bzrdir.cloning_metadir()
467
456
        # We should have got a control dir matching the referenced branch.
480
469
        client.add_expected_call(
481
470
            'BzrDir.cloning_metadir', ('quack/', 'False'),
482
471
            'success', (control_name, '', ('branch', ''))),
483
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
472
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
484
473
            _client=client)
485
474
        result = a_bzrdir.cloning_metadir()
486
475
        # We should have got a reference control dir with default branch and
491
480
        self.assertEqual(None, result._branch_format)
492
481
        self.assertFinished(client)
493
482
 
494
 
    def test_unknown(self):
495
 
        transport = self.get_transport('quack')
496
 
        referenced = self.make_branch('referenced')
497
 
        expected = referenced.bzrdir.cloning_metadir()
498
 
        client = FakeClient(transport.base)
499
 
        client.add_expected_call(
500
 
            'BzrDir.cloning_metadir', ('quack/', 'False'),
501
 
            'success', ('unknown', 'unknown', ('branch', ''))),
502
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
503
 
            _client=client)
504
 
        self.assertRaises(errors.UnknownFormatError, a_bzrdir.cloning_metadir)
505
 
 
506
 
 
507
 
class TestBzrDirCheckoutMetaDir(TestRemote):
508
 
 
509
 
    def test__get_checkout_format(self):
510
 
        transport = MemoryTransport()
511
 
        client = FakeClient(transport.base)
512
 
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
513
 
        control_name = reference_bzrdir_format.network_name()
514
 
        client.add_expected_call(
515
 
            'BzrDir.checkout_metadir', ('quack/', ),
516
 
            'success', (control_name, '', ''))
517
 
        transport.mkdir('quack')
518
 
        transport = transport.clone('quack')
519
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
520
 
            _client=client)
521
 
        result = a_bzrdir.checkout_metadir()
522
 
        # We should have got a reference control dir with default branch and
523
 
        # repository formats.
524
 
        self.assertEqual(bzrdir.BzrDirMetaFormat1, type(result))
525
 
        self.assertEqual(None, result._repository_format)
526
 
        self.assertEqual(None, result._branch_format)
527
 
        self.assertFinished(client)
528
 
 
529
 
    def test_unknown_format(self):
530
 
        transport = MemoryTransport()
531
 
        client = FakeClient(transport.base)
532
 
        client.add_expected_call(
533
 
            'BzrDir.checkout_metadir', ('quack/',),
534
 
            'success', ('dontknow', '', ''))
535
 
        transport.mkdir('quack')
536
 
        transport = transport.clone('quack')
537
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
538
 
            _client=client)
539
 
        self.assertRaises(errors.UnknownFormatError,
540
 
            a_bzrdir.checkout_metadir)
541
 
        self.assertFinished(client)
542
 
 
543
 
 
544
 
class TestBzrDirDestroyBranch(TestRemote):
545
 
 
546
 
    def test_destroy_default(self):
547
 
        transport = self.get_transport('quack')
548
 
        referenced = self.make_branch('referenced')
549
 
        client = FakeClient(transport.base)
550
 
        client.add_expected_call(
551
 
            'BzrDir.destroy_branch', ('quack/', ),
552
 
            'success', ('ok',)),
553
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
554
 
            _client=client)
555
 
        a_bzrdir.destroy_branch()
556
 
        self.assertFinished(client)
557
 
 
558
 
    def test_destroy_named(self):
559
 
        transport = self.get_transport('quack')
560
 
        referenced = self.make_branch('referenced')
561
 
        client = FakeClient(transport.base)
562
 
        client.add_expected_call(
563
 
            'BzrDir.destroy_branch', ('quack/', "foo"),
564
 
            'success', ('ok',)),
565
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
566
 
            _client=client)
567
 
        a_bzrdir.destroy_branch("foo")
568
 
        self.assertFinished(client)
569
 
 
570
 
 
571
 
class TestBzrDirHasWorkingTree(TestRemote):
572
 
 
573
 
    def test_has_workingtree(self):
574
 
        transport = self.get_transport('quack')
575
 
        client = FakeClient(transport.base)
576
 
        client.add_expected_call(
577
 
            'BzrDir.has_workingtree', ('quack/',),
578
 
            'success', ('yes',)),
579
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
580
 
            _client=client)
581
 
        self.assertTrue(a_bzrdir.has_workingtree())
582
 
        self.assertFinished(client)
583
 
 
584
 
    def test_no_workingtree(self):
585
 
        transport = self.get_transport('quack')
586
 
        client = FakeClient(transport.base)
587
 
        client.add_expected_call(
588
 
            'BzrDir.has_workingtree', ('quack/',),
589
 
            'success', ('no',)),
590
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
591
 
            _client=client)
592
 
        self.assertFalse(a_bzrdir.has_workingtree())
593
 
        self.assertFinished(client)
594
 
 
595
 
 
596
 
class TestBzrDirDestroyRepository(TestRemote):
597
 
 
598
 
    def test_destroy_repository(self):
599
 
        transport = self.get_transport('quack')
600
 
        client = FakeClient(transport.base)
601
 
        client.add_expected_call(
602
 
            'BzrDir.destroy_repository', ('quack/',),
603
 
            'success', ('ok',)),
604
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
605
 
            _client=client)
606
 
        a_bzrdir.destroy_repository()
607
 
        self.assertFinished(client)
608
 
 
609
483
 
610
484
class TestBzrDirOpen(TestRemote):
611
485
 
621
495
        client.add_expected_call(
622
496
            'BzrDir.open_2.1', ('quack/',), 'success', ('no',))
623
497
        self.assertRaises(errors.NotBranchError, RemoteBzrDir, transport,
624
 
                RemoteBzrDirFormat(), _client=client, _force_probe=True)
 
498
                remote.RemoteBzrDirFormat(), _client=client, _force_probe=True)
625
499
        self.assertFinished(client)
626
500
 
627
501
    def test_present_without_workingtree(self):
628
502
        client, transport = self.make_fake_client_and_transport()
629
503
        client.add_expected_call(
630
504
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'no'))
631
 
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
505
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
632
506
            _client=client, _force_probe=True)
633
507
        self.assertIsInstance(bd, RemoteBzrDir)
634
508
        self.assertFalse(bd.has_workingtree())
639
513
        client, transport = self.make_fake_client_and_transport()
640
514
        client.add_expected_call(
641
515
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'yes'))
642
 
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
516
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
643
517
            _client=client, _force_probe=True)
644
518
        self.assertIsInstance(bd, RemoteBzrDir)
645
519
        self.assertTrue(bd.has_workingtree())
652
526
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
653
527
        client.add_expected_call(
654
528
            'BzrDir.open', ('quack/',), 'success', ('yes',))
655
 
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
529
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
656
530
            _client=client, _force_probe=True)
657
531
        self.assertIsInstance(bd, RemoteBzrDir)
658
532
        self.assertFinished(client)
674
548
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
675
549
        client.add_expected_call(
676
550
            'BzrDir.open', ('quack/',), 'success', ('yes',))
677
 
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
551
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
678
552
            _client=client, _force_probe=True)
679
553
        self.assertIsInstance(bd, RemoteBzrDir)
680
554
        self.assertFinished(client)
711
585
        client.add_expected_call(
712
586
            'Branch.get_stacked_on_url', ('quack/',),
713
587
            'error', ('NotStacked',))
714
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
588
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
715
589
            _client=client)
716
590
        result = bzrdir.open_branch()
717
591
        self.assertIsInstance(result, RemoteBranch)
724
598
        transport = transport.clone('quack')
725
599
        client = FakeClient(transport.base)
726
600
        client.add_error_response('nobranch')
727
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
601
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
728
602
            _client=client)
729
603
        self.assertRaises(errors.NotBranchError, bzrdir.open_branch)
730
604
        self.assertEqual(
735
609
        # _get_tree_branch is a form of open_branch, but it should only ask for
736
610
        # branch opening, not any other network requests.
737
611
        calls = []
738
 
        def open_branch(name=None, possible_transports=None):
 
612
        def open_branch(name=None):
739
613
            calls.append("Called")
740
614
            return "a-branch"
741
615
        transport = MemoryTransport()
742
616
        # no requests on the network - catches other api calls being made.
743
617
        client = FakeClient(transport.base)
744
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
618
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
745
619
            _client=client)
746
620
        # patch the open_branch call to record that it was called.
747
621
        bzrdir.open_branch = open_branch
766
640
        client.add_expected_call(
767
641
            'Branch.get_stacked_on_url', ('~hello/',),
768
642
            'error', ('NotStacked',))
769
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
643
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
770
644
            _client=client)
771
645
        result = bzrdir.open_branch()
772
646
        self.assertFinished(client)
789
663
        client.add_success_response(
790
664
            'ok', '', rich_response, subtree_response, external_lookup,
791
665
            network_name)
792
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
666
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
793
667
            _client=client)
794
668
        result = bzrdir.open_repository()
795
669
        self.assertEqual(
812
686
        old.
813
687
        """
814
688
        self.assertRaises(errors.NotBranchError,
815
 
            RemoteBzrProber.probe_transport, OldServerTransport())
 
689
            RemoteBzrDirFormat.probe_transport, OldServerTransport())
816
690
 
817
691
 
818
692
class TestBzrDirCreateBranch(TestRemote):
841
715
            'BzrDir.create_branch', ('quack/', network_name),
842
716
            'success', ('ok', network_name, '', 'no', 'no', 'yes',
843
717
            reference_repo_name))
844
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
718
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
845
719
            _client=client)
846
720
        branch = a_bzrdir.create_branch()
847
721
        # We should have got a remote branch
850
724
        format = branch._format
851
725
        self.assertEqual(network_name, format.network_name())
852
726
 
853
 
    def test_already_open_repo_and_reused_medium(self):
854
 
        """Bug 726584: create_branch(..., repository=repo) should work
855
 
        regardless of what the smart medium's base URL is.
856
 
        """
857
 
        self.transport_server = test_server.SmartTCPServer_for_testing
858
 
        transport = self.get_transport('.')
859
 
        repo = self.make_repository('quack')
860
 
        # Client's medium rooted a transport root (not at the bzrdir)
861
 
        client = FakeClient(transport.base)
862
 
        transport = transport.clone('quack')
863
 
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
864
 
        reference_format = reference_bzrdir_format.get_branch_format()
865
 
        network_name = reference_format.network_name()
866
 
        reference_repo_fmt = reference_bzrdir_format.repository_format
867
 
        reference_repo_name = reference_repo_fmt.network_name()
868
 
        client.add_expected_call(
869
 
            'BzrDir.create_branch', ('extra/quack/', network_name),
870
 
            'success', ('ok', network_name, '', 'no', 'no', 'yes',
871
 
            reference_repo_name))
872
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
873
 
            _client=client)
874
 
        branch = a_bzrdir.create_branch(repository=repo)
875
 
        # We should have got a remote branch
876
 
        self.assertIsInstance(branch, remote.RemoteBranch)
877
 
        # its format should have the settings from the response
878
 
        format = branch._format
879
 
        self.assertEqual(network_name, format.network_name())
880
 
 
881
727
 
882
728
class TestBzrDirCreateRepository(TestRemote):
883
729
 
904
750
                'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
905
751
                'False'),
906
752
            'success', ('ok', 'yes', 'yes', 'yes', network_name))
907
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
753
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
908
754
            _client=client)
909
755
        repo = a_bzrdir.create_repository()
910
756
        # We should have got a remote repository
939
785
        client.add_success_response('stat', '0', '65535')
940
786
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
941
787
            _client=client)
942
 
        bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
 
788
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
943
789
            _client=client)
944
790
        repo = bzrdir.open_repository()
945
791
        self.assertEqual(
972
818
        client.add_success_response('stat', '0', '65535')
973
819
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
974
820
            _client=client)
975
 
        bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
 
821
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
976
822
            _client=client)
977
823
        repo = bzrdir.open_repository()
978
824
        self.assertEqual(
993
839
        transport = transport.clone('quack')
994
840
        client = FakeClient(transport.base)
995
841
        client.add_success_response('ok', '', 'no', 'no', 'no', network_name)
996
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
842
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
997
843
            _client=client)
998
844
        repo = bzrdir.open_repository()
999
845
        self.assertEqual(
1006
852
 
1007
853
    def test_success(self):
1008
854
        """Simple test for typical successful call."""
1009
 
        fmt = RemoteBzrDirFormat()
 
855
        fmt = bzrdir.RemoteBzrDirFormat()
1010
856
        default_format_name = BzrDirFormat.get_default_format().network_name()
1011
857
        transport = self.get_transport()
1012
858
        client = FakeClient(transport.base)
1028
874
        """Error responses are translated, e.g. 'PermissionDenied' raises the
1029
875
        corresponding error from the client.
1030
876
        """
1031
 
        fmt = RemoteBzrDirFormat()
 
877
        fmt = bzrdir.RemoteBzrDirFormat()
1032
878
        default_format_name = BzrDirFormat.get_default_format().network_name()
1033
879
        transport = self.get_transport()
1034
880
        client = FakeClient(transport.base)
1052
898
        """Integration test for error translation."""
1053
899
        transport = self.make_smart_server('foo')
1054
900
        transport = transport.clone('no-such-path')
1055
 
        fmt = RemoteBzrDirFormat()
 
901
        fmt = bzrdir.RemoteBzrDirFormat()
1056
902
        err = self.assertRaises(errors.NoSuchFile,
1057
903
            fmt.initialize_on_transport_ex, transport, create_prefix=False)
1058
904
 
1089
935
 
1090
936
    def make_remote_bzrdir(self, transport, client):
1091
937
        """Make a RemotebzrDir using 'client' as the _client."""
1092
 
        return RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
938
        return RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1093
939
            _client=client)
1094
940
 
1095
941
 
1121
967
        return RemoteBranch(bzrdir, repo, _client=client, format=format)
1122
968
 
1123
969
 
1124
 
class TestBranchBreakLock(RemoteBranchTestCase):
1125
 
 
1126
 
    def test_break_lock(self):
1127
 
        transport_path = 'quack'
1128
 
        transport = MemoryTransport()
1129
 
        client = FakeClient(transport.base)
1130
 
        client.add_expected_call(
1131
 
            'Branch.get_stacked_on_url', ('quack/',),
1132
 
            'error', ('NotStacked',))
1133
 
        client.add_expected_call(
1134
 
            'Branch.break_lock', ('quack/',),
1135
 
            'success', ('ok',))
1136
 
        transport.mkdir('quack')
1137
 
        transport = transport.clone('quack')
1138
 
        branch = self.make_remote_branch(transport, client)
1139
 
        branch.break_lock()
1140
 
        self.assertFinished(client)
1141
 
 
1142
 
 
1143
 
class TestBranchGetPhysicalLockStatus(RemoteBranchTestCase):
1144
 
 
1145
 
    def test_get_physical_lock_status_yes(self):
1146
 
        transport = MemoryTransport()
1147
 
        client = FakeClient(transport.base)
1148
 
        client.add_expected_call(
1149
 
            'Branch.get_stacked_on_url', ('quack/',),
1150
 
            'error', ('NotStacked',))
1151
 
        client.add_expected_call(
1152
 
            'Branch.get_physical_lock_status', ('quack/',),
1153
 
            'success', ('yes',))
1154
 
        transport.mkdir('quack')
1155
 
        transport = transport.clone('quack')
1156
 
        branch = self.make_remote_branch(transport, client)
1157
 
        result = branch.get_physical_lock_status()
1158
 
        self.assertFinished(client)
1159
 
        self.assertEqual(True, result)
1160
 
 
1161
 
    def test_get_physical_lock_status_no(self):
1162
 
        transport = MemoryTransport()
1163
 
        client = FakeClient(transport.base)
1164
 
        client.add_expected_call(
1165
 
            'Branch.get_stacked_on_url', ('quack/',),
1166
 
            'error', ('NotStacked',))
1167
 
        client.add_expected_call(
1168
 
            'Branch.get_physical_lock_status', ('quack/',),
1169
 
            'success', ('no',))
1170
 
        transport.mkdir('quack')
1171
 
        transport = transport.clone('quack')
1172
 
        branch = self.make_remote_branch(transport, client)
1173
 
        result = branch.get_physical_lock_status()
1174
 
        self.assertFinished(client)
1175
 
        self.assertEqual(False, result)
1176
 
 
1177
 
 
1178
970
class TestBranchGetParent(RemoteBranchTestCase):
1179
971
 
1180
972
    def test_no_parent(self):
1351
1143
            [('set_tags_bytes', 'tags bytes')] * 2, real_branch.calls)
1352
1144
 
1353
1145
 
1354
 
class TestBranchHeadsToFetch(RemoteBranchTestCase):
1355
 
 
1356
 
    def test_uses_last_revision_info_and_tags_by_default(self):
1357
 
        transport = MemoryTransport()
1358
 
        client = FakeClient(transport.base)
1359
 
        client.add_expected_call(
1360
 
            'Branch.get_stacked_on_url', ('quack/',),
1361
 
            'error', ('NotStacked',))
1362
 
        client.add_expected_call(
1363
 
            'Branch.last_revision_info', ('quack/',),
1364
 
            'success', ('ok', '1', 'rev-tip'))
1365
 
        client.add_expected_call(
1366
 
            'Branch.get_config_file', ('quack/',),
1367
 
            'success', ('ok',), '')
1368
 
        transport.mkdir('quack')
1369
 
        transport = transport.clone('quack')
1370
 
        branch = self.make_remote_branch(transport, client)
1371
 
        result = branch.heads_to_fetch()
1372
 
        self.assertFinished(client)
1373
 
        self.assertEqual((set(['rev-tip']), set()), result)
1374
 
 
1375
 
    def test_uses_last_revision_info_and_tags_when_set(self):
1376
 
        transport = MemoryTransport()
1377
 
        client = FakeClient(transport.base)
1378
 
        client.add_expected_call(
1379
 
            'Branch.get_stacked_on_url', ('quack/',),
1380
 
            'error', ('NotStacked',))
1381
 
        client.add_expected_call(
1382
 
            'Branch.last_revision_info', ('quack/',),
1383
 
            'success', ('ok', '1', 'rev-tip'))
1384
 
        client.add_expected_call(
1385
 
            'Branch.get_config_file', ('quack/',),
1386
 
            'success', ('ok',), 'branch.fetch_tags = True')
1387
 
        # XXX: this will break if the default format's serialization of tags
1388
 
        # changes, or if the RPC for fetching tags changes from get_tags_bytes.
1389
 
        client.add_expected_call(
1390
 
            'Branch.get_tags_bytes', ('quack/',),
1391
 
            'success', ('d5:tag-17:rev-foo5:tag-27:rev-bare',))
1392
 
        transport.mkdir('quack')
1393
 
        transport = transport.clone('quack')
1394
 
        branch = self.make_remote_branch(transport, client)
1395
 
        result = branch.heads_to_fetch()
1396
 
        self.assertFinished(client)
1397
 
        self.assertEqual(
1398
 
            (set(['rev-tip']), set(['rev-foo', 'rev-bar'])), result)
1399
 
 
1400
 
    def test_uses_rpc_for_formats_with_non_default_heads_to_fetch(self):
1401
 
        transport = MemoryTransport()
1402
 
        client = FakeClient(transport.base)
1403
 
        client.add_expected_call(
1404
 
            'Branch.get_stacked_on_url', ('quack/',),
1405
 
            'error', ('NotStacked',))
1406
 
        client.add_expected_call(
1407
 
            'Branch.heads_to_fetch', ('quack/',),
1408
 
            'success', (['tip'], ['tagged-1', 'tagged-2']))
1409
 
        transport.mkdir('quack')
1410
 
        transport = transport.clone('quack')
1411
 
        branch = self.make_remote_branch(transport, client)
1412
 
        branch._format._use_default_local_heads_to_fetch = lambda: False
1413
 
        result = branch.heads_to_fetch()
1414
 
        self.assertFinished(client)
1415
 
        self.assertEqual((set(['tip']), set(['tagged-1', 'tagged-2'])), result)
1416
 
 
1417
 
    def make_branch_with_tags(self):
1418
 
        self.setup_smart_server_with_call_log()
1419
 
        # Make a branch with a single revision.
1420
 
        builder = self.make_branch_builder('foo')
1421
 
        builder.start_series()
1422
 
        builder.build_snapshot('tip', None, [
1423
 
            ('add', ('', 'root-id', 'directory', ''))])
1424
 
        builder.finish_series()
1425
 
        branch = builder.get_branch()
1426
 
        # Add two tags to that branch
1427
 
        branch.tags.set_tag('tag-1', 'rev-1')
1428
 
        branch.tags.set_tag('tag-2', 'rev-2')
1429
 
        return branch
1430
 
 
1431
 
    def test_backwards_compatible(self):
1432
 
        branch = self.make_branch_with_tags()
1433
 
        c = branch.get_config()
1434
 
        c.set_user_option('branch.fetch_tags', 'True')
1435
 
        self.addCleanup(branch.lock_read().unlock)
1436
 
        # Disable the heads_to_fetch verb
1437
 
        verb = 'Branch.heads_to_fetch'
1438
 
        self.disable_verb(verb)
1439
 
        self.reset_smart_call_log()
1440
 
        result = branch.heads_to_fetch()
1441
 
        self.assertEqual((set(['tip']), set(['rev-1', 'rev-2'])), result)
1442
 
        self.assertEqual(
1443
 
            ['Branch.last_revision_info', 'Branch.get_config_file',
1444
 
             'Branch.get_tags_bytes'],
1445
 
            [call.call.method for call in self.hpss_calls])
1446
 
 
1447
 
    def test_backwards_compatible_no_tags(self):
1448
 
        branch = self.make_branch_with_tags()
1449
 
        c = branch.get_config()
1450
 
        c.set_user_option('branch.fetch_tags', 'False')
1451
 
        self.addCleanup(branch.lock_read().unlock)
1452
 
        # Disable the heads_to_fetch verb
1453
 
        verb = 'Branch.heads_to_fetch'
1454
 
        self.disable_verb(verb)
1455
 
        self.reset_smart_call_log()
1456
 
        result = branch.heads_to_fetch()
1457
 
        self.assertEqual((set(['tip']), set()), result)
1458
 
        self.assertEqual(
1459
 
            ['Branch.last_revision_info', 'Branch.get_config_file'],
1460
 
            [call.call.method for call in self.hpss_calls])
1461
 
 
1462
 
 
1463
1146
class TestBranchLastRevisionInfo(RemoteBranchTestCase):
1464
1147
 
1465
1148
    def test_empty_branch(self):
1520
1203
        client.add_expected_call(
1521
1204
            'Branch.get_stacked_on_url', ('stacked/',),
1522
1205
            'success', ('ok', vfs_url))
1523
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
1206
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1524
1207
            _client=client)
1525
1208
        repo_fmt = remote.RemoteRepositoryFormat()
1526
1209
        repo_fmt._custom_format = stacked_branch.repository._format
1553
1236
        # this will also do vfs access, but that goes direct to the transport
1554
1237
        # and isn't seen by the FakeClient.
1555
1238
        bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1556
 
            RemoteBzrDirFormat(), _client=client)
 
1239
            remote.RemoteBzrDirFormat(), _client=client)
1557
1240
        branch = bzrdir.open_branch()
1558
1241
        result = branch.get_stacked_on_url()
1559
1242
        self.assertEqual('../base', result)
1586
1269
            'Branch.get_stacked_on_url', ('stacked/',),
1587
1270
            'success', ('ok', '../base'))
1588
1271
        bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1589
 
            RemoteBzrDirFormat(), _client=client)
 
1272
            remote.RemoteBzrDirFormat(), _client=client)
1590
1273
        branch = bzrdir.open_branch()
1591
1274
        result = branch.get_stacked_on_url()
1592
1275
        self.assertEqual('../base', result)
1600
1283
class TestBranchSetLastRevision(RemoteBranchTestCase):
1601
1284
 
1602
1285
    def test_set_empty(self):
1603
 
        # _set_last_revision_info('null:') is translated to calling
 
1286
        # set_revision_history([]) is translated to calling
1604
1287
        # Branch.set_last_revision(path, '') on the wire.
1605
1288
        transport = MemoryTransport()
1606
1289
        transport.mkdir('branch')
1624
1307
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1625
1308
            'success', ('ok',))
1626
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
1627
1313
        branch.lock_write()
1628
 
        result = branch._set_last_revision(NULL_REVISION)
 
1314
        result = branch.set_revision_history([])
1629
1315
        branch.unlock()
1630
1316
        self.assertEqual(None, result)
1631
1317
        self.assertFinished(client)
1632
1318
 
1633
1319
    def test_set_nonempty(self):
1634
 
        # set_last_revision_info(N, rev-idN) is translated to calling
 
1320
        # set_revision_history([rev-id1, ..., rev-idN]) is translated to calling
1635
1321
        # Branch.set_last_revision(path, rev-idN) on the wire.
1636
1322
        transport = MemoryTransport()
1637
1323
        transport.mkdir('branch')
1658
1344
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1659
1345
            'success', ('ok',))
1660
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
1661
1350
        # Lock the branch, reset the record of remote calls.
1662
1351
        branch.lock_write()
1663
 
        result = branch._set_last_revision('rev-id2')
 
1352
        result = branch.set_revision_history(['rev-id1', 'rev-id2'])
1664
1353
        branch.unlock()
1665
1354
        self.assertEqual(None, result)
1666
1355
        self.assertFinished(client)
1696
1385
        branch = self.make_remote_branch(transport, client)
1697
1386
        branch.lock_write()
1698
1387
        self.assertRaises(
1699
 
            errors.NoSuchRevision, branch._set_last_revision, 'rev-id')
 
1388
            errors.NoSuchRevision, branch.set_revision_history, ['rev-id'])
1700
1389
        branch.unlock()
1701
1390
        self.assertFinished(client)
1702
1391
 
1730
1419
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1731
1420
            'success', ('ok',))
1732
1421
        branch = self.make_remote_branch(transport, client)
 
1422
        branch._ensure_real = lambda: None
1733
1423
        branch.lock_write()
1734
1424
        # The 'TipChangeRejected' error response triggered by calling
1735
 
        # set_last_revision_info causes a TipChangeRejected exception.
 
1425
        # set_revision_history causes a TipChangeRejected exception.
1736
1426
        err = self.assertRaises(
1737
 
            errors.TipChangeRejected,
1738
 
            branch._set_last_revision, 'rev-id')
 
1427
            errors.TipChangeRejected, branch.set_revision_history, ['rev-id'])
1739
1428
        # The UTF-8 message from the response has been decoded into a unicode
1740
1429
        # object.
1741
1430
        self.assertIsInstance(err.msg, unicode)
2016
1705
        self.assertEqual(value_dict, branch._get_config().get_option('name'))
2017
1706
 
2018
1707
 
2019
 
class TestBranchGetPutConfigStore(RemoteBranchTestCase):
2020
 
 
2021
 
    def test_get_branch_conf(self):
2022
 
        # in an empty branch we decode the response properly
2023
 
        client = FakeClient()
2024
 
        client.add_expected_call(
2025
 
            'Branch.get_stacked_on_url', ('memory:///',),
2026
 
            'error', ('NotStacked',),)
2027
 
        client.add_success_response_with_body('# config file body', 'ok')
2028
 
        transport = MemoryTransport()
2029
 
        branch = self.make_remote_branch(transport, client)
2030
 
        config = branch.get_config_stack()
2031
 
        config.get("email")
2032
 
        config.get("log_format")
2033
 
        self.assertEqual(
2034
 
            [('call', 'Branch.get_stacked_on_url', ('memory:///',)),
2035
 
             ('call_expecting_body', 'Branch.get_config_file', ('memory:///',))],
2036
 
            client._calls)
2037
 
 
2038
 
    def test_set_branch_conf(self):
2039
 
        client = FakeClient()
2040
 
        client.add_expected_call(
2041
 
            'Branch.get_stacked_on_url', ('memory:///',),
2042
 
            'error', ('NotStacked',),)
2043
 
        client.add_expected_call(
2044
 
            'Branch.lock_write', ('memory:///', '', ''),
2045
 
            'success', ('ok', 'branch token', 'repo token'))
2046
 
        client.add_expected_call(
2047
 
            'Branch.get_config_file', ('memory:///', ),
2048
 
            'success', ('ok', ), "# line 1\n")
2049
 
        client.add_expected_call(
2050
 
            'Branch.put_config_file', ('memory:///', 'branch token',
2051
 
            'repo token'),
2052
 
            'success', ('ok',))
2053
 
        client.add_expected_call(
2054
 
            'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
2055
 
            'success', ('ok',))
2056
 
        transport = MemoryTransport()
2057
 
        branch = self.make_remote_branch(transport, client)
2058
 
        branch.lock_write()
2059
 
        config = branch.get_config_stack()
2060
 
        config.set('email', 'The Dude <lebowski@example.com>')
2061
 
        branch.unlock()
2062
 
        self.assertFinished(client)
2063
 
        self.assertEqual(
2064
 
            [('call', 'Branch.get_stacked_on_url', ('memory:///',)),
2065
 
             ('call', 'Branch.lock_write', ('memory:///', '', '')),
2066
 
             ('call_expecting_body', 'Branch.get_config_file', ('memory:///',)),
2067
 
             ('call_with_body_bytes_expecting_body', 'Branch.put_config_file',
2068
 
                 ('memory:///', 'branch token', 'repo token'),
2069
 
                 '# line 1\nemail = The Dude <lebowski@example.com>\n'),
2070
 
             ('call', 'Branch.unlock', ('memory:///', 'branch token', 'repo token'))],
2071
 
            client._calls)
2072
 
 
2073
 
 
2074
1708
class TestBranchLockWrite(RemoteBranchTestCase):
2075
1709
 
2076
1710
    def test_lock_write_unlockable(self):
2089
1723
        self.assertFinished(client)
2090
1724
 
2091
1725
 
2092
 
class TestBranchRevisionIdToRevno(RemoteBranchTestCase):
2093
 
 
2094
 
    def test_simple(self):
2095
 
        transport = MemoryTransport()
2096
 
        client = FakeClient(transport.base)
2097
 
        client.add_expected_call(
2098
 
            'Branch.get_stacked_on_url', ('quack/',),
2099
 
            'error', ('NotStacked',),)
2100
 
        client.add_expected_call(
2101
 
            'Branch.revision_id_to_revno', ('quack/', 'null:'),
2102
 
            'success', ('ok', '0',),)
2103
 
        client.add_expected_call(
2104
 
            'Branch.revision_id_to_revno', ('quack/', 'unknown'),
2105
 
            'error', ('NoSuchRevision', 'unknown',),)
2106
 
        transport.mkdir('quack')
2107
 
        transport = transport.clone('quack')
2108
 
        branch = self.make_remote_branch(transport, client)
2109
 
        self.assertEquals(0, branch.revision_id_to_revno('null:'))
2110
 
        self.assertRaises(errors.NoSuchRevision,
2111
 
            branch.revision_id_to_revno, 'unknown')
2112
 
        self.assertFinished(client)
2113
 
 
2114
 
    def test_dotted(self):
2115
 
        transport = MemoryTransport()
2116
 
        client = FakeClient(transport.base)
2117
 
        client.add_expected_call(
2118
 
            'Branch.get_stacked_on_url', ('quack/',),
2119
 
            'error', ('NotStacked',),)
2120
 
        client.add_expected_call(
2121
 
            'Branch.revision_id_to_revno', ('quack/', 'null:'),
2122
 
            'success', ('ok', '0',),)
2123
 
        client.add_expected_call(
2124
 
            'Branch.revision_id_to_revno', ('quack/', 'unknown'),
2125
 
            'error', ('NoSuchRevision', 'unknown',),)
2126
 
        transport.mkdir('quack')
2127
 
        transport = transport.clone('quack')
2128
 
        branch = self.make_remote_branch(transport, client)
2129
 
        self.assertEquals((0, ), branch.revision_id_to_dotted_revno('null:'))
2130
 
        self.assertRaises(errors.NoSuchRevision,
2131
 
            branch.revision_id_to_dotted_revno, 'unknown')
2132
 
        self.assertFinished(client)
2133
 
 
2134
 
    def test_dotted_no_smart_verb(self):
2135
 
        self.setup_smart_server_with_call_log()
2136
 
        branch = self.make_branch('.')
2137
 
        self.disable_verb('Branch.revision_id_to_revno')
2138
 
        self.reset_smart_call_log()
2139
 
        self.assertEquals((0, ),
2140
 
            branch.revision_id_to_dotted_revno('null:'))
2141
 
        self.assertLength(7, self.hpss_calls)
2142
 
 
2143
 
 
2144
1726
class TestBzrDirGetSetConfig(RemoteBzrDirTestCase):
2145
1727
 
2146
1728
    def test__get_config(self):
2263
1845
        client = FakeClient(transport.base)
2264
1846
        transport = transport.clone(transport_path)
2265
1847
        # we do not want bzrdir to make any remote calls
2266
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
1848
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
2267
1849
            _client=False)
2268
1850
        repo = RemoteRepository(bzrdir, None, _client=client)
2269
1851
        return repo, client
2277
1859
 
2278
1860
    def test_get_format_description(self):
2279
1861
        remote_format = RemoteBranchFormat()
2280
 
        real_format = branch.format_registry.get_default()
 
1862
        real_format = branch.BranchFormat.get_default_format()
2281
1863
        remote_format._network_name = real_format.network_name()
2282
1864
        self.assertEqual(remoted_description(real_format),
2283
1865
            remote_format.get_format_description())
2286
1868
class TestRepositoryFormat(TestRemoteRepository):
2287
1869
 
2288
1870
    def test_fast_delta(self):
2289
 
        true_name = groupcompress_repo.RepositoryFormat2a().network_name()
 
1871
        true_name = groupcompress_repo.RepositoryFormatCHK1().network_name()
2290
1872
        true_format = RemoteRepositoryFormat()
2291
1873
        true_format._network_name = true_name
2292
1874
        self.assertEqual(True, true_format.fast_deltas)
2293
 
        false_name = knitpack_repo.RepositoryFormatKnitPack1().network_name()
 
1875
        false_name = pack_repo.RepositoryFormatKnitPack1().network_name()
2294
1876
        false_format = RemoteRepositoryFormat()
2295
1877
        false_format._network_name = false_name
2296
1878
        self.assertEqual(False, false_format.fast_deltas)
2297
1879
 
2298
1880
    def test_get_format_description(self):
2299
1881
        remote_repo_format = RemoteRepositoryFormat()
2300
 
        real_format = repository.format_registry.get_default()
 
1882
        real_format = repository.RepositoryFormat.get_default_format()
2301
1883
        remote_repo_format._network_name = real_format.network_name()
2302
1884
        self.assertEqual(remoted_description(real_format),
2303
1885
            remote_repo_format.get_format_description())
2304
1886
 
2305
1887
 
2306
 
class TestRepositoryAllRevisionIds(TestRemoteRepository):
2307
 
 
2308
 
    def test_empty(self):
2309
 
        transport_path = 'quack'
2310
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2311
 
        client.add_success_response_with_body('', 'ok')
2312
 
        self.assertEquals([], repo.all_revision_ids())
2313
 
        self.assertEqual(
2314
 
            [('call_expecting_body', 'Repository.all_revision_ids',
2315
 
             ('quack/',))],
2316
 
            client._calls)
2317
 
 
2318
 
    def test_with_some_content(self):
2319
 
        transport_path = 'quack'
2320
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2321
 
        client.add_success_response_with_body(
2322
 
            'rev1\nrev2\nanotherrev\n', 'ok')
2323
 
        self.assertEquals(["rev1", "rev2", "anotherrev"],
2324
 
            repo.all_revision_ids())
2325
 
        self.assertEqual(
2326
 
            [('call_expecting_body', 'Repository.all_revision_ids',
2327
 
             ('quack/',))],
2328
 
            client._calls)
2329
 
 
2330
 
 
2331
1888
class TestRepositoryGatherStats(TestRemoteRepository):
2332
1889
 
2333
1890
    def test_revid_none(self):
2386
1943
                         result)
2387
1944
 
2388
1945
 
2389
 
class TestRepositoryBreakLock(TestRemoteRepository):
2390
 
 
2391
 
    def test_break_lock(self):
2392
 
        transport_path = 'quack'
2393
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2394
 
        client.add_success_response('ok')
2395
 
        repo.break_lock()
2396
 
        self.assertEqual(
2397
 
            [('call', 'Repository.break_lock', ('quack/',))],
2398
 
            client._calls)
2399
 
 
2400
 
 
2401
 
class TestRepositoryGetSerializerFormat(TestRemoteRepository):
2402
 
 
2403
 
    def test_get_serializer_format(self):
2404
 
        transport_path = 'hill'
2405
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2406
 
        client.add_success_response('ok', '7')
2407
 
        self.assertEquals('7', repo.get_serializer_format())
2408
 
        self.assertEqual(
2409
 
            [('call', 'VersionedFileRepository.get_serializer_format',
2410
 
              ('hill/', ))],
2411
 
            client._calls)
2412
 
 
2413
 
 
2414
 
class TestRepositoryReconcile(TestRemoteRepository):
2415
 
 
2416
 
    def test_reconcile(self):
2417
 
        transport_path = 'hill'
2418
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2419
 
        body = ("garbage_inventories: 2\n"
2420
 
                "inconsistent_parents: 3\n")
2421
 
        client.add_expected_call(
2422
 
            'Repository.lock_write', ('hill/', ''),
2423
 
            'success', ('ok', 'a token'))
2424
 
        client.add_success_response_with_body(body, 'ok')
2425
 
        reconciler = repo.reconcile()
2426
 
        self.assertEqual(
2427
 
            [('call', 'Repository.lock_write', ('hill/', '')),
2428
 
             ('call_expecting_body', 'Repository.reconcile',
2429
 
                ('hill/', 'a token'))],
2430
 
            client._calls)
2431
 
        self.assertEquals(2, reconciler.garbage_inventories)
2432
 
        self.assertEquals(3, reconciler.inconsistent_parents)
2433
 
 
2434
 
 
2435
 
class TestRepositoryGetRevisionSignatureText(TestRemoteRepository):
2436
 
 
2437
 
    def test_text(self):
2438
 
        # ('ok',), body with signature text
2439
 
        transport_path = 'quack'
2440
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2441
 
        client.add_success_response_with_body(
2442
 
            'THETEXT', 'ok')
2443
 
        self.assertEquals("THETEXT", repo.get_signature_text("revid"))
2444
 
        self.assertEqual(
2445
 
            [('call_expecting_body', 'Repository.get_revision_signature_text',
2446
 
             ('quack/', 'revid'))],
2447
 
            client._calls)
2448
 
 
2449
 
    def test_no_signature(self):
2450
 
        transport_path = 'quick'
2451
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2452
 
        client.add_error_response('nosuchrevision', 'unknown')
2453
 
        self.assertRaises(errors.NoSuchRevision, repo.get_signature_text,
2454
 
                "unknown")
2455
 
        self.assertEqual(
2456
 
            [('call_expecting_body', 'Repository.get_revision_signature_text',
2457
 
              ('quick/', 'unknown'))],
2458
 
            client._calls)
2459
 
 
2460
 
 
2461
1946
class TestRepositoryGetGraph(TestRemoteRepository):
2462
1947
 
2463
1948
    def test_get_graph(self):
2468
1953
        self.assertNotEqual(graph._parents_provider, repo)
2469
1954
 
2470
1955
 
2471
 
class TestRepositoryAddSignatureText(TestRemoteRepository):
2472
 
 
2473
 
    def test_add_signature_text(self):
2474
 
        transport_path = 'quack'
2475
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2476
 
        client.add_expected_call(
2477
 
            'Repository.lock_write', ('quack/', ''),
2478
 
            'success', ('ok', 'a token'))
2479
 
        client.add_expected_call(
2480
 
            'Repository.start_write_group', ('quack/', 'a token'),
2481
 
            'success', ('ok', ('token1', )))
2482
 
        client.add_expected_call(
2483
 
            'Repository.add_signature_text', ('quack/', 'a token', 'rev1',
2484
 
                'token1'),
2485
 
            'success', ('ok', ), None)
2486
 
        repo.lock_write()
2487
 
        repo.start_write_group()
2488
 
        self.assertIs(None,
2489
 
            repo.add_signature_text("rev1", "every bloody emperor"))
2490
 
        self.assertEqual(
2491
 
            ('call_with_body_bytes_expecting_body',
2492
 
              'Repository.add_signature_text',
2493
 
                ('quack/', 'a token', 'rev1', 'token1'),
2494
 
              'every bloody emperor'),
2495
 
            client._calls[-1])
2496
 
 
2497
 
 
2498
1956
class TestRepositoryGetParentMap(TestRemoteRepository):
2499
1957
 
2500
1958
    def test_get_parent_map_caching(self):
2550
2008
        parents = repo.get_parent_map([rev_id])
2551
2009
        self.assertEqual(
2552
2010
            [('call_with_body_bytes_expecting_body',
2553
 
              'Repository.get_parent_map',
2554
 
              ('quack/', 'include-missing:', rev_id), '\n\n0'),
 
2011
              'Repository.get_parent_map', ('quack/', 'include-missing:',
 
2012
              rev_id), '\n\n0'),
2555
2013
             ('disconnect medium',),
2556
2014
             ('call_expecting_body', 'Repository.get_revision_graph',
2557
2015
              ('quack/', ''))],
2677
2135
        self.assertEqual({}, repo.get_parent_map(['non-existant']))
2678
2136
        self.assertLength(0, self.hpss_calls)
2679
2137
 
2680
 
    def test_exposes_get_cached_parent_map(self):
2681
 
        """RemoteRepository exposes get_cached_parent_map from
2682
 
        _unstacked_provider
2683
 
        """
2684
 
        r1 = u'\u0e33'.encode('utf8')
2685
 
        r2 = u'\u0dab'.encode('utf8')
2686
 
        lines = [' '.join([r2, r1]), r1]
2687
 
        encoded_body = bz2.compress('\n'.join(lines))
2688
 
 
2689
 
        transport_path = 'quack'
2690
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2691
 
        client.add_success_response_with_body(encoded_body, 'ok')
2692
 
        repo.lock_read()
2693
 
        # get_cached_parent_map should *not* trigger an RPC
2694
 
        self.assertEqual({}, repo.get_cached_parent_map([r1]))
2695
 
        self.assertEqual([], client._calls)
2696
 
        self.assertEqual({r2: (r1,)}, repo.get_parent_map([r2]))
2697
 
        self.assertEqual({r1: (NULL_REVISION,)},
2698
 
            repo.get_cached_parent_map([r1]))
2699
 
        self.assertEqual(
2700
 
            [('call_with_body_bytes_expecting_body',
2701
 
              'Repository.get_parent_map', ('quack/', 'include-missing:', r2),
2702
 
              '\n\n0')],
2703
 
            client._calls)
2704
 
        repo.unlock()
2705
 
 
2706
2138
 
2707
2139
class TestGetParentMapAllowsNew(tests.TestCaseWithTransport):
2708
2140
 
2723
2155
        self.assertEqual({'rev1': ('null:',)}, graph.get_parent_map(['rev1']))
2724
2156
 
2725
2157
 
2726
 
class TestRepositoryGetRevisions(TestRemoteRepository):
2727
 
 
2728
 
    def test_hpss_missing_revision(self):
2729
 
        transport_path = 'quack'
2730
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2731
 
        client.add_success_response_with_body(
2732
 
            '', 'ok', '10')
2733
 
        self.assertRaises(errors.NoSuchRevision, repo.get_revisions,
2734
 
            ['somerev1', 'anotherrev2'])
2735
 
        self.assertEqual(
2736
 
            [('call_with_body_bytes_expecting_body', 'Repository.iter_revisions',
2737
 
             ('quack/', ), "somerev1\nanotherrev2")],
2738
 
            client._calls)
2739
 
 
2740
 
    def test_hpss_get_single_revision(self):
2741
 
        transport_path = 'quack'
2742
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2743
 
        somerev1 = Revision("somerev1")
2744
 
        somerev1.committer = "Joe Committer <joe@example.com>"
2745
 
        somerev1.timestamp = 1321828927
2746
 
        somerev1.timezone = -60
2747
 
        somerev1.inventory_sha1 = "691b39be74c67b1212a75fcb19c433aaed903c2b"
2748
 
        somerev1.message = "Message"
2749
 
        body = zlib.compress(chk_bencode_serializer.write_revision_to_string(
2750
 
            somerev1))
2751
 
        # Split up body into two bits to make sure the zlib compression object
2752
 
        # gets data fed twice.
2753
 
        client.add_success_response_with_body(
2754
 
                [body[:10], body[10:]], 'ok', '10')
2755
 
        revs = repo.get_revisions(['somerev1'])
2756
 
        self.assertEquals(revs, [somerev1])
2757
 
        self.assertEqual(
2758
 
            [('call_with_body_bytes_expecting_body', 'Repository.iter_revisions',
2759
 
             ('quack/', ), "somerev1")],
2760
 
            client._calls)
2761
 
 
2762
 
 
2763
2158
class TestRepositoryGetRevisionGraph(TestRemoteRepository):
2764
2159
 
2765
2160
    def test_null_revision(self):
2916
2311
                              call.call.method == verb])
2917
2312
 
2918
2313
 
2919
 
class TestRepositoryHasSignatureForRevisionId(TestRemoteRepository):
2920
 
 
2921
 
    def test_has_signature_for_revision_id(self):
2922
 
        # ('yes', ) for Repository.has_signature_for_revision_id -> 'True'.
2923
 
        transport_path = 'quack'
2924
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2925
 
        client.add_success_response('yes')
2926
 
        result = repo.has_signature_for_revision_id('A')
2927
 
        self.assertEqual(
2928
 
            [('call', 'Repository.has_signature_for_revision_id',
2929
 
              ('quack/', 'A'))],
2930
 
            client._calls)
2931
 
        self.assertEqual(True, result)
2932
 
 
2933
 
    def test_is_not_shared(self):
2934
 
        # ('no', ) for Repository.has_signature_for_revision_id -> 'False'.
2935
 
        transport_path = 'qwack'
2936
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2937
 
        client.add_success_response('no')
2938
 
        result = repo.has_signature_for_revision_id('A')
2939
 
        self.assertEqual(
2940
 
            [('call', 'Repository.has_signature_for_revision_id',
2941
 
              ('qwack/', 'A'))],
2942
 
            client._calls)
2943
 
        self.assertEqual(False, result)
2944
 
 
2945
 
 
2946
 
class TestRepositoryPhysicalLockStatus(TestRemoteRepository):
2947
 
 
2948
 
    def test_get_physical_lock_status_yes(self):
2949
 
        transport_path = 'qwack'
2950
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2951
 
        client.add_success_response('yes')
2952
 
        result = repo.get_physical_lock_status()
2953
 
        self.assertEqual(
2954
 
            [('call', 'Repository.get_physical_lock_status',
2955
 
              ('qwack/', ))],
2956
 
            client._calls)
2957
 
        self.assertEqual(True, result)
2958
 
 
2959
 
    def test_get_physical_lock_status_no(self):
2960
 
        transport_path = 'qwack'
2961
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2962
 
        client.add_success_response('no')
2963
 
        result = repo.get_physical_lock_status()
2964
 
        self.assertEqual(
2965
 
            [('call', 'Repository.get_physical_lock_status',
2966
 
              ('qwack/', ))],
2967
 
            client._calls)
2968
 
        self.assertEqual(False, result)
2969
 
 
2970
 
 
2971
2314
class TestRepositoryIsShared(TestRemoteRepository):
2972
2315
 
2973
2316
    def test_is_shared(self):
2993
2336
        self.assertEqual(False, result)
2994
2337
 
2995
2338
 
2996
 
class TestRepositoryMakeWorkingTrees(TestRemoteRepository):
2997
 
 
2998
 
    def test_make_working_trees(self):
2999
 
        # ('yes', ) for Repository.make_working_trees -> 'True'.
3000
 
        transport_path = 'quack'
3001
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
3002
 
        client.add_success_response('yes')
3003
 
        result = repo.make_working_trees()
3004
 
        self.assertEqual(
3005
 
            [('call', 'Repository.make_working_trees', ('quack/',))],
3006
 
            client._calls)
3007
 
        self.assertEqual(True, result)
3008
 
 
3009
 
    def test_no_working_trees(self):
3010
 
        # ('no', ) for Repository.make_working_trees -> 'False'.
3011
 
        transport_path = 'qwack'
3012
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
3013
 
        client.add_success_response('no')
3014
 
        result = repo.make_working_trees()
3015
 
        self.assertEqual(
3016
 
            [('call', 'Repository.make_working_trees', ('qwack/',))],
3017
 
            client._calls)
3018
 
        self.assertEqual(False, result)
3019
 
 
3020
 
 
3021
2339
class TestRepositoryLockWrite(TestRemoteRepository):
3022
2340
 
3023
2341
    def test_lock_write(self):
3049
2367
            client._calls)
3050
2368
 
3051
2369
 
3052
 
class TestRepositoryWriteGroups(TestRemoteRepository):
3053
 
 
3054
 
    def test_start_write_group(self):
3055
 
        transport_path = 'quack'
3056
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
3057
 
        client.add_expected_call(
3058
 
            'Repository.lock_write', ('quack/', ''),
3059
 
            'success', ('ok', 'a token'))
3060
 
        client.add_expected_call(
3061
 
            'Repository.start_write_group', ('quack/', 'a token'),
3062
 
            'success', ('ok', ('token1', )))
3063
 
        repo.lock_write()
3064
 
        repo.start_write_group()
3065
 
 
3066
 
    def test_start_write_group_unsuspendable(self):
3067
 
        # Some repositories do not support suspending write
3068
 
        # groups. For those, fall back to the "real" repository.
3069
 
        transport_path = 'quack'
3070
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
3071
 
        def stub_ensure_real():
3072
 
            client._calls.append(('_ensure_real',))
3073
 
            repo._real_repository = _StubRealPackRepository(client._calls)
3074
 
        repo._ensure_real = stub_ensure_real
3075
 
        client.add_expected_call(
3076
 
            'Repository.lock_write', ('quack/', ''),
3077
 
            'success', ('ok', 'a token'))
3078
 
        client.add_expected_call(
3079
 
            'Repository.start_write_group', ('quack/', 'a token'),
3080
 
            'error', ('UnsuspendableWriteGroup',))
3081
 
        repo.lock_write()
3082
 
        repo.start_write_group()
3083
 
        self.assertEquals(client._calls[-2:], [ 
3084
 
            ('_ensure_real',),
3085
 
            ('start_write_group',)])
3086
 
 
3087
 
    def test_commit_write_group(self):
3088
 
        transport_path = 'quack'
3089
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
3090
 
        client.add_expected_call(
3091
 
            'Repository.lock_write', ('quack/', ''),
3092
 
            'success', ('ok', 'a token'))
3093
 
        client.add_expected_call(
3094
 
            'Repository.start_write_group', ('quack/', 'a token'),
3095
 
            'success', ('ok', ['token1']))
3096
 
        client.add_expected_call(
3097
 
            'Repository.commit_write_group', ('quack/', 'a token', ['token1']),
3098
 
            'success', ('ok',))
3099
 
        repo.lock_write()
3100
 
        repo.start_write_group()
3101
 
        repo.commit_write_group()
3102
 
 
3103
 
    def test_abort_write_group(self):
3104
 
        transport_path = 'quack'
3105
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
3106
 
        client.add_expected_call(
3107
 
            'Repository.lock_write', ('quack/', ''),
3108
 
            'success', ('ok', 'a token'))
3109
 
        client.add_expected_call(
3110
 
            'Repository.start_write_group', ('quack/', 'a token'),
3111
 
            'success', ('ok', ['token1']))
3112
 
        client.add_expected_call(
3113
 
            'Repository.abort_write_group', ('quack/', 'a token', ['token1']),
3114
 
            'success', ('ok',))
3115
 
        repo.lock_write()
3116
 
        repo.start_write_group()
3117
 
        repo.abort_write_group(False)
3118
 
 
3119
 
    def test_suspend_write_group(self):
3120
 
        transport_path = 'quack'
3121
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
3122
 
        self.assertEquals([], repo.suspend_write_group())
3123
 
 
3124
 
    def test_resume_write_group(self):
3125
 
        transport_path = 'quack'
3126
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
3127
 
        client.add_expected_call(
3128
 
            'Repository.lock_write', ('quack/', ''),
3129
 
            'success', ('ok', 'a token'))
3130
 
        client.add_expected_call(
3131
 
            'Repository.check_write_group', ('quack/', 'a token', ['token1']),
3132
 
            'success', ('ok',))
3133
 
        repo.lock_write()
3134
 
        repo.resume_write_group(['token1'])
3135
 
 
3136
 
 
3137
2370
class TestRepositorySetMakeWorkingTrees(TestRemoteRepository):
3138
2371
 
3139
2372
    def test_backwards_compat(self):
3198
2431
        self.assertEqual([], client._calls)
3199
2432
 
3200
2433
 
3201
 
class TestRepositoryIterFilesBytes(TestRemoteRepository):
3202
 
    """Test Repository.iter_file_bytes."""
3203
 
 
3204
 
    def test_single(self):
3205
 
        transport_path = 'quack'
3206
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
3207
 
        client.add_expected_call(
3208
 
            'Repository.iter_files_bytes', ('quack/', ),
3209
 
            'success', ('ok',), iter(["ok\x000", "\n", zlib.compress("mydata" * 10)]))
3210
 
        for (identifier, byte_stream) in repo.iter_files_bytes([("somefile",
3211
 
                "somerev", "myid")]):
3212
 
            self.assertEquals("myid", identifier)
3213
 
            self.assertEquals("".join(byte_stream), "mydata" * 10)
3214
 
 
3215
 
    def test_missing(self):
3216
 
        transport_path = 'quack'
3217
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
3218
 
        client.add_expected_call(
3219
 
            'Repository.iter_files_bytes',
3220
 
                ('quack/', ),
3221
 
            'error', ('RevisionNotPresent', 'somefile', 'somerev'),
3222
 
            iter(["absent\0somefile\0somerev\n"]))
3223
 
        self.assertRaises(errors.RevisionNotPresent, list,
3224
 
                repo.iter_files_bytes(
3225
 
                [("somefile", "somerev", "myid")]))
3226
 
 
3227
 
 
3228
2434
class TestRepositoryInsertStreamBase(TestRemoteRepository):
3229
2435
    """Base class for Repository.insert_stream and .insert_stream_1.19
3230
2436
    tests.
3237
2443
        the client is finished.
3238
2444
        """
3239
2445
        sink = repo._get_sink()
3240
 
        fmt = repository.format_registry.get_default()
 
2446
        fmt = repository.RepositoryFormat.get_default_format()
3241
2447
        resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
3242
2448
        self.assertEqual([], resume_tokens)
3243
2449
        self.assertEqual(set(), missing_keys)
3343
2549
                return True
3344
2550
        repo._real_repository = FakeRealRepository()
3345
2551
        sink = repo._get_sink()
3346
 
        fmt = repository.format_registry.get_default()
 
2552
        fmt = repository.RepositoryFormat.get_default_format()
3347
2553
        stream = self.make_stream_with_inv_deltas(fmt)
3348
2554
        resume_tokens, missing_keys = sink.insert_stream(stream, fmt, [])
3349
2555
        # Every record from the first inventory delta should have been sent to
3505
2711
        self.calls = calls
3506
2712
        self._pack_collection = _StubPackCollection(calls)
3507
2713
 
3508
 
    def start_write_group(self):
3509
 
        self.calls.append(('start_write_group',))
3510
 
 
3511
2714
    def is_in_write_group(self):
3512
2715
        return False
3513
2716
 
3572
2775
             ('pack collection autopack',)],
3573
2776
            client._calls)
3574
2777
 
3575
 
    def test_oom_error_reporting(self):
3576
 
        """An out-of-memory condition on the server is reported clearly"""
3577
 
        transport_path = 'quack'
3578
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
3579
 
        client.add_expected_call(
3580
 
            'PackRepository.autopack', ('quack/',),
3581
 
            'error', ('MemoryError',))
3582
 
        err = self.assertRaises(errors.BzrError, repo.autopack)
3583
 
        self.assertContainsRe(str(err), "^remote server out of mem")
3584
 
 
3585
2778
 
3586
2779
class TestErrorTranslationBase(tests.TestCaseWithMemoryTransport):
3587
2780
    """Base class for unit tests for bzrlib.remote._translate_error."""
3660
2853
            detail='extra detail')
3661
2854
        self.assertEqual(expected_error, translated_error)
3662
2855
 
3663
 
    def test_norepository(self):
3664
 
        bzrdir = self.make_bzrdir('')
3665
 
        translated_error = self.translateTuple(('norepository',),
3666
 
            bzrdir=bzrdir)
3667
 
        expected_error = errors.NoRepositoryPresent(bzrdir)
3668
 
        self.assertEqual(expected_error, translated_error)
3669
 
 
3670
2856
    def test_LockContention(self):
3671
2857
        translated_error = self.translateTuple(('LockContention',))
3672
2858
        expected_error = errors.LockContention('(remote lock)')
3700
2886
        expected_error = errors.DivergedBranches(branch, other_branch)
3701
2887
        self.assertEqual(expected_error, translated_error)
3702
2888
 
3703
 
    def test_NotStacked(self):
3704
 
        branch = self.make_branch('')
3705
 
        translated_error = self.translateTuple(('NotStacked',), branch=branch)
3706
 
        expected_error = errors.NotStacked(branch)
3707
 
        self.assertEqual(expected_error, translated_error)
3708
 
 
3709
2889
    def test_ReadError_no_args(self):
3710
2890
        path = 'a path'
3711
2891
        translated_error = self.translateTuple(('ReadError',), path=path)
3727
2907
 
3728
2908
    def test_PermissionDenied_no_args(self):
3729
2909
        path = 'a path'
3730
 
        translated_error = self.translateTuple(('PermissionDenied',),
3731
 
            path=path)
 
2910
        translated_error = self.translateTuple(('PermissionDenied',), path=path)
3732
2911
        expected_error = errors.PermissionDenied(path)
3733
2912
        self.assertEqual(expected_error, translated_error)
3734
2913
 
3757
2936
        expected_error = errors.PermissionDenied(path, extra)
3758
2937
        self.assertEqual(expected_error, translated_error)
3759
2938
 
3760
 
    # GZ 2011-03-02: TODO test for PermissionDenied with non-ascii 'extra'
3761
 
 
3762
 
    def test_NoSuchFile_context_path(self):
3763
 
        local_path = "local path"
3764
 
        translated_error = self.translateTuple(('ReadError', "remote path"),
3765
 
            path=local_path)
3766
 
        expected_error = errors.ReadError(local_path)
3767
 
        self.assertEqual(expected_error, translated_error)
3768
 
 
3769
 
    def test_NoSuchFile_without_context(self):
3770
 
        remote_path = "remote path"
3771
 
        translated_error = self.translateTuple(('ReadError', remote_path))
3772
 
        expected_error = errors.ReadError(remote_path)
3773
 
        self.assertEqual(expected_error, translated_error)
3774
 
 
3775
 
    def test_ReadOnlyError(self):
3776
 
        translated_error = self.translateTuple(('ReadOnlyError',))
3777
 
        expected_error = errors.TransportNotPossible("readonly transport")
3778
 
        self.assertEqual(expected_error, translated_error)
3779
 
 
3780
 
    def test_MemoryError(self):
3781
 
        translated_error = self.translateTuple(('MemoryError',))
3782
 
        self.assertStartsWith(str(translated_error),
3783
 
            "remote server out of memory")
3784
 
 
3785
 
    def test_generic_IndexError_no_classname(self):
3786
 
        err = errors.ErrorFromSmartServer(('error', "list index out of range"))
3787
 
        translated_error = self.translateErrorFromSmartServer(err)
3788
 
        expected_error = errors.UnknownErrorFromSmartServer(err)
3789
 
        self.assertEqual(expected_error, translated_error)
3790
 
 
3791
 
    # GZ 2011-03-02: TODO test generic non-ascii error string
3792
 
 
3793
 
    def test_generic_KeyError(self):
3794
 
        err = errors.ErrorFromSmartServer(('error', 'KeyError', "1"))
3795
 
        translated_error = self.translateErrorFromSmartServer(err)
3796
 
        expected_error = errors.UnknownErrorFromSmartServer(err)
3797
 
        self.assertEqual(expected_error, translated_error)
3798
 
 
3799
2939
 
3800
2940
class TestErrorTranslationRobustness(TestErrorTranslationBase):
3801
2941
    """Unit tests for bzrlib.remote._translate_error's robustness.
3946
3086
        _, stacked = branch_factory()
3947
3087
        source = stacked.repository._get_source(target_repository_format)
3948
3088
        tip = stacked.last_revision()
3949
 
        stacked.repository._ensure_real()
3950
 
        graph = stacked.repository.get_graph()
3951
 
        revs = [r for (r,ps) in graph.iter_ancestry([tip])
3952
 
                if r != NULL_REVISION]
3953
 
        revs.reverse()
3954
 
        search = vf_search.PendingAncestryResult([tip], stacked.repository)
 
3089
        revs = stacked.repository.get_ancestry(tip)
 
3090
        search = graph.PendingAncestryResult([tip], stacked.repository)
3955
3091
        self.reset_smart_call_log()
3956
3092
        stream = source.get_stream(search)
 
3093
        if None in revs:
 
3094
            revs.remove(None)
3957
3095
        # We trust that if a revision is in the stream the rest of the new
3958
3096
        # content for it is too, as per our main fetch tests; here we are
3959
3097
        # checking that the revisions are actually included at all, and their
3998
3136
        self.assertEqual(expected_revs, rev_ord)
3999
3137
        # Getting topological sort requires VFS calls still - one of which is
4000
3138
        # pushing up from the bound branch.
4001
 
        self.assertLength(14, self.hpss_calls)
 
3139
        self.assertLength(13, self.hpss_calls)
4002
3140
 
4003
3141
    def test_stacked_get_stream_groupcompress(self):
4004
3142
        # Repository._get_source.get_stream() from a stacked repository with
4045
3183
 
4046
3184
    def test_copy_content_into_avoids_revision_history(self):
4047
3185
        local = self.make_branch('local')
4048
 
        builder = self.make_branch_builder('remote')
4049
 
        builder.build_commit(message="Commit.")
 
3186
        remote_backing_tree = self.make_branch_and_tree('remote')
 
3187
        remote_backing_tree.commit("Commit.")
4050
3188
        remote_branch_url = self.smart_server.get_url() + 'remote'
4051
3189
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
4052
3190
        local.repository.fetch(remote_branch.repository)
4053
3191
        self.hpss_calls = []
4054
3192
        remote_branch.copy_content_into(local)
4055
3193
        self.assertFalse('Branch.revision_history' in self.hpss_calls)
4056
 
 
4057
 
    def test_fetch_everything_needs_just_one_call(self):
4058
 
        local = self.make_branch('local')
4059
 
        builder = self.make_branch_builder('remote')
4060
 
        builder.build_commit(message="Commit.")
4061
 
        remote_branch_url = self.smart_server.get_url() + 'remote'
4062
 
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
4063
 
        self.hpss_calls = []
4064
 
        local.repository.fetch(
4065
 
            remote_branch.repository,
4066
 
            fetch_spec=vf_search.EverythingResult(remote_branch.repository))
4067
 
        self.assertEqual(['Repository.get_stream_1.19'], self.hpss_calls)
4068
 
 
4069
 
    def override_verb(self, verb_name, verb):
4070
 
        request_handlers = request.request_handlers
4071
 
        orig_verb = request_handlers.get(verb_name)
4072
 
        orig_info = request_handlers.get_info(verb_name)
4073
 
        request_handlers.register(verb_name, verb, override_existing=True)
4074
 
        self.addCleanup(request_handlers.register, verb_name, orig_verb,
4075
 
                override_existing=True, info=orig_info)
4076
 
 
4077
 
    def test_fetch_everything_backwards_compat(self):
4078
 
        """Can fetch with EverythingResult even with pre 2.4 servers.
4079
 
        
4080
 
        Pre-2.4 do not support 'everything' searches with the
4081
 
        Repository.get_stream_1.19 verb.
4082
 
        """
4083
 
        verb_log = []
4084
 
        class OldGetStreamVerb(SmartServerRepositoryGetStream_1_19):
4085
 
            """A version of the Repository.get_stream_1.19 verb patched to
4086
 
            reject 'everything' searches the way 2.3 and earlier do.
4087
 
            """
4088
 
            def recreate_search(self, repository, search_bytes,
4089
 
                                discard_excess=False):
4090
 
                verb_log.append(search_bytes.split('\n', 1)[0])
4091
 
                if search_bytes == 'everything':
4092
 
                    return (None,
4093
 
                            request.FailedSmartServerResponse(('BadSearch',)))
4094
 
                return super(OldGetStreamVerb,
4095
 
                        self).recreate_search(repository, search_bytes,
4096
 
                            discard_excess=discard_excess)
4097
 
        self.override_verb('Repository.get_stream_1.19', OldGetStreamVerb)
4098
 
        local = self.make_branch('local')
4099
 
        builder = self.make_branch_builder('remote')
4100
 
        builder.build_commit(message="Commit.")
4101
 
        remote_branch_url = self.smart_server.get_url() + 'remote'
4102
 
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
4103
 
        self.hpss_calls = []
4104
 
        local.repository.fetch(
4105
 
            remote_branch.repository,
4106
 
            fetch_spec=vf_search.EverythingResult(remote_branch.repository))
4107
 
        # make sure the overridden verb was used
4108
 
        self.assertLength(1, verb_log)
4109
 
        # more than one HPSS call is needed, but because it's a VFS callback
4110
 
        # its hard to predict exactly how many.
4111
 
        self.assertTrue(len(self.hpss_calls) > 1)
4112
 
 
4113
 
 
4114
 
class TestUpdateBoundBranchWithModifiedBoundLocation(
4115
 
    tests.TestCaseWithTransport):
4116
 
    """Ensure correct handling of bound_location modifications.
4117
 
 
4118
 
    This is tested against a smart server as http://pad.lv/786980 was about a
4119
 
    ReadOnlyError (write attempt during a read-only transaction) which can only
4120
 
    happen in this context.
4121
 
    """
4122
 
 
4123
 
    def setUp(self):
4124
 
        super(TestUpdateBoundBranchWithModifiedBoundLocation, self).setUp()
4125
 
        self.transport_server = test_server.SmartTCPServer_for_testing
4126
 
 
4127
 
    def make_master_and_checkout(self, master_name, checkout_name):
4128
 
        # Create the master branch and its associated checkout
4129
 
        self.master = self.make_branch_and_tree(master_name)
4130
 
        self.checkout = self.master.branch.create_checkout(checkout_name)
4131
 
        # Modify the master branch so there is something to update
4132
 
        self.master.commit('add stuff')
4133
 
        self.last_revid = self.master.commit('even more stuff')
4134
 
        self.bound_location = self.checkout.branch.get_bound_location()
4135
 
 
4136
 
    def assertUpdateSucceeds(self, new_location):
4137
 
        self.checkout.branch.set_bound_location(new_location)
4138
 
        self.checkout.update()
4139
 
        self.assertEquals(self.last_revid, self.checkout.last_revision())
4140
 
 
4141
 
    def test_without_final_slash(self):
4142
 
        self.make_master_and_checkout('master', 'checkout')
4143
 
        # For unclear reasons some users have a bound_location without a final
4144
 
        # '/', simulate that by forcing such a value
4145
 
        self.assertEndsWith(self.bound_location, '/')
4146
 
        self.assertUpdateSucceeds(self.bound_location.rstrip('/'))
4147
 
 
4148
 
    def test_plus_sign(self):
4149
 
        self.make_master_and_checkout('+master', 'checkout')
4150
 
        self.assertUpdateSucceeds(self.bound_location.replace('%2B', '+', 1))
4151
 
 
4152
 
    def test_tilda(self):
4153
 
        # Embed ~ in the middle of the path just to avoid any $HOME
4154
 
        # interpretation
4155
 
        self.make_master_and_checkout('mas~ter', 'checkout')
4156
 
        self.assertUpdateSucceeds(self.bound_location.replace('%2E', '~', 1))
4157
 
 
4158
 
 
4159
 
class TestWithCustomErrorHandler(RemoteBranchTestCase):
4160
 
 
4161
 
    def test_no_context(self):
4162
 
        class OutOfCoffee(errors.BzrError):
4163
 
            """A dummy exception for testing."""
4164
 
 
4165
 
            def __init__(self, urgency):
4166
 
                self.urgency = urgency
4167
 
        remote.no_context_error_translators.register("OutOfCoffee",
4168
 
            lambda err: OutOfCoffee(err.error_args[0]))
4169
 
        transport = MemoryTransport()
4170
 
        client = FakeClient(transport.base)
4171
 
        client.add_expected_call(
4172
 
            'Branch.get_stacked_on_url', ('quack/',),
4173
 
            'error', ('NotStacked',))
4174
 
        client.add_expected_call(
4175
 
            'Branch.last_revision_info',
4176
 
            ('quack/',),
4177
 
            'error', ('OutOfCoffee', 'low'))
4178
 
        transport.mkdir('quack')
4179
 
        transport = transport.clone('quack')
4180
 
        branch = self.make_remote_branch(transport, client)
4181
 
        self.assertRaises(OutOfCoffee, branch.last_revision_info)
4182
 
        self.assertFinished(client)
4183
 
 
4184
 
    def test_with_context(self):
4185
 
        class OutOfTea(errors.BzrError):
4186
 
            def __init__(self, branch, urgency):
4187
 
                self.branch = branch
4188
 
                self.urgency = urgency
4189
 
        remote.error_translators.register("OutOfTea",
4190
 
            lambda err, find, path: OutOfTea(err.error_args[0],
4191
 
                find("branch")))
4192
 
        transport = MemoryTransport()
4193
 
        client = FakeClient(transport.base)
4194
 
        client.add_expected_call(
4195
 
            'Branch.get_stacked_on_url', ('quack/',),
4196
 
            'error', ('NotStacked',))
4197
 
        client.add_expected_call(
4198
 
            'Branch.last_revision_info',
4199
 
            ('quack/',),
4200
 
            'error', ('OutOfTea', 'low'))
4201
 
        transport.mkdir('quack')
4202
 
        transport = transport.clone('quack')
4203
 
        branch = self.make_remote_branch(transport, client)
4204
 
        self.assertRaises(OutOfTea, branch.last_revision_info)
4205
 
        self.assertFinished(client)
4206
 
 
4207
 
 
4208
 
class TestRepositoryPack(TestRemoteRepository):
4209
 
 
4210
 
    def test_pack(self):
4211
 
        transport_path = 'quack'
4212
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
4213
 
        client.add_expected_call(
4214
 
            'Repository.lock_write', ('quack/', ''),
4215
 
            'success', ('ok', 'token'))
4216
 
        client.add_expected_call(
4217
 
            'Repository.pack', ('quack/', 'token', 'False'),
4218
 
            'success', ('ok',), )
4219
 
        client.add_expected_call(
4220
 
            'Repository.unlock', ('quack/', 'token'),
4221
 
            'success', ('ok', ))
4222
 
        repo.pack()
4223
 
 
4224
 
    def test_pack_with_hint(self):
4225
 
        transport_path = 'quack'
4226
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
4227
 
        client.add_expected_call(
4228
 
            'Repository.lock_write', ('quack/', ''),
4229
 
            'success', ('ok', 'token'))
4230
 
        client.add_expected_call(
4231
 
            'Repository.pack', ('quack/', 'token', 'False'),
4232
 
            'success', ('ok',), )
4233
 
        client.add_expected_call(
4234
 
            'Repository.unlock', ('quack/', 'token', 'False'),
4235
 
            'success', ('ok', ))
4236
 
        repo.pack(['hinta', 'hintb'])
4237
 
 
4238
 
 
4239
 
class TestRepositoryIterInventories(TestRemoteRepository):
4240
 
    """Test Repository.iter_inventories."""
4241
 
 
4242
 
    def _serialize_inv_delta(self, old_name, new_name, delta):
4243
 
        serializer = inventory_delta.InventoryDeltaSerializer(True, False)
4244
 
        return "".join(serializer.delta_to_lines(old_name, new_name, delta))
4245
 
 
4246
 
    def test_single_empty(self):
4247
 
        transport_path = 'quack'
4248
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
4249
 
        fmt = bzrdir.format_registry.get('2a')().repository_format
4250
 
        repo._format = fmt
4251
 
        stream = [('inventory-deltas', [
4252
 
            versionedfile.FulltextContentFactory('somerevid', None, None,
4253
 
                self._serialize_inv_delta('null:', 'somerevid', []))])]
4254
 
        client.add_expected_call(
4255
 
            'VersionedFileRepository.get_inventories', ('quack/', 'unordered'),
4256
 
            'success', ('ok', ),
4257
 
            _stream_to_byte_stream(stream, fmt))
4258
 
        ret = list(repo.iter_inventories(["somerevid"]))
4259
 
        self.assertLength(1, ret)
4260
 
        inv = ret[0]
4261
 
        self.assertEquals("somerevid", inv.revision_id)
4262
 
 
4263
 
    def test_empty(self):
4264
 
        transport_path = 'quack'
4265
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
4266
 
        ret = list(repo.iter_inventories([]))
4267
 
        self.assertEquals(ret, [])
4268
 
 
4269
 
    def test_missing(self):
4270
 
        transport_path = 'quack'
4271
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
4272
 
        client.add_expected_call(
4273
 
            'VersionedFileRepository.get_inventories', ('quack/', 'unordered'),
4274
 
            'success', ('ok', ), iter([]))
4275
 
        self.assertRaises(errors.NoSuchRevision, list, repo.iter_inventories(
4276
 
            ["somerevid"]))