/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/tests/test_remote.py

  • Committer: Jelmer Vernooij
  • Date: 2017-06-04 19:17:13 UTC
  • mfrom: (0.193.10 trunk)
  • mto: This revision was merged to the branch mainline in revision 6778.
  • Revision ID: jelmer@jelmer.uk-20170604191713-hau7dfsqsl035slm
Bundle the cvs plugin.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2006-2013, 2016 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
24
24
"""
25
25
 
26
26
import bz2
27
 
from cStringIO import StringIO
 
27
import zlib
28
28
 
29
 
from bzrlib import (
 
29
from .. import (
 
30
    bencode,
30
31
    branch,
31
32
    bzrdir,
32
33
    config,
 
34
    controldir,
33
35
    errors,
34
 
    graph,
35
36
    inventory,
36
37
    inventory_delta,
37
 
    pack,
38
38
    remote,
39
39
    repository,
40
40
    tests,
 
41
    transport,
41
42
    treebuilder,
42
 
    urlutils,
43
43
    versionedfile,
44
 
    )
45
 
from bzrlib.branch import Branch
46
 
from bzrlib.bzrdir import BzrDir, BzrDirFormat
47
 
from bzrlib.remote import (
 
44
    vf_search,
 
45
    )
 
46
from ..branch import Branch
 
47
from ..bzrdir import (
 
48
    BzrDir,
 
49
    BzrDirFormat,
 
50
    RemoteBzrProber,
 
51
    )
 
52
from ..chk_serializer import chk_bencode_serializer
 
53
from ..remote import (
48
54
    RemoteBranch,
49
55
    RemoteBranchFormat,
50
56
    RemoteBzrDir,
52
58
    RemoteRepository,
53
59
    RemoteRepositoryFormat,
54
60
    )
55
 
from bzrlib.repofmt import groupcompress_repo, pack_repo
56
 
from bzrlib.revision import NULL_REVISION
57
 
from bzrlib.smart import medium
58
 
from bzrlib.smart.client import _SmartClient
59
 
from bzrlib.smart.repository import SmartServerRepositoryGetParentMap
60
 
from bzrlib.tests import (
61
 
    condition_isinstance,
62
 
    split_suite_by_condition,
63
 
    multiply_tests,
 
61
from ..repofmt import groupcompress_repo, knitpack_repo
 
62
from ..revision import (
 
63
    NULL_REVISION,
 
64
    Revision,
 
65
    )
 
66
from ..sixish import (
 
67
    BytesIO,
 
68
    )
 
69
from ..smart import medium, request
 
70
from ..smart.client import _SmartClient
 
71
from ..smart.repository import (
 
72
    SmartServerRepositoryGetParentMap,
 
73
    SmartServerRepositoryGetStream_1_19,
 
74
    _stream_to_byte_stream,
 
75
    )
 
76
from . import (
64
77
    test_server,
65
78
    )
66
 
from bzrlib.transport import get_transport
67
 
from bzrlib.transport.memory import MemoryTransport
68
 
from bzrlib.transport.remote import (
 
79
from .scenarios import load_tests_apply_scenarios
 
80
from ..transport.memory import MemoryTransport
 
81
from ..transport.remote import (
69
82
    RemoteTransport,
70
83
    RemoteSSHTransport,
71
84
    RemoteTCPTransport,
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
    )
 
86
 
 
87
 
 
88
load_tests = load_tests_apply_scenarios
 
89
 
 
90
 
 
91
class BasicRemoteObjectTests(tests.TestCaseWithTransport):
 
92
 
 
93
    scenarios = [
78
94
        ('HPSS-v2',
79
 
         {'transport_server': test_server.SmartTCPServer_for_testing_v2_only}),
 
95
            {'transport_server': test_server.SmartTCPServer_for_testing_v2_only}),
80
96
        ('HPSS-v3',
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):
 
97
            {'transport_server': test_server.SmartTCPServer_for_testing})]
 
98
 
86
99
 
87
100
    def setUp(self):
88
101
        super(BasicRemoteObjectTests, self).setUp()
89
102
        self.transport = self.get_transport()
90
103
        # make a branch that can be opened over the smart transport
91
104
        self.local_wt = BzrDir.create_standalone_workingtree('.')
92
 
 
93
 
    def tearDown(self):
94
 
        self.transport.disconnect()
95
 
        tests.TestCaseWithTransport.tearDown(self)
 
105
        self.addCleanup(self.transport.disconnect)
96
106
 
97
107
    def test_create_remote_bzrdir(self):
98
 
        b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
 
108
        b = remote.RemoteBzrDir(self.transport, RemoteBzrDirFormat())
99
109
        self.assertIsInstance(b, BzrDir)
100
110
 
101
111
    def test_open_remote_branch(self):
102
112
        # open a standalone branch in the working directory
103
 
        b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
 
113
        b = remote.RemoteBzrDir(self.transport, RemoteBzrDirFormat())
104
114
        branch = b.open_branch()
105
115
        self.assertIsInstance(branch, Branch)
106
116
 
112
122
        self.local_wt.commit(message='test commit', rev_id=revid)
113
123
        self.assertTrue(repo.has_revision(revid))
114
124
 
115
 
    def test_remote_branch_revision_history(self):
116
 
        b = BzrDir.open_from_transport(self.transport).open_branch()
117
 
        self.assertEqual([], b.revision_history())
118
 
        r1 = self.local_wt.commit('1st commit')
119
 
        r2 = self.local_wt.commit('1st commit', rev_id=u'\xc8'.encode('utf8'))
120
 
        self.assertEqual([r1, r2], b.revision_history())
121
 
 
122
125
    def test_find_correct_format(self):
123
126
        """Should open a RemoteBzrDir over a RemoteTransport"""
124
127
        fmt = BzrDirFormat.find_format(self.transport)
125
 
        self.assertTrue(RemoteBzrDirFormat
126
 
                        in BzrDirFormat._control_server_formats)
127
 
        self.assertIsInstance(fmt, remote.RemoteBzrDirFormat)
 
128
        self.assertTrue(bzrdir.RemoteBzrProber
 
129
                        in controldir.ControlDirFormat._server_probers)
 
130
        self.assertIsInstance(fmt, RemoteBzrDirFormat)
128
131
 
129
132
    def test_open_detected_smart_format(self):
130
133
        fmt = BzrDirFormat.find_format(self.transport)
164
167
    def test_remote_branch_set_append_revisions_only(self):
165
168
        # Make a format 1.9 branch, which supports append_revisions_only
166
169
        branch = self.make_branch('branch', format='1.9')
167
 
        config = branch.get_config()
168
170
        branch.set_append_revisions_only(True)
 
171
        config = branch.get_config_stack()
169
172
        self.assertEqual(
170
 
            'True', config.get_user_option('append_revisions_only'))
 
173
            True, config.get('append_revisions_only'))
171
174
        branch.set_append_revisions_only(False)
 
175
        config = branch.get_config_stack()
172
176
        self.assertEqual(
173
 
            'False', config.get_user_option('append_revisions_only'))
 
177
            False, config.get('append_revisions_only'))
174
178
 
175
179
    def test_remote_branch_set_append_revisions_only_upgrade_reqd(self):
176
180
        branch = self.make_branch('branch', format='knit')
177
 
        config = branch.get_config()
178
181
        self.assertRaises(
179
182
            errors.UpgradeRequired, branch.set_append_revisions_only, True)
180
183
 
189
192
 
190
193
    def read_body_bytes(self, count=-1):
191
194
        if self._body_buffer is None:
192
 
            self._body_buffer = StringIO(self.body)
 
195
            self._body_buffer = BytesIO(self.body)
193
196
        bytes = self._body_buffer.read(count)
194
197
        if self._body_buffer.tell() == len(self._body_buffer.getvalue()):
195
198
            self._fake_client.expecting_body = False
246
249
    def _get_next_response(self):
247
250
        try:
248
251
            response_tuple = self.responses.pop(0)
249
 
        except IndexError, e:
 
252
        except IndexError as e:
250
253
            raise AssertionError("%r didn't expect any more calls"
251
254
                % (self,))
252
255
        if response_tuple[0] == 'unknown':
338
341
class TestRemote(tests.TestCaseWithMemoryTransport):
339
342
 
340
343
    def get_branch_format(self):
341
 
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
 
344
        reference_bzrdir_format = controldir.format_registry.get('default')()
342
345
        return reference_bzrdir_format.get_branch_format()
343
346
 
344
347
    def get_repo_format(self):
345
 
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
 
348
        reference_bzrdir_format = controldir.format_registry.get('default')()
346
349
        return reference_bzrdir_format.repository_format
347
350
 
348
351
    def assertFinished(self, fake_client):
359
362
        a given client_base and transport_base.
360
363
        """
361
364
        client_medium = medium.SmartClientMedium(client_base)
362
 
        transport = get_transport(transport_base)
363
 
        result = client_medium.remote_path_from_transport(transport)
 
365
        t = transport.get_transport(transport_base)
 
366
        result = client_medium.remote_path_from_transport(t)
364
367
        self.assertEqual(expected, result)
365
368
 
366
369
    def test_remote_path_from_transport(self):
377
380
        a given transport_base and relpath of that transport.  (Note that
378
381
        HttpTransportBase is a subclass of SmartClientMedium)
379
382
        """
380
 
        base_transport = get_transport(transport_base)
 
383
        base_transport = transport.get_transport(transport_base)
381
384
        client_medium = base_transport.get_smart_medium()
382
385
        cloned_transport = base_transport.clone(relpath)
383
386
        result = client_medium.remote_path_from_transport(cloned_transport)
450
453
        client.add_expected_call(
451
454
            'BzrDir.open_branchV3', ('quack/',),
452
455
            'success', ('ref', self.get_url('referenced'))),
453
 
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
456
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
454
457
            _client=client)
455
458
        result = a_bzrdir.cloning_metadir()
456
459
        # We should have got a control dir matching the referenced branch.
464
467
        transport = transport.clone('quack')
465
468
        self.make_bzrdir('quack')
466
469
        client = FakeClient(transport.base)
467
 
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
 
470
        reference_bzrdir_format = controldir.format_registry.get('default')()
468
471
        control_name = reference_bzrdir_format.network_name()
469
472
        client.add_expected_call(
470
473
            'BzrDir.cloning_metadir', ('quack/', 'False'),
471
474
            'success', (control_name, '', ('branch', ''))),
472
 
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
475
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
473
476
            _client=client)
474
477
        result = a_bzrdir.cloning_metadir()
475
478
        # We should have got a reference control dir with default branch and
480
483
        self.assertEqual(None, result._branch_format)
481
484
        self.assertFinished(client)
482
485
 
 
486
    def test_unknown(self):
 
487
        transport = self.get_transport('quack')
 
488
        referenced = self.make_branch('referenced')
 
489
        expected = referenced.bzrdir.cloning_metadir()
 
490
        client = FakeClient(transport.base)
 
491
        client.add_expected_call(
 
492
            'BzrDir.cloning_metadir', ('quack/', 'False'),
 
493
            'success', ('unknown', 'unknown', ('branch', ''))),
 
494
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
495
            _client=client)
 
496
        self.assertRaises(errors.UnknownFormatError, a_bzrdir.cloning_metadir)
 
497
 
 
498
 
 
499
class TestBzrDirCheckoutMetaDir(TestRemote):
 
500
 
 
501
    def test__get_checkout_format(self):
 
502
        transport = MemoryTransport()
 
503
        client = FakeClient(transport.base)
 
504
        reference_bzrdir_format = controldir.format_registry.get('default')()
 
505
        control_name = reference_bzrdir_format.network_name()
 
506
        client.add_expected_call(
 
507
            'BzrDir.checkout_metadir', ('quack/', ),
 
508
            'success', (control_name, '', ''))
 
509
        transport.mkdir('quack')
 
510
        transport = transport.clone('quack')
 
511
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
512
            _client=client)
 
513
        result = a_bzrdir.checkout_metadir()
 
514
        # We should have got a reference control dir with default branch and
 
515
        # repository formats.
 
516
        self.assertEqual(bzrdir.BzrDirMetaFormat1, type(result))
 
517
        self.assertEqual(None, result._repository_format)
 
518
        self.assertEqual(None, result._branch_format)
 
519
        self.assertFinished(client)
 
520
 
 
521
    def test_unknown_format(self):
 
522
        transport = MemoryTransport()
 
523
        client = FakeClient(transport.base)
 
524
        client.add_expected_call(
 
525
            'BzrDir.checkout_metadir', ('quack/',),
 
526
            'success', ('dontknow', '', ''))
 
527
        transport.mkdir('quack')
 
528
        transport = transport.clone('quack')
 
529
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
530
            _client=client)
 
531
        self.assertRaises(errors.UnknownFormatError,
 
532
            a_bzrdir.checkout_metadir)
 
533
        self.assertFinished(client)
 
534
 
 
535
 
 
536
class TestBzrDirGetBranches(TestRemote):
 
537
 
 
538
    def test_get_branches(self):
 
539
        transport = MemoryTransport()
 
540
        client = FakeClient(transport.base)
 
541
        reference_bzrdir_format = controldir.format_registry.get('default')()
 
542
        branch_name = reference_bzrdir_format.get_branch_format().network_name()
 
543
        client.add_success_response_with_body(
 
544
            bencode.bencode({
 
545
                "foo": ("branch", branch_name),
 
546
                "": ("branch", branch_name)}), "success")
 
547
        client.add_success_response(
 
548
            'ok', '', 'no', 'no', 'no',
 
549
                reference_bzrdir_format.repository_format.network_name())
 
550
        client.add_error_response('NotStacked')
 
551
        client.add_success_response(
 
552
            'ok', '', 'no', 'no', 'no',
 
553
                reference_bzrdir_format.repository_format.network_name())
 
554
        client.add_error_response('NotStacked')
 
555
        transport.mkdir('quack')
 
556
        transport = transport.clone('quack')
 
557
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
558
            _client=client)
 
559
        result = a_bzrdir.get_branches()
 
560
        self.assertEqual({"", "foo"}, set(result.keys()))
 
561
        self.assertEqual(
 
562
            [('call_expecting_body', 'BzrDir.get_branches', ('quack/',)),
 
563
             ('call', 'BzrDir.find_repositoryV3', ('quack/', )),
 
564
             ('call', 'Branch.get_stacked_on_url', ('quack/', )),
 
565
             ('call', 'BzrDir.find_repositoryV3', ('quack/', )),
 
566
             ('call', 'Branch.get_stacked_on_url', ('quack/', ))],
 
567
            client._calls)
 
568
 
 
569
 
 
570
class TestBzrDirDestroyBranch(TestRemote):
 
571
 
 
572
    def test_destroy_default(self):
 
573
        transport = self.get_transport('quack')
 
574
        referenced = self.make_branch('referenced')
 
575
        client = FakeClient(transport.base)
 
576
        client.add_expected_call(
 
577
            'BzrDir.destroy_branch', ('quack/', ),
 
578
            'success', ('ok',)),
 
579
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
580
            _client=client)
 
581
        a_bzrdir.destroy_branch()
 
582
        self.assertFinished(client)
 
583
 
 
584
 
 
585
class TestBzrDirHasWorkingTree(TestRemote):
 
586
 
 
587
    def test_has_workingtree(self):
 
588
        transport = self.get_transport('quack')
 
589
        client = FakeClient(transport.base)
 
590
        client.add_expected_call(
 
591
            'BzrDir.has_workingtree', ('quack/',),
 
592
            'success', ('yes',)),
 
593
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
594
            _client=client)
 
595
        self.assertTrue(a_bzrdir.has_workingtree())
 
596
        self.assertFinished(client)
 
597
 
 
598
    def test_no_workingtree(self):
 
599
        transport = self.get_transport('quack')
 
600
        client = FakeClient(transport.base)
 
601
        client.add_expected_call(
 
602
            'BzrDir.has_workingtree', ('quack/',),
 
603
            'success', ('no',)),
 
604
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
605
            _client=client)
 
606
        self.assertFalse(a_bzrdir.has_workingtree())
 
607
        self.assertFinished(client)
 
608
 
 
609
 
 
610
class TestBzrDirDestroyRepository(TestRemote):
 
611
 
 
612
    def test_destroy_repository(self):
 
613
        transport = self.get_transport('quack')
 
614
        client = FakeClient(transport.base)
 
615
        client.add_expected_call(
 
616
            'BzrDir.destroy_repository', ('quack/',),
 
617
            'success', ('ok',)),
 
618
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
619
            _client=client)
 
620
        a_bzrdir.destroy_repository()
 
621
        self.assertFinished(client)
 
622
 
483
623
 
484
624
class TestBzrDirOpen(TestRemote):
485
625
 
495
635
        client.add_expected_call(
496
636
            'BzrDir.open_2.1', ('quack/',), 'success', ('no',))
497
637
        self.assertRaises(errors.NotBranchError, RemoteBzrDir, transport,
498
 
                remote.RemoteBzrDirFormat(), _client=client, _force_probe=True)
 
638
                RemoteBzrDirFormat(), _client=client, _force_probe=True)
499
639
        self.assertFinished(client)
500
640
 
501
641
    def test_present_without_workingtree(self):
502
642
        client, transport = self.make_fake_client_and_transport()
503
643
        client.add_expected_call(
504
644
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'no'))
505
 
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
645
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
506
646
            _client=client, _force_probe=True)
507
647
        self.assertIsInstance(bd, RemoteBzrDir)
508
648
        self.assertFalse(bd.has_workingtree())
513
653
        client, transport = self.make_fake_client_and_transport()
514
654
        client.add_expected_call(
515
655
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'yes'))
516
 
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
656
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
517
657
            _client=client, _force_probe=True)
518
658
        self.assertIsInstance(bd, RemoteBzrDir)
519
659
        self.assertTrue(bd.has_workingtree())
526
666
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
527
667
        client.add_expected_call(
528
668
            'BzrDir.open', ('quack/',), 'success', ('yes',))
529
 
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
669
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
530
670
            _client=client, _force_probe=True)
531
671
        self.assertIsInstance(bd, RemoteBzrDir)
532
672
        self.assertFinished(client)
548
688
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
549
689
        client.add_expected_call(
550
690
            'BzrDir.open', ('quack/',), 'success', ('yes',))
551
 
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
691
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
552
692
            _client=client, _force_probe=True)
553
693
        self.assertIsInstance(bd, RemoteBzrDir)
554
694
        self.assertFinished(client)
585
725
        client.add_expected_call(
586
726
            'Branch.get_stacked_on_url', ('quack/',),
587
727
            'error', ('NotStacked',))
588
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
728
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
589
729
            _client=client)
590
730
        result = bzrdir.open_branch()
591
731
        self.assertIsInstance(result, RemoteBranch)
598
738
        transport = transport.clone('quack')
599
739
        client = FakeClient(transport.base)
600
740
        client.add_error_response('nobranch')
601
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
741
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
602
742
            _client=client)
603
743
        self.assertRaises(errors.NotBranchError, bzrdir.open_branch)
604
744
        self.assertEqual(
609
749
        # _get_tree_branch is a form of open_branch, but it should only ask for
610
750
        # branch opening, not any other network requests.
611
751
        calls = []
612
 
        def open_branch():
 
752
        def open_branch(name=None, possible_transports=None):
613
753
            calls.append("Called")
614
754
            return "a-branch"
615
755
        transport = MemoryTransport()
616
756
        # no requests on the network - catches other api calls being made.
617
757
        client = FakeClient(transport.base)
618
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
758
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
619
759
            _client=client)
620
760
        # patch the open_branch call to record that it was called.
621
761
        bzrdir.open_branch = open_branch
640
780
        client.add_expected_call(
641
781
            'Branch.get_stacked_on_url', ('~hello/',),
642
782
            'error', ('NotStacked',))
643
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
783
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
644
784
            _client=client)
645
785
        result = bzrdir.open_branch()
646
786
        self.assertFinished(client)
663
803
        client.add_success_response(
664
804
            'ok', '', rich_response, subtree_response, external_lookup,
665
805
            network_name)
666
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
806
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
667
807
            _client=client)
668
808
        result = bzrdir.open_repository()
669
809
        self.assertEqual(
686
826
        old.
687
827
        """
688
828
        self.assertRaises(errors.NotBranchError,
689
 
            RemoteBzrDirFormat.probe_transport, OldServerTransport())
 
829
            RemoteBzrProber.probe_transport, OldServerTransport())
690
830
 
691
831
 
692
832
class TestBzrDirCreateBranch(TestRemote):
706
846
        transport = transport.clone('quack')
707
847
        self.make_repository('quack')
708
848
        client = FakeClient(transport.base)
709
 
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
 
849
        reference_bzrdir_format = controldir.format_registry.get('default')()
710
850
        reference_format = reference_bzrdir_format.get_branch_format()
711
851
        network_name = reference_format.network_name()
712
852
        reference_repo_fmt = reference_bzrdir_format.repository_format
715
855
            'BzrDir.create_branch', ('quack/', network_name),
716
856
            'success', ('ok', network_name, '', 'no', 'no', 'yes',
717
857
            reference_repo_name))
718
 
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
858
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
719
859
            _client=client)
720
860
        branch = a_bzrdir.create_branch()
721
861
        # We should have got a remote branch
724
864
        format = branch._format
725
865
        self.assertEqual(network_name, format.network_name())
726
866
 
 
867
    def test_already_open_repo_and_reused_medium(self):
 
868
        """Bug 726584: create_branch(..., repository=repo) should work
 
869
        regardless of what the smart medium's base URL is.
 
870
        """
 
871
        self.transport_server = test_server.SmartTCPServer_for_testing
 
872
        transport = self.get_transport('.')
 
873
        repo = self.make_repository('quack')
 
874
        # Client's medium rooted a transport root (not at the bzrdir)
 
875
        client = FakeClient(transport.base)
 
876
        transport = transport.clone('quack')
 
877
        reference_bzrdir_format = controldir.format_registry.get('default')()
 
878
        reference_format = reference_bzrdir_format.get_branch_format()
 
879
        network_name = reference_format.network_name()
 
880
        reference_repo_fmt = reference_bzrdir_format.repository_format
 
881
        reference_repo_name = reference_repo_fmt.network_name()
 
882
        client.add_expected_call(
 
883
            'BzrDir.create_branch', ('extra/quack/', network_name),
 
884
            'success', ('ok', network_name, '', 'no', 'no', 'yes',
 
885
            reference_repo_name))
 
886
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
887
            _client=client)
 
888
        branch = a_bzrdir.create_branch(repository=repo)
 
889
        # We should have got a remote branch
 
890
        self.assertIsInstance(branch, remote.RemoteBranch)
 
891
        # its format should have the settings from the response
 
892
        format = branch._format
 
893
        self.assertEqual(network_name, format.network_name())
 
894
 
727
895
 
728
896
class TestBzrDirCreateRepository(TestRemote):
729
897
 
742
910
        transport = transport.clone('quack')
743
911
        self.make_bzrdir('quack')
744
912
        client = FakeClient(transport.base)
745
 
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
 
913
        reference_bzrdir_format = controldir.format_registry.get('default')()
746
914
        reference_format = reference_bzrdir_format.repository_format
747
915
        network_name = reference_format.network_name()
748
916
        client.add_expected_call(
750
918
                'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
751
919
                'False'),
752
920
            'success', ('ok', 'yes', 'yes', 'yes', network_name))
753
 
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
921
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
754
922
            _client=client)
755
923
        repo = a_bzrdir.create_repository()
756
924
        # We should have got a remote repository
779
947
        # name.
780
948
        client.add_success_response_with_body(
781
949
            "Bazaar-NG meta directory, format 1\n", 'ok')
 
950
        client.add_success_response('stat', '0', '65535')
782
951
        client.add_success_response_with_body(
783
952
            reference_format.get_format_string(), 'ok')
784
953
        # PackRepository wants to do a stat
785
954
        client.add_success_response('stat', '0', '65535')
786
955
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
787
956
            _client=client)
788
 
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
 
957
        bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
789
958
            _client=client)
790
959
        repo = bzrdir.open_repository()
791
960
        self.assertEqual(
793
962
             ('call', 'BzrDir.find_repositoryV2', ('quack/',)),
794
963
             ('call', 'BzrDir.find_repository', ('quack/',)),
795
964
             ('call_expecting_body', 'get', ('/quack/.bzr/branch-format',)),
 
965
             ('call', 'stat', ('/quack/.bzr',)),
796
966
             ('call_expecting_body', 'get', ('/quack/.bzr/repository/format',)),
797
967
             ('call', 'stat', ('/quack/.bzr/repository',)),
798
968
             ],
812
982
        # name.
813
983
        client.add_success_response_with_body(
814
984
            "Bazaar-NG meta directory, format 1\n", 'ok')
 
985
        client.add_success_response('stat', '0', '65535')
815
986
        client.add_success_response_with_body(
816
987
            reference_format.get_format_string(), 'ok')
817
988
        # PackRepository wants to do a stat
818
989
        client.add_success_response('stat', '0', '65535')
819
990
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
820
991
            _client=client)
821
 
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
 
992
        bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
822
993
            _client=client)
823
994
        repo = bzrdir.open_repository()
824
995
        self.assertEqual(
825
996
            [('call', 'BzrDir.find_repositoryV3', ('quack/',)),
826
997
             ('call', 'BzrDir.find_repositoryV2', ('quack/',)),
827
998
             ('call_expecting_body', 'get', ('/quack/.bzr/branch-format',)),
 
999
             ('call', 'stat', ('/quack/.bzr',)),
828
1000
             ('call_expecting_body', 'get', ('/quack/.bzr/repository/format',)),
829
1001
             ('call', 'stat', ('/quack/.bzr/repository',)),
830
1002
             ],
839
1011
        transport = transport.clone('quack')
840
1012
        client = FakeClient(transport.base)
841
1013
        client.add_success_response('ok', '', 'no', 'no', 'no', network_name)
842
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
1014
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
843
1015
            _client=client)
844
1016
        repo = bzrdir.open_repository()
845
1017
        self.assertEqual(
852
1024
 
853
1025
    def test_success(self):
854
1026
        """Simple test for typical successful call."""
855
 
        fmt = bzrdir.RemoteBzrDirFormat()
 
1027
        fmt = RemoteBzrDirFormat()
856
1028
        default_format_name = BzrDirFormat.get_default_format().network_name()
857
1029
        transport = self.get_transport()
858
1030
        client = FakeClient(transport.base)
874
1046
        """Error responses are translated, e.g. 'PermissionDenied' raises the
875
1047
        corresponding error from the client.
876
1048
        """
877
 
        fmt = bzrdir.RemoteBzrDirFormat()
 
1049
        fmt = RemoteBzrDirFormat()
878
1050
        default_format_name = BzrDirFormat.get_default_format().network_name()
879
1051
        transport = self.get_transport()
880
1052
        client = FakeClient(transport.base)
898
1070
        """Integration test for error translation."""
899
1071
        transport = self.make_smart_server('foo')
900
1072
        transport = transport.clone('no-such-path')
901
 
        fmt = bzrdir.RemoteBzrDirFormat()
 
1073
        fmt = RemoteBzrDirFormat()
902
1074
        err = self.assertRaises(errors.NoSuchFile,
903
1075
            fmt.initialize_on_transport_ex, transport, create_prefix=False)
904
1076
 
909
1081
    """
910
1082
 
911
1083
    def get_request(self):
912
 
        input_file = StringIO('ok\x011\n')
913
 
        output_file = StringIO()
 
1084
        input_file = BytesIO(b'ok\x011\n')
 
1085
        output_file = BytesIO()
914
1086
        client_medium = medium.SmartSimplePipesClientMedium(
915
1087
            input_file, output_file)
916
1088
        return medium.SmartClientStreamMediumRequest(client_medium)
935
1107
 
936
1108
    def make_remote_bzrdir(self, transport, client):
937
1109
        """Make a RemotebzrDir using 'client' as the _client."""
938
 
        return RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
1110
        return RemoteBzrDir(transport, RemoteBzrDirFormat(),
939
1111
            _client=client)
940
1112
 
941
1113
 
967
1139
        return RemoteBranch(bzrdir, repo, _client=client, format=format)
968
1140
 
969
1141
 
 
1142
class TestBranchBreakLock(RemoteBranchTestCase):
 
1143
 
 
1144
    def test_break_lock(self):
 
1145
        transport_path = 'quack'
 
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.break_lock', ('quack/',),
 
1153
            'success', ('ok',))
 
1154
        transport.mkdir('quack')
 
1155
        transport = transport.clone('quack')
 
1156
        branch = self.make_remote_branch(transport, client)
 
1157
        branch.break_lock()
 
1158
        self.assertFinished(client)
 
1159
 
 
1160
 
 
1161
class TestBranchGetPhysicalLockStatus(RemoteBranchTestCase):
 
1162
 
 
1163
    def test_get_physical_lock_status_yes(self):
 
1164
        transport = MemoryTransport()
 
1165
        client = FakeClient(transport.base)
 
1166
        client.add_expected_call(
 
1167
            'Branch.get_stacked_on_url', ('quack/',),
 
1168
            'error', ('NotStacked',))
 
1169
        client.add_expected_call(
 
1170
            'Branch.get_physical_lock_status', ('quack/',),
 
1171
            'success', ('yes',))
 
1172
        transport.mkdir('quack')
 
1173
        transport = transport.clone('quack')
 
1174
        branch = self.make_remote_branch(transport, client)
 
1175
        result = branch.get_physical_lock_status()
 
1176
        self.assertFinished(client)
 
1177
        self.assertEqual(True, result)
 
1178
 
 
1179
    def test_get_physical_lock_status_no(self):
 
1180
        transport = MemoryTransport()
 
1181
        client = FakeClient(transport.base)
 
1182
        client.add_expected_call(
 
1183
            'Branch.get_stacked_on_url', ('quack/',),
 
1184
            'error', ('NotStacked',))
 
1185
        client.add_expected_call(
 
1186
            'Branch.get_physical_lock_status', ('quack/',),
 
1187
            'success', ('no',))
 
1188
        transport.mkdir('quack')
 
1189
        transport = transport.clone('quack')
 
1190
        branch = self.make_remote_branch(transport, client)
 
1191
        result = branch.get_physical_lock_status()
 
1192
        self.assertFinished(client)
 
1193
        self.assertEqual(False, result)
 
1194
 
 
1195
 
970
1196
class TestBranchGetParent(RemoteBranchTestCase):
971
1197
 
972
1198
    def test_no_parent(self):
1062
1288
        verb = 'Branch.set_parent_location'
1063
1289
        self.disable_verb(verb)
1064
1290
        branch.set_parent('http://foo/')
1065
 
        self.assertLength(12, self.hpss_calls)
 
1291
        self.assertLength(14, self.hpss_calls)
1066
1292
 
1067
1293
 
1068
1294
class TestBranchGetTagsBytes(RemoteBranchTestCase):
1143
1369
            [('set_tags_bytes', 'tags bytes')] * 2, real_branch.calls)
1144
1370
 
1145
1371
 
 
1372
class TestBranchHeadsToFetch(RemoteBranchTestCase):
 
1373
 
 
1374
    def test_uses_last_revision_info_and_tags_by_default(self):
 
1375
        transport = MemoryTransport()
 
1376
        client = FakeClient(transport.base)
 
1377
        client.add_expected_call(
 
1378
            'Branch.get_stacked_on_url', ('quack/',),
 
1379
            'error', ('NotStacked',))
 
1380
        client.add_expected_call(
 
1381
            'Branch.last_revision_info', ('quack/',),
 
1382
            'success', ('ok', '1', 'rev-tip'))
 
1383
        client.add_expected_call(
 
1384
            'Branch.get_config_file', ('quack/',),
 
1385
            'success', ('ok',), '')
 
1386
        transport.mkdir('quack')
 
1387
        transport = transport.clone('quack')
 
1388
        branch = self.make_remote_branch(transport, client)
 
1389
        result = branch.heads_to_fetch()
 
1390
        self.assertFinished(client)
 
1391
        self.assertEqual(({'rev-tip'}, set()), result)
 
1392
 
 
1393
    def test_uses_last_revision_info_and_tags_when_set(self):
 
1394
        transport = MemoryTransport()
 
1395
        client = FakeClient(transport.base)
 
1396
        client.add_expected_call(
 
1397
            'Branch.get_stacked_on_url', ('quack/',),
 
1398
            'error', ('NotStacked',))
 
1399
        client.add_expected_call(
 
1400
            'Branch.last_revision_info', ('quack/',),
 
1401
            'success', ('ok', '1', 'rev-tip'))
 
1402
        client.add_expected_call(
 
1403
            'Branch.get_config_file', ('quack/',),
 
1404
            'success', ('ok',), 'branch.fetch_tags = True')
 
1405
        # XXX: this will break if the default format's serialization of tags
 
1406
        # changes, or if the RPC for fetching tags changes from get_tags_bytes.
 
1407
        client.add_expected_call(
 
1408
            'Branch.get_tags_bytes', ('quack/',),
 
1409
            'success', ('d5:tag-17:rev-foo5:tag-27:rev-bare',))
 
1410
        transport.mkdir('quack')
 
1411
        transport = transport.clone('quack')
 
1412
        branch = self.make_remote_branch(transport, client)
 
1413
        result = branch.heads_to_fetch()
 
1414
        self.assertFinished(client)
 
1415
        self.assertEqual(
 
1416
            ({'rev-tip'}, {'rev-foo', 'rev-bar'}), result)
 
1417
 
 
1418
    def test_uses_rpc_for_formats_with_non_default_heads_to_fetch(self):
 
1419
        transport = MemoryTransport()
 
1420
        client = FakeClient(transport.base)
 
1421
        client.add_expected_call(
 
1422
            'Branch.get_stacked_on_url', ('quack/',),
 
1423
            'error', ('NotStacked',))
 
1424
        client.add_expected_call(
 
1425
            'Branch.heads_to_fetch', ('quack/',),
 
1426
            'success', (['tip'], ['tagged-1', 'tagged-2']))
 
1427
        transport.mkdir('quack')
 
1428
        transport = transport.clone('quack')
 
1429
        branch = self.make_remote_branch(transport, client)
 
1430
        branch._format._use_default_local_heads_to_fetch = lambda: False
 
1431
        result = branch.heads_to_fetch()
 
1432
        self.assertFinished(client)
 
1433
        self.assertEqual(({'tip'}, {'tagged-1', 'tagged-2'}), result)
 
1434
 
 
1435
    def make_branch_with_tags(self):
 
1436
        self.setup_smart_server_with_call_log()
 
1437
        # Make a branch with a single revision.
 
1438
        builder = self.make_branch_builder('foo')
 
1439
        builder.start_series()
 
1440
        builder.build_snapshot('tip', None, [
 
1441
            ('add', ('', 'root-id', 'directory', ''))])
 
1442
        builder.finish_series()
 
1443
        branch = builder.get_branch()
 
1444
        # Add two tags to that branch
 
1445
        branch.tags.set_tag('tag-1', 'rev-1')
 
1446
        branch.tags.set_tag('tag-2', 'rev-2')
 
1447
        return branch
 
1448
 
 
1449
    def test_backwards_compatible(self):
 
1450
        br = self.make_branch_with_tags()
 
1451
        br.get_config_stack().set('branch.fetch_tags', True)
 
1452
        self.addCleanup(br.lock_read().unlock)
 
1453
        # Disable the heads_to_fetch verb
 
1454
        verb = 'Branch.heads_to_fetch'
 
1455
        self.disable_verb(verb)
 
1456
        self.reset_smart_call_log()
 
1457
        result = br.heads_to_fetch()
 
1458
        self.assertEqual(({'tip'}, {'rev-1', 'rev-2'}), result)
 
1459
        self.assertEqual(
 
1460
            ['Branch.last_revision_info', 'Branch.get_tags_bytes'],
 
1461
            [call.call.method for call in self.hpss_calls])
 
1462
 
 
1463
    def test_backwards_compatible_no_tags(self):
 
1464
        br = self.make_branch_with_tags()
 
1465
        br.get_config_stack().set('branch.fetch_tags', False)
 
1466
        self.addCleanup(br.lock_read().unlock)
 
1467
        # Disable the heads_to_fetch verb
 
1468
        verb = 'Branch.heads_to_fetch'
 
1469
        self.disable_verb(verb)
 
1470
        self.reset_smart_call_log()
 
1471
        result = br.heads_to_fetch()
 
1472
        self.assertEqual(({'tip'}, set()), result)
 
1473
        self.assertEqual(
 
1474
            ['Branch.last_revision_info'],
 
1475
            [call.call.method for call in self.hpss_calls])
 
1476
 
 
1477
 
1146
1478
class TestBranchLastRevisionInfo(RemoteBranchTestCase):
1147
1479
 
1148
1480
    def test_empty_branch(self):
1203
1535
        client.add_expected_call(
1204
1536
            'Branch.get_stacked_on_url', ('stacked/',),
1205
1537
            'success', ('ok', vfs_url))
1206
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
1538
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1207
1539
            _client=client)
1208
1540
        repo_fmt = remote.RemoteRepositoryFormat()
1209
1541
        repo_fmt._custom_format = stacked_branch.repository._format
1236
1568
        # this will also do vfs access, but that goes direct to the transport
1237
1569
        # and isn't seen by the FakeClient.
1238
1570
        bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1239
 
            remote.RemoteBzrDirFormat(), _client=client)
 
1571
            RemoteBzrDirFormat(), _client=client)
1240
1572
        branch = bzrdir.open_branch()
1241
1573
        result = branch.get_stacked_on_url()
1242
1574
        self.assertEqual('../base', result)
1269
1601
            'Branch.get_stacked_on_url', ('stacked/',),
1270
1602
            'success', ('ok', '../base'))
1271
1603
        bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1272
 
            remote.RemoteBzrDirFormat(), _client=client)
 
1604
            RemoteBzrDirFormat(), _client=client)
1273
1605
        branch = bzrdir.open_branch()
1274
1606
        result = branch.get_stacked_on_url()
1275
1607
        self.assertEqual('../base', result)
1283
1615
class TestBranchSetLastRevision(RemoteBranchTestCase):
1284
1616
 
1285
1617
    def test_set_empty(self):
1286
 
        # set_revision_history([]) is translated to calling
 
1618
        # _set_last_revision_info('null:') is translated to calling
1287
1619
        # Branch.set_last_revision(path, '') on the wire.
1288
1620
        transport = MemoryTransport()
1289
1621
        transport.mkdir('branch')
1307
1639
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1308
1640
            'success', ('ok',))
1309
1641
        branch = self.make_remote_branch(transport, client)
1310
 
        # This is a hack to work around the problem that RemoteBranch currently
1311
 
        # unnecessarily invokes _ensure_real upon a call to lock_write.
1312
 
        branch._ensure_real = lambda: None
1313
1642
        branch.lock_write()
1314
 
        result = branch.set_revision_history([])
 
1643
        result = branch._set_last_revision(NULL_REVISION)
1315
1644
        branch.unlock()
1316
1645
        self.assertEqual(None, result)
1317
1646
        self.assertFinished(client)
1318
1647
 
1319
1648
    def test_set_nonempty(self):
1320
 
        # set_revision_history([rev-id1, ..., rev-idN]) is translated to calling
 
1649
        # set_last_revision_info(N, rev-idN) is translated to calling
1321
1650
        # Branch.set_last_revision(path, rev-idN) on the wire.
1322
1651
        transport = MemoryTransport()
1323
1652
        transport.mkdir('branch')
1344
1673
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1345
1674
            'success', ('ok',))
1346
1675
        branch = self.make_remote_branch(transport, client)
1347
 
        # This is a hack to work around the problem that RemoteBranch currently
1348
 
        # unnecessarily invokes _ensure_real upon a call to lock_write.
1349
 
        branch._ensure_real = lambda: None
1350
1676
        # Lock the branch, reset the record of remote calls.
1351
1677
        branch.lock_write()
1352
 
        result = branch.set_revision_history(['rev-id1', 'rev-id2'])
 
1678
        result = branch._set_last_revision('rev-id2')
1353
1679
        branch.unlock()
1354
1680
        self.assertEqual(None, result)
1355
1681
        self.assertFinished(client)
1385
1711
        branch = self.make_remote_branch(transport, client)
1386
1712
        branch.lock_write()
1387
1713
        self.assertRaises(
1388
 
            errors.NoSuchRevision, branch.set_revision_history, ['rev-id'])
 
1714
            errors.NoSuchRevision, branch._set_last_revision, 'rev-id')
1389
1715
        branch.unlock()
1390
1716
        self.assertFinished(client)
1391
1717
 
1419
1745
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1420
1746
            'success', ('ok',))
1421
1747
        branch = self.make_remote_branch(transport, client)
1422
 
        branch._ensure_real = lambda: None
1423
1748
        branch.lock_write()
1424
1749
        # The 'TipChangeRejected' error response triggered by calling
1425
 
        # set_revision_history causes a TipChangeRejected exception.
 
1750
        # set_last_revision_info causes a TipChangeRejected exception.
1426
1751
        err = self.assertRaises(
1427
 
            errors.TipChangeRejected, branch.set_revision_history, ['rev-id'])
 
1752
            errors.TipChangeRejected,
 
1753
            branch._set_last_revision, 'rev-id')
1428
1754
        # The UTF-8 message from the response has been decoded into a unicode
1429
1755
        # object.
1430
1756
        self.assertIsInstance(err.msg, unicode)
1618
1944
    def test_get_multi_line_branch_conf(self):
1619
1945
        # Make sure that multiple-line branch.conf files are supported
1620
1946
        #
1621
 
        # https://bugs.edge.launchpad.net/bzr/+bug/354075
 
1947
        # https://bugs.launchpad.net/bzr/+bug/354075
1622
1948
        client = FakeClient()
1623
1949
        client.add_expected_call(
1624
1950
            'Branch.get_stacked_on_url', ('memory:///',),
1652
1978
        branch.unlock()
1653
1979
        self.assertFinished(client)
1654
1980
 
 
1981
    def test_set_option_with_dict(self):
 
1982
        client = FakeClient()
 
1983
        client.add_expected_call(
 
1984
            'Branch.get_stacked_on_url', ('memory:///',),
 
1985
            'error', ('NotStacked',),)
 
1986
        client.add_expected_call(
 
1987
            'Branch.lock_write', ('memory:///', '', ''),
 
1988
            'success', ('ok', 'branch token', 'repo token'))
 
1989
        encoded_dict_value = 'd5:ascii1:a11:unicode \xe2\x8c\x9a3:\xe2\x80\xbde'
 
1990
        client.add_expected_call(
 
1991
            'Branch.set_config_option_dict', ('memory:///', 'branch token',
 
1992
            'repo token', encoded_dict_value, 'foo', ''),
 
1993
            'success', ())
 
1994
        client.add_expected_call(
 
1995
            'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
 
1996
            'success', ('ok',))
 
1997
        transport = MemoryTransport()
 
1998
        branch = self.make_remote_branch(transport, client)
 
1999
        branch.lock_write()
 
2000
        config = branch._get_config()
 
2001
        config.set_option(
 
2002
            {'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'},
 
2003
            'foo')
 
2004
        branch.unlock()
 
2005
        self.assertFinished(client)
 
2006
 
1655
2007
    def test_backwards_compat_set_option(self):
1656
2008
        self.setup_smart_server_with_call_log()
1657
2009
        branch = self.make_branch('.')
1661
2013
        self.addCleanup(branch.unlock)
1662
2014
        self.reset_smart_call_log()
1663
2015
        branch._get_config().set_option('value', 'name')
1664
 
        self.assertLength(10, self.hpss_calls)
 
2016
        self.assertLength(11, self.hpss_calls)
1665
2017
        self.assertEqual('value', branch._get_config().get_option('name'))
1666
2018
 
 
2019
    def test_backwards_compat_set_option_with_dict(self):
 
2020
        self.setup_smart_server_with_call_log()
 
2021
        branch = self.make_branch('.')
 
2022
        verb = 'Branch.set_config_option_dict'
 
2023
        self.disable_verb(verb)
 
2024
        branch.lock_write()
 
2025
        self.addCleanup(branch.unlock)
 
2026
        self.reset_smart_call_log()
 
2027
        config = branch._get_config()
 
2028
        value_dict = {'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'}
 
2029
        config.set_option(value_dict, 'name')
 
2030
        self.assertLength(11, self.hpss_calls)
 
2031
        self.assertEqual(value_dict, branch._get_config().get_option('name'))
 
2032
 
 
2033
 
 
2034
class TestBranchGetPutConfigStore(RemoteBranchTestCase):
 
2035
 
 
2036
    def test_get_branch_conf(self):
 
2037
        # in an empty branch we decode the response properly
 
2038
        client = FakeClient()
 
2039
        client.add_expected_call(
 
2040
            'Branch.get_stacked_on_url', ('memory:///',),
 
2041
            'error', ('NotStacked',),)
 
2042
        client.add_success_response_with_body('# config file body', 'ok')
 
2043
        transport = MemoryTransport()
 
2044
        branch = self.make_remote_branch(transport, client)
 
2045
        config = branch.get_config_stack()
 
2046
        config.get("email")
 
2047
        config.get("log_format")
 
2048
        self.assertEqual(
 
2049
            [('call', 'Branch.get_stacked_on_url', ('memory:///',)),
 
2050
             ('call_expecting_body', 'Branch.get_config_file', ('memory:///',))],
 
2051
            client._calls)
 
2052
 
 
2053
    def test_set_branch_conf(self):
 
2054
        client = FakeClient()
 
2055
        client.add_expected_call(
 
2056
            'Branch.get_stacked_on_url', ('memory:///',),
 
2057
            'error', ('NotStacked',),)
 
2058
        client.add_expected_call(
 
2059
            'Branch.lock_write', ('memory:///', '', ''),
 
2060
            'success', ('ok', 'branch token', 'repo token'))
 
2061
        client.add_expected_call(
 
2062
            'Branch.get_config_file', ('memory:///', ),
 
2063
            'success', ('ok', ), "# line 1\n")
 
2064
        client.add_expected_call(
 
2065
            'Branch.get_config_file', ('memory:///', ),
 
2066
            'success', ('ok', ), "# line 1\n")
 
2067
        client.add_expected_call(
 
2068
            'Branch.put_config_file', ('memory:///', 'branch token',
 
2069
            'repo token'),
 
2070
            'success', ('ok',))
 
2071
        client.add_expected_call(
 
2072
            'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
 
2073
            'success', ('ok',))
 
2074
        transport = MemoryTransport()
 
2075
        branch = self.make_remote_branch(transport, client)
 
2076
        branch.lock_write()
 
2077
        config = branch.get_config_stack()
 
2078
        config.set('email', 'The Dude <lebowski@example.com>')
 
2079
        branch.unlock()
 
2080
        self.assertFinished(client)
 
2081
        self.assertEqual(
 
2082
            [('call', 'Branch.get_stacked_on_url', ('memory:///',)),
 
2083
             ('call', 'Branch.lock_write', ('memory:///', '', '')),
 
2084
             ('call_expecting_body', 'Branch.get_config_file', ('memory:///',)),
 
2085
             ('call_expecting_body', 'Branch.get_config_file', ('memory:///',)),
 
2086
             ('call_with_body_bytes_expecting_body', 'Branch.put_config_file',
 
2087
                 ('memory:///', 'branch token', 'repo token'),
 
2088
                 '# line 1\nemail = The Dude <lebowski@example.com>\n'),
 
2089
             ('call', 'Branch.unlock', ('memory:///', 'branch token', 'repo token'))],
 
2090
            client._calls)
 
2091
 
1667
2092
 
1668
2093
class TestBranchLockWrite(RemoteBranchTestCase):
1669
2094
 
1683
2108
        self.assertFinished(client)
1684
2109
 
1685
2110
 
 
2111
class TestBranchRevisionIdToRevno(RemoteBranchTestCase):
 
2112
 
 
2113
    def test_simple(self):
 
2114
        transport = MemoryTransport()
 
2115
        client = FakeClient(transport.base)
 
2116
        client.add_expected_call(
 
2117
            'Branch.get_stacked_on_url', ('quack/',),
 
2118
            'error', ('NotStacked',),)
 
2119
        client.add_expected_call(
 
2120
            'Branch.revision_id_to_revno', ('quack/', 'null:'),
 
2121
            'success', ('ok', '0',),)
 
2122
        client.add_expected_call(
 
2123
            'Branch.revision_id_to_revno', ('quack/', 'unknown'),
 
2124
            'error', ('NoSuchRevision', 'unknown',),)
 
2125
        transport.mkdir('quack')
 
2126
        transport = transport.clone('quack')
 
2127
        branch = self.make_remote_branch(transport, client)
 
2128
        self.assertEqual(0, branch.revision_id_to_revno('null:'))
 
2129
        self.assertRaises(errors.NoSuchRevision,
 
2130
            branch.revision_id_to_revno, 'unknown')
 
2131
        self.assertFinished(client)
 
2132
 
 
2133
    def test_dotted(self):
 
2134
        transport = MemoryTransport()
 
2135
        client = FakeClient(transport.base)
 
2136
        client.add_expected_call(
 
2137
            'Branch.get_stacked_on_url', ('quack/',),
 
2138
            'error', ('NotStacked',),)
 
2139
        client.add_expected_call(
 
2140
            'Branch.revision_id_to_revno', ('quack/', 'null:'),
 
2141
            'success', ('ok', '0',),)
 
2142
        client.add_expected_call(
 
2143
            'Branch.revision_id_to_revno', ('quack/', 'unknown'),
 
2144
            'error', ('NoSuchRevision', 'unknown',),)
 
2145
        transport.mkdir('quack')
 
2146
        transport = transport.clone('quack')
 
2147
        branch = self.make_remote_branch(transport, client)
 
2148
        self.assertEqual((0, ), branch.revision_id_to_dotted_revno('null:'))
 
2149
        self.assertRaises(errors.NoSuchRevision,
 
2150
            branch.revision_id_to_dotted_revno, 'unknown')
 
2151
        self.assertFinished(client)
 
2152
 
 
2153
    def test_dotted_no_smart_verb(self):
 
2154
        self.setup_smart_server_with_call_log()
 
2155
        branch = self.make_branch('.')
 
2156
        self.disable_verb('Branch.revision_id_to_revno')
 
2157
        self.reset_smart_call_log()
 
2158
        self.assertEqual((0, ),
 
2159
            branch.revision_id_to_dotted_revno('null:'))
 
2160
        self.assertLength(8, self.hpss_calls)
 
2161
 
 
2162
 
1686
2163
class TestBzrDirGetSetConfig(RemoteBzrDirTestCase):
1687
2164
 
1688
2165
    def test__get_config(self):
1702
2179
        self.reset_smart_call_log()
1703
2180
        config = bzrdir.get_config()
1704
2181
        config.set_default_stack_on('/')
1705
 
        self.assertLength(3, self.hpss_calls)
 
2182
        self.assertLength(4, self.hpss_calls)
1706
2183
 
1707
2184
    def test_backwards_compat_get_option(self):
1708
2185
        self.setup_smart_server_with_call_log()
1712
2189
        self.reset_smart_call_log()
1713
2190
        self.assertEqual(None,
1714
2191
            bzrdir._get_config().get_option('default_stack_on'))
1715
 
        self.assertLength(3, self.hpss_calls)
 
2192
        self.assertLength(4, self.hpss_calls)
1716
2193
 
1717
2194
 
1718
2195
class TestTransportIsReadonly(tests.TestCase):
1805
2282
        client = FakeClient(transport.base)
1806
2283
        transport = transport.clone(transport_path)
1807
2284
        # we do not want bzrdir to make any remote calls
1808
 
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
 
2285
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1809
2286
            _client=False)
1810
2287
        repo = RemoteRepository(bzrdir, None, _client=client)
1811
2288
        return repo, client
1819
2296
 
1820
2297
    def test_get_format_description(self):
1821
2298
        remote_format = RemoteBranchFormat()
1822
 
        real_format = branch.BranchFormat.get_default_format()
 
2299
        real_format = branch.format_registry.get_default()
1823
2300
        remote_format._network_name = real_format.network_name()
1824
2301
        self.assertEqual(remoted_description(real_format),
1825
2302
            remote_format.get_format_description())
1828
2305
class TestRepositoryFormat(TestRemoteRepository):
1829
2306
 
1830
2307
    def test_fast_delta(self):
1831
 
        true_name = groupcompress_repo.RepositoryFormatCHK1().network_name()
 
2308
        true_name = groupcompress_repo.RepositoryFormat2a().network_name()
1832
2309
        true_format = RemoteRepositoryFormat()
1833
2310
        true_format._network_name = true_name
1834
2311
        self.assertEqual(True, true_format.fast_deltas)
1835
 
        false_name = pack_repo.RepositoryFormatKnitPack1().network_name()
 
2312
        false_name = knitpack_repo.RepositoryFormatKnitPack1().network_name()
1836
2313
        false_format = RemoteRepositoryFormat()
1837
2314
        false_format._network_name = false_name
1838
2315
        self.assertEqual(False, false_format.fast_deltas)
1839
2316
 
1840
2317
    def test_get_format_description(self):
1841
2318
        remote_repo_format = RemoteRepositoryFormat()
1842
 
        real_format = repository.RepositoryFormat.get_default_format()
 
2319
        real_format = repository.format_registry.get_default()
1843
2320
        remote_repo_format._network_name = real_format.network_name()
1844
2321
        self.assertEqual(remoted_description(real_format),
1845
2322
            remote_repo_format.get_format_description())
1846
2323
 
1847
2324
 
 
2325
class TestRepositoryAllRevisionIds(TestRemoteRepository):
 
2326
 
 
2327
    def test_empty(self):
 
2328
        transport_path = 'quack'
 
2329
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2330
        client.add_success_response_with_body('', 'ok')
 
2331
        self.assertEqual([], repo.all_revision_ids())
 
2332
        self.assertEqual(
 
2333
            [('call_expecting_body', 'Repository.all_revision_ids',
 
2334
             ('quack/',))],
 
2335
            client._calls)
 
2336
 
 
2337
    def test_with_some_content(self):
 
2338
        transport_path = 'quack'
 
2339
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2340
        client.add_success_response_with_body(
 
2341
            'rev1\nrev2\nanotherrev\n', 'ok')
 
2342
        self.assertEqual(["rev1", "rev2", "anotherrev"],
 
2343
            repo.all_revision_ids())
 
2344
        self.assertEqual(
 
2345
            [('call_expecting_body', 'Repository.all_revision_ids',
 
2346
             ('quack/',))],
 
2347
            client._calls)
 
2348
 
 
2349
 
1848
2350
class TestRepositoryGatherStats(TestRemoteRepository):
1849
2351
 
1850
2352
    def test_revid_none(self):
1903
2405
                         result)
1904
2406
 
1905
2407
 
 
2408
class TestRepositoryBreakLock(TestRemoteRepository):
 
2409
 
 
2410
    def test_break_lock(self):
 
2411
        transport_path = 'quack'
 
2412
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2413
        client.add_success_response('ok')
 
2414
        repo.break_lock()
 
2415
        self.assertEqual(
 
2416
            [('call', 'Repository.break_lock', ('quack/',))],
 
2417
            client._calls)
 
2418
 
 
2419
 
 
2420
class TestRepositoryGetSerializerFormat(TestRemoteRepository):
 
2421
 
 
2422
    def test_get_serializer_format(self):
 
2423
        transport_path = 'hill'
 
2424
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2425
        client.add_success_response('ok', '7')
 
2426
        self.assertEqual('7', repo.get_serializer_format())
 
2427
        self.assertEqual(
 
2428
            [('call', 'VersionedFileRepository.get_serializer_format',
 
2429
              ('hill/', ))],
 
2430
            client._calls)
 
2431
 
 
2432
 
 
2433
class TestRepositoryReconcile(TestRemoteRepository):
 
2434
 
 
2435
    def test_reconcile(self):
 
2436
        transport_path = 'hill'
 
2437
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2438
        body = ("garbage_inventories: 2\n"
 
2439
                "inconsistent_parents: 3\n")
 
2440
        client.add_expected_call(
 
2441
            'Repository.lock_write', ('hill/', ''),
 
2442
            'success', ('ok', 'a token'))
 
2443
        client.add_success_response_with_body(body, 'ok')
 
2444
        reconciler = repo.reconcile()
 
2445
        self.assertEqual(
 
2446
            [('call', 'Repository.lock_write', ('hill/', '')),
 
2447
             ('call_expecting_body', 'Repository.reconcile',
 
2448
                ('hill/', 'a token'))],
 
2449
            client._calls)
 
2450
        self.assertEqual(2, reconciler.garbage_inventories)
 
2451
        self.assertEqual(3, reconciler.inconsistent_parents)
 
2452
 
 
2453
 
 
2454
class TestRepositoryGetRevisionSignatureText(TestRemoteRepository):
 
2455
 
 
2456
    def test_text(self):
 
2457
        # ('ok',), body with signature text
 
2458
        transport_path = 'quack'
 
2459
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2460
        client.add_success_response_with_body(
 
2461
            'THETEXT', 'ok')
 
2462
        self.assertEqual("THETEXT", repo.get_signature_text("revid"))
 
2463
        self.assertEqual(
 
2464
            [('call_expecting_body', 'Repository.get_revision_signature_text',
 
2465
             ('quack/', 'revid'))],
 
2466
            client._calls)
 
2467
 
 
2468
    def test_no_signature(self):
 
2469
        transport_path = 'quick'
 
2470
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2471
        client.add_error_response('nosuchrevision', 'unknown')
 
2472
        self.assertRaises(errors.NoSuchRevision, repo.get_signature_text,
 
2473
                "unknown")
 
2474
        self.assertEqual(
 
2475
            [('call_expecting_body', 'Repository.get_revision_signature_text',
 
2476
              ('quick/', 'unknown'))],
 
2477
            client._calls)
 
2478
 
 
2479
 
1906
2480
class TestRepositoryGetGraph(TestRemoteRepository):
1907
2481
 
1908
2482
    def test_get_graph(self):
1913
2487
        self.assertNotEqual(graph._parents_provider, repo)
1914
2488
 
1915
2489
 
 
2490
class TestRepositoryAddSignatureText(TestRemoteRepository):
 
2491
 
 
2492
    def test_add_signature_text(self):
 
2493
        transport_path = 'quack'
 
2494
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2495
        client.add_expected_call(
 
2496
            'Repository.lock_write', ('quack/', ''),
 
2497
            'success', ('ok', 'a token'))
 
2498
        client.add_expected_call(
 
2499
            'Repository.start_write_group', ('quack/', 'a token'),
 
2500
            'success', ('ok', ('token1', )))
 
2501
        client.add_expected_call(
 
2502
            'Repository.add_signature_text', ('quack/', 'a token', 'rev1',
 
2503
                'token1'),
 
2504
            'success', ('ok', ), None)
 
2505
        repo.lock_write()
 
2506
        repo.start_write_group()
 
2507
        self.assertIs(None,
 
2508
            repo.add_signature_text("rev1", "every bloody emperor"))
 
2509
        self.assertEqual(
 
2510
            ('call_with_body_bytes_expecting_body',
 
2511
              'Repository.add_signature_text',
 
2512
                ('quack/', 'a token', 'rev1', 'token1'),
 
2513
              'every bloody emperor'),
 
2514
            client._calls[-1])
 
2515
 
 
2516
 
1916
2517
class TestRepositoryGetParentMap(TestRemoteRepository):
1917
2518
 
1918
2519
    def test_get_parent_map_caching(self):
1968
2569
        parents = repo.get_parent_map([rev_id])
1969
2570
        self.assertEqual(
1970
2571
            [('call_with_body_bytes_expecting_body',
1971
 
              'Repository.get_parent_map', ('quack/', 'include-missing:',
1972
 
              rev_id), '\n\n0'),
 
2572
              'Repository.get_parent_map',
 
2573
              ('quack/', 'include-missing:', rev_id), '\n\n0'),
1973
2574
             ('disconnect medium',),
1974
2575
             ('call_expecting_body', 'Repository.get_revision_graph',
1975
2576
              ('quack/', ''))],
2095
2696
        self.assertEqual({}, repo.get_parent_map(['non-existant']))
2096
2697
        self.assertLength(0, self.hpss_calls)
2097
2698
 
 
2699
    def test_exposes_get_cached_parent_map(self):
 
2700
        """RemoteRepository exposes get_cached_parent_map from
 
2701
        _unstacked_provider
 
2702
        """
 
2703
        r1 = u'\u0e33'.encode('utf8')
 
2704
        r2 = u'\u0dab'.encode('utf8')
 
2705
        lines = [' '.join([r2, r1]), r1]
 
2706
        encoded_body = bz2.compress('\n'.join(lines))
 
2707
 
 
2708
        transport_path = 'quack'
 
2709
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2710
        client.add_success_response_with_body(encoded_body, 'ok')
 
2711
        repo.lock_read()
 
2712
        # get_cached_parent_map should *not* trigger an RPC
 
2713
        self.assertEqual({}, repo.get_cached_parent_map([r1]))
 
2714
        self.assertEqual([], client._calls)
 
2715
        self.assertEqual({r2: (r1,)}, repo.get_parent_map([r2]))
 
2716
        self.assertEqual({r1: (NULL_REVISION,)},
 
2717
            repo.get_cached_parent_map([r1]))
 
2718
        self.assertEqual(
 
2719
            [('call_with_body_bytes_expecting_body',
 
2720
              'Repository.get_parent_map', ('quack/', 'include-missing:', r2),
 
2721
              '\n\n0')],
 
2722
            client._calls)
 
2723
        repo.unlock()
 
2724
 
2098
2725
 
2099
2726
class TestGetParentMapAllowsNew(tests.TestCaseWithTransport):
2100
2727
 
2115
2742
        self.assertEqual({'rev1': ('null:',)}, graph.get_parent_map(['rev1']))
2116
2743
 
2117
2744
 
 
2745
class TestRepositoryGetRevisions(TestRemoteRepository):
 
2746
 
 
2747
    def test_hpss_missing_revision(self):
 
2748
        transport_path = 'quack'
 
2749
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2750
        client.add_success_response_with_body(
 
2751
            '', 'ok', '10')
 
2752
        self.assertRaises(errors.NoSuchRevision, repo.get_revisions,
 
2753
            ['somerev1', 'anotherrev2'])
 
2754
        self.assertEqual(
 
2755
            [('call_with_body_bytes_expecting_body', 'Repository.iter_revisions',
 
2756
             ('quack/', ), "somerev1\nanotherrev2")],
 
2757
            client._calls)
 
2758
 
 
2759
    def test_hpss_get_single_revision(self):
 
2760
        transport_path = 'quack'
 
2761
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2762
        somerev1 = Revision("somerev1")
 
2763
        somerev1.committer = "Joe Committer <joe@example.com>"
 
2764
        somerev1.timestamp = 1321828927
 
2765
        somerev1.timezone = -60
 
2766
        somerev1.inventory_sha1 = "691b39be74c67b1212a75fcb19c433aaed903c2b"
 
2767
        somerev1.message = "Message"
 
2768
        body = zlib.compress(chk_bencode_serializer.write_revision_to_string(
 
2769
            somerev1))
 
2770
        # Split up body into two bits to make sure the zlib compression object
 
2771
        # gets data fed twice.
 
2772
        client.add_success_response_with_body(
 
2773
                [body[:10], body[10:]], 'ok', '10')
 
2774
        revs = repo.get_revisions(['somerev1'])
 
2775
        self.assertEqual(revs, [somerev1])
 
2776
        self.assertEqual(
 
2777
            [('call_with_body_bytes_expecting_body', 'Repository.iter_revisions',
 
2778
             ('quack/', ), "somerev1")],
 
2779
            client._calls)
 
2780
 
 
2781
 
2118
2782
class TestRepositoryGetRevisionGraph(TestRemoteRepository):
2119
2783
 
2120
2784
    def test_null_revision(self):
2257
2921
        self.setup_smart_server_with_call_log()
2258
2922
        tree = self.make_branch_and_memory_tree('.')
2259
2923
        tree.lock_write()
 
2924
        tree.add('')
2260
2925
        rev1 = tree.commit('First')
2261
2926
        rev2 = tree.commit('Second')
2262
2927
        tree.unlock()
2270
2935
                              call.call.method == verb])
2271
2936
 
2272
2937
 
 
2938
class TestRepositoryHasSignatureForRevisionId(TestRemoteRepository):
 
2939
 
 
2940
    def test_has_signature_for_revision_id(self):
 
2941
        # ('yes', ) for Repository.has_signature_for_revision_id -> 'True'.
 
2942
        transport_path = 'quack'
 
2943
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2944
        client.add_success_response('yes')
 
2945
        result = repo.has_signature_for_revision_id('A')
 
2946
        self.assertEqual(
 
2947
            [('call', 'Repository.has_signature_for_revision_id',
 
2948
              ('quack/', 'A'))],
 
2949
            client._calls)
 
2950
        self.assertEqual(True, result)
 
2951
 
 
2952
    def test_is_not_shared(self):
 
2953
        # ('no', ) for Repository.has_signature_for_revision_id -> 'False'.
 
2954
        transport_path = 'qwack'
 
2955
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2956
        client.add_success_response('no')
 
2957
        result = repo.has_signature_for_revision_id('A')
 
2958
        self.assertEqual(
 
2959
            [('call', 'Repository.has_signature_for_revision_id',
 
2960
              ('qwack/', 'A'))],
 
2961
            client._calls)
 
2962
        self.assertEqual(False, result)
 
2963
 
 
2964
 
 
2965
class TestRepositoryPhysicalLockStatus(TestRemoteRepository):
 
2966
 
 
2967
    def test_get_physical_lock_status_yes(self):
 
2968
        transport_path = 'qwack'
 
2969
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2970
        client.add_success_response('yes')
 
2971
        result = repo.get_physical_lock_status()
 
2972
        self.assertEqual(
 
2973
            [('call', 'Repository.get_physical_lock_status',
 
2974
              ('qwack/', ))],
 
2975
            client._calls)
 
2976
        self.assertEqual(True, result)
 
2977
 
 
2978
    def test_get_physical_lock_status_no(self):
 
2979
        transport_path = 'qwack'
 
2980
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2981
        client.add_success_response('no')
 
2982
        result = repo.get_physical_lock_status()
 
2983
        self.assertEqual(
 
2984
            [('call', 'Repository.get_physical_lock_status',
 
2985
              ('qwack/', ))],
 
2986
            client._calls)
 
2987
        self.assertEqual(False, result)
 
2988
 
 
2989
 
2273
2990
class TestRepositoryIsShared(TestRemoteRepository):
2274
2991
 
2275
2992
    def test_is_shared(self):
2295
3012
        self.assertEqual(False, result)
2296
3013
 
2297
3014
 
 
3015
class TestRepositoryMakeWorkingTrees(TestRemoteRepository):
 
3016
 
 
3017
    def test_make_working_trees(self):
 
3018
        # ('yes', ) for Repository.make_working_trees -> 'True'.
 
3019
        transport_path = 'quack'
 
3020
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3021
        client.add_success_response('yes')
 
3022
        result = repo.make_working_trees()
 
3023
        self.assertEqual(
 
3024
            [('call', 'Repository.make_working_trees', ('quack/',))],
 
3025
            client._calls)
 
3026
        self.assertEqual(True, result)
 
3027
 
 
3028
    def test_no_working_trees(self):
 
3029
        # ('no', ) for Repository.make_working_trees -> 'False'.
 
3030
        transport_path = 'qwack'
 
3031
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3032
        client.add_success_response('no')
 
3033
        result = repo.make_working_trees()
 
3034
        self.assertEqual(
 
3035
            [('call', 'Repository.make_working_trees', ('qwack/',))],
 
3036
            client._calls)
 
3037
        self.assertEqual(False, result)
 
3038
 
 
3039
 
2298
3040
class TestRepositoryLockWrite(TestRemoteRepository):
2299
3041
 
2300
3042
    def test_lock_write(self):
2301
3043
        transport_path = 'quack'
2302
3044
        repo, client = self.setup_fake_client_and_repository(transport_path)
2303
3045
        client.add_success_response('ok', 'a token')
2304
 
        result = repo.lock_write()
 
3046
        token = repo.lock_write().repository_token
2305
3047
        self.assertEqual(
2306
3048
            [('call', 'Repository.lock_write', ('quack/', ''))],
2307
3049
            client._calls)
2308
 
        self.assertEqual('a token', result)
 
3050
        self.assertEqual('a token', token)
2309
3051
 
2310
3052
    def test_lock_write_already_locked(self):
2311
3053
        transport_path = 'quack'
2326
3068
            client._calls)
2327
3069
 
2328
3070
 
 
3071
class TestRepositoryWriteGroups(TestRemoteRepository):
 
3072
 
 
3073
    def test_start_write_group(self):
 
3074
        transport_path = 'quack'
 
3075
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3076
        client.add_expected_call(
 
3077
            'Repository.lock_write', ('quack/', ''),
 
3078
            'success', ('ok', 'a token'))
 
3079
        client.add_expected_call(
 
3080
            'Repository.start_write_group', ('quack/', 'a token'),
 
3081
            'success', ('ok', ('token1', )))
 
3082
        repo.lock_write()
 
3083
        repo.start_write_group()
 
3084
 
 
3085
    def test_start_write_group_unsuspendable(self):
 
3086
        # Some repositories do not support suspending write
 
3087
        # groups. For those, fall back to the "real" repository.
 
3088
        transport_path = 'quack'
 
3089
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3090
        def stub_ensure_real():
 
3091
            client._calls.append(('_ensure_real',))
 
3092
            repo._real_repository = _StubRealPackRepository(client._calls)
 
3093
        repo._ensure_real = stub_ensure_real
 
3094
        client.add_expected_call(
 
3095
            'Repository.lock_write', ('quack/', ''),
 
3096
            'success', ('ok', 'a token'))
 
3097
        client.add_expected_call(
 
3098
            'Repository.start_write_group', ('quack/', 'a token'),
 
3099
            'error', ('UnsuspendableWriteGroup',))
 
3100
        repo.lock_write()
 
3101
        repo.start_write_group()
 
3102
        self.assertEqual(client._calls[-2:], [ 
 
3103
            ('_ensure_real',),
 
3104
            ('start_write_group',)])
 
3105
 
 
3106
    def test_commit_write_group(self):
 
3107
        transport_path = 'quack'
 
3108
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3109
        client.add_expected_call(
 
3110
            'Repository.lock_write', ('quack/', ''),
 
3111
            'success', ('ok', 'a token'))
 
3112
        client.add_expected_call(
 
3113
            'Repository.start_write_group', ('quack/', 'a token'),
 
3114
            'success', ('ok', ['token1']))
 
3115
        client.add_expected_call(
 
3116
            'Repository.commit_write_group', ('quack/', 'a token', ['token1']),
 
3117
            'success', ('ok',))
 
3118
        repo.lock_write()
 
3119
        repo.start_write_group()
 
3120
        repo.commit_write_group()
 
3121
 
 
3122
    def test_abort_write_group(self):
 
3123
        transport_path = 'quack'
 
3124
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3125
        client.add_expected_call(
 
3126
            'Repository.lock_write', ('quack/', ''),
 
3127
            'success', ('ok', 'a token'))
 
3128
        client.add_expected_call(
 
3129
            'Repository.start_write_group', ('quack/', 'a token'),
 
3130
            'success', ('ok', ['token1']))
 
3131
        client.add_expected_call(
 
3132
            'Repository.abort_write_group', ('quack/', 'a token', ['token1']),
 
3133
            'success', ('ok',))
 
3134
        repo.lock_write()
 
3135
        repo.start_write_group()
 
3136
        repo.abort_write_group(False)
 
3137
 
 
3138
    def test_suspend_write_group(self):
 
3139
        transport_path = 'quack'
 
3140
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3141
        self.assertEqual([], repo.suspend_write_group())
 
3142
 
 
3143
    def test_resume_write_group(self):
 
3144
        transport_path = 'quack'
 
3145
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3146
        client.add_expected_call(
 
3147
            'Repository.lock_write', ('quack/', ''),
 
3148
            'success', ('ok', 'a token'))
 
3149
        client.add_expected_call(
 
3150
            'Repository.check_write_group', ('quack/', 'a token', ['token1']),
 
3151
            'success', ('ok',))
 
3152
        repo.lock_write()
 
3153
        repo.resume_write_group(['token1'])
 
3154
 
 
3155
 
2329
3156
class TestRepositorySetMakeWorkingTrees(TestRemoteRepository):
2330
3157
 
2331
3158
    def test_backwards_compat(self):
2390
3217
        self.assertEqual([], client._calls)
2391
3218
 
2392
3219
 
 
3220
class TestRepositoryIterFilesBytes(TestRemoteRepository):
 
3221
    """Test Repository.iter_file_bytes."""
 
3222
 
 
3223
    def test_single(self):
 
3224
        transport_path = 'quack'
 
3225
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3226
        client.add_expected_call(
 
3227
            'Repository.iter_files_bytes', ('quack/', ),
 
3228
            'success', ('ok',), iter(["ok\x000", "\n", zlib.compress("mydata" * 10)]))
 
3229
        for (identifier, byte_stream) in repo.iter_files_bytes([("somefile",
 
3230
                "somerev", "myid")]):
 
3231
            self.assertEqual("myid", identifier)
 
3232
            self.assertEqual("".join(byte_stream), "mydata" * 10)
 
3233
 
 
3234
    def test_missing(self):
 
3235
        transport_path = 'quack'
 
3236
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3237
        client.add_expected_call(
 
3238
            'Repository.iter_files_bytes',
 
3239
                ('quack/', ),
 
3240
            'error', ('RevisionNotPresent', 'somefile', 'somerev'),
 
3241
            iter(["absent\0somefile\0somerev\n"]))
 
3242
        self.assertRaises(errors.RevisionNotPresent, list,
 
3243
                repo.iter_files_bytes(
 
3244
                [("somefile", "somerev", "myid")]))
 
3245
 
 
3246
 
2393
3247
class TestRepositoryInsertStreamBase(TestRemoteRepository):
2394
3248
    """Base class for Repository.insert_stream and .insert_stream_1.19
2395
3249
    tests.
2402
3256
        the client is finished.
2403
3257
        """
2404
3258
        sink = repo._get_sink()
2405
 
        fmt = repository.RepositoryFormat.get_default_format()
 
3259
        fmt = repository.format_registry.get_default()
2406
3260
        resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
2407
3261
        self.assertEqual([], resume_tokens)
2408
3262
        self.assertEqual(set(), missing_keys)
2417
3271
    """
2418
3272
 
2419
3273
    def setUp(self):
2420
 
        TestRemoteRepository.setUp(self)
 
3274
        super(TestRepositoryInsertStream, self).setUp()
2421
3275
        self.disable_verb('Repository.insert_stream_1.19')
2422
3276
 
2423
3277
    def test_unlocked_repo(self):
2508
3362
                return True
2509
3363
        repo._real_repository = FakeRealRepository()
2510
3364
        sink = repo._get_sink()
2511
 
        fmt = repository.RepositoryFormat.get_default_format()
 
3365
        fmt = repository.format_registry.get_default()
2512
3366
        stream = self.make_stream_with_inv_deltas(fmt)
2513
3367
        resume_tokens, missing_keys = sink.insert_stream(stream, fmt, [])
2514
3368
        # Every record from the first inventory delta should have been sent to
2670
3524
        self.calls = calls
2671
3525
        self._pack_collection = _StubPackCollection(calls)
2672
3526
 
 
3527
    def start_write_group(self):
 
3528
        self.calls.append(('start_write_group',))
 
3529
 
2673
3530
    def is_in_write_group(self):
2674
3531
        return False
2675
3532
 
2734
3591
             ('pack collection autopack',)],
2735
3592
            client._calls)
2736
3593
 
 
3594
    def test_oom_error_reporting(self):
 
3595
        """An out-of-memory condition on the server is reported clearly"""
 
3596
        transport_path = 'quack'
 
3597
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3598
        client.add_expected_call(
 
3599
            'PackRepository.autopack', ('quack/',),
 
3600
            'error', ('MemoryError',))
 
3601
        err = self.assertRaises(errors.BzrError, repo.autopack)
 
3602
        self.assertContainsRe(str(err), "^remote server out of mem")
 
3603
 
2737
3604
 
2738
3605
class TestErrorTranslationBase(tests.TestCaseWithMemoryTransport):
2739
 
    """Base class for unit tests for bzrlib.remote._translate_error."""
 
3606
    """Base class for unit tests for breezy.remote._translate_error."""
2740
3607
 
2741
3608
    def translateTuple(self, error_tuple, **context):
2742
3609
        """Call _translate_error with an ErrorFromSmartServer built from the
2762
3629
        """
2763
3630
        try:
2764
3631
            raise error_object
2765
 
        except errors.ErrorFromSmartServer, server_error:
 
3632
        except errors.ErrorFromSmartServer as server_error:
2766
3633
            translated_error = self.assertRaises(
2767
3634
                errors.BzrError, remote._translate_error, server_error,
2768
3635
                **context)
2770
3637
 
2771
3638
 
2772
3639
class TestErrorTranslationSuccess(TestErrorTranslationBase):
2773
 
    """Unit tests for bzrlib.remote._translate_error.
 
3640
    """Unit tests for breezy.remote._translate_error.
2774
3641
 
2775
3642
    Given an ErrorFromSmartServer (which has an error tuple from a smart
2776
3643
    server) and some context, _translate_error raises more specific errors from
2777
 
    bzrlib.errors.
 
3644
    breezy.errors.
2778
3645
 
2779
3646
    This test case covers the cases where _translate_error succeeds in
2780
3647
    translating an ErrorFromSmartServer to something better.  See
2812
3679
            detail='extra detail')
2813
3680
        self.assertEqual(expected_error, translated_error)
2814
3681
 
 
3682
    def test_norepository(self):
 
3683
        bzrdir = self.make_bzrdir('')
 
3684
        translated_error = self.translateTuple(('norepository',),
 
3685
            bzrdir=bzrdir)
 
3686
        expected_error = errors.NoRepositoryPresent(bzrdir)
 
3687
        self.assertEqual(expected_error, translated_error)
 
3688
 
2815
3689
    def test_LockContention(self):
2816
3690
        translated_error = self.translateTuple(('LockContention',))
2817
3691
        expected_error = errors.LockContention('(remote lock)')
2845
3719
        expected_error = errors.DivergedBranches(branch, other_branch)
2846
3720
        self.assertEqual(expected_error, translated_error)
2847
3721
 
 
3722
    def test_NotStacked(self):
 
3723
        branch = self.make_branch('')
 
3724
        translated_error = self.translateTuple(('NotStacked',), branch=branch)
 
3725
        expected_error = errors.NotStacked(branch)
 
3726
        self.assertEqual(expected_error, translated_error)
 
3727
 
2848
3728
    def test_ReadError_no_args(self):
2849
3729
        path = 'a path'
2850
3730
        translated_error = self.translateTuple(('ReadError',), path=path)
2866
3746
 
2867
3747
    def test_PermissionDenied_no_args(self):
2868
3748
        path = 'a path'
2869
 
        translated_error = self.translateTuple(('PermissionDenied',), path=path)
 
3749
        translated_error = self.translateTuple(('PermissionDenied',),
 
3750
            path=path)
2870
3751
        expected_error = errors.PermissionDenied(path)
2871
3752
        self.assertEqual(expected_error, translated_error)
2872
3753
 
2895
3776
        expected_error = errors.PermissionDenied(path, extra)
2896
3777
        self.assertEqual(expected_error, translated_error)
2897
3778
 
 
3779
    # GZ 2011-03-02: TODO test for PermissionDenied with non-ascii 'extra'
 
3780
 
 
3781
    def test_NoSuchFile_context_path(self):
 
3782
        local_path = "local path"
 
3783
        translated_error = self.translateTuple(('ReadError', "remote path"),
 
3784
            path=local_path)
 
3785
        expected_error = errors.ReadError(local_path)
 
3786
        self.assertEqual(expected_error, translated_error)
 
3787
 
 
3788
    def test_NoSuchFile_without_context(self):
 
3789
        remote_path = "remote path"
 
3790
        translated_error = self.translateTuple(('ReadError', remote_path))
 
3791
        expected_error = errors.ReadError(remote_path)
 
3792
        self.assertEqual(expected_error, translated_error)
 
3793
 
 
3794
    def test_ReadOnlyError(self):
 
3795
        translated_error = self.translateTuple(('ReadOnlyError',))
 
3796
        expected_error = errors.TransportNotPossible("readonly transport")
 
3797
        self.assertEqual(expected_error, translated_error)
 
3798
 
 
3799
    def test_MemoryError(self):
 
3800
        translated_error = self.translateTuple(('MemoryError',))
 
3801
        self.assertStartsWith(str(translated_error),
 
3802
            "remote server out of memory")
 
3803
 
 
3804
    def test_generic_IndexError_no_classname(self):
 
3805
        err = errors.ErrorFromSmartServer(('error', "list index out of range"))
 
3806
        translated_error = self.translateErrorFromSmartServer(err)
 
3807
        expected_error = errors.UnknownErrorFromSmartServer(err)
 
3808
        self.assertEqual(expected_error, translated_error)
 
3809
 
 
3810
    # GZ 2011-03-02: TODO test generic non-ascii error string
 
3811
 
 
3812
    def test_generic_KeyError(self):
 
3813
        err = errors.ErrorFromSmartServer(('error', 'KeyError', "1"))
 
3814
        translated_error = self.translateErrorFromSmartServer(err)
 
3815
        expected_error = errors.UnknownErrorFromSmartServer(err)
 
3816
        self.assertEqual(expected_error, translated_error)
 
3817
 
2898
3818
 
2899
3819
class TestErrorTranslationRobustness(TestErrorTranslationBase):
2900
 
    """Unit tests for bzrlib.remote._translate_error's robustness.
 
3820
    """Unit tests for breezy.remote._translate_error's robustness.
2901
3821
 
2902
3822
    TestErrorTranslationSuccess is for cases where _translate_error can
2903
3823
    translate successfully.  This class about how _translate_err behaves when
3036
3956
        :result: The revision ids in the stream, in the order seen,
3037
3957
            the topological order of revisions in the source.
3038
3958
        """
3039
 
        unordered_format = bzrdir.format_registry.get(format)()
 
3959
        unordered_format = controldir.format_registry.get(format)()
3040
3960
        target_repository_format = unordered_format.repository_format
3041
3961
        # Cross check
3042
3962
        self.assertEqual(order, target_repository_format._fetch_order)
3045
3965
        _, stacked = branch_factory()
3046
3966
        source = stacked.repository._get_source(target_repository_format)
3047
3967
        tip = stacked.last_revision()
3048
 
        revs = stacked.repository.get_ancestry(tip)
3049
 
        search = graph.PendingAncestryResult([tip], stacked.repository)
 
3968
        stacked.repository._ensure_real()
 
3969
        graph = stacked.repository.get_graph()
 
3970
        revs = [r for (r,ps) in graph.iter_ancestry([tip])
 
3971
                if r != NULL_REVISION]
 
3972
        revs.reverse()
 
3973
        search = vf_search.PendingAncestryResult([tip], stacked.repository)
3050
3974
        self.reset_smart_call_log()
3051
3975
        stream = source.get_stream(search)
3052
 
        if None in revs:
3053
 
            revs.remove(None)
3054
3976
        # We trust that if a revision is in the stream the rest of the new
3055
3977
        # content for it is too, as per our main fetch tests; here we are
3056
3978
        # checking that the revisions are actually included at all, and their
3095
4017
        self.assertEqual(expected_revs, rev_ord)
3096
4018
        # Getting topological sort requires VFS calls still - one of which is
3097
4019
        # pushing up from the bound branch.
3098
 
        self.assertLength(13, self.hpss_calls)
 
4020
        self.assertLength(14, self.hpss_calls)
3099
4021
 
3100
4022
    def test_stacked_get_stream_groupcompress(self):
3101
4023
        # Repository._get_source.get_stream() from a stacked repository with
3142
4064
 
3143
4065
    def test_copy_content_into_avoids_revision_history(self):
3144
4066
        local = self.make_branch('local')
3145
 
        remote_backing_tree = self.make_branch_and_tree('remote')
3146
 
        remote_backing_tree.commit("Commit.")
 
4067
        builder = self.make_branch_builder('remote')
 
4068
        builder.build_commit(message="Commit.")
3147
4069
        remote_branch_url = self.smart_server.get_url() + 'remote'
3148
4070
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
3149
4071
        local.repository.fetch(remote_branch.repository)
3150
4072
        self.hpss_calls = []
3151
4073
        remote_branch.copy_content_into(local)
3152
4074
        self.assertFalse('Branch.revision_history' in self.hpss_calls)
 
4075
 
 
4076
    def test_fetch_everything_needs_just_one_call(self):
 
4077
        local = self.make_branch('local')
 
4078
        builder = self.make_branch_builder('remote')
 
4079
        builder.build_commit(message="Commit.")
 
4080
        remote_branch_url = self.smart_server.get_url() + 'remote'
 
4081
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
 
4082
        self.hpss_calls = []
 
4083
        local.repository.fetch(
 
4084
            remote_branch.repository,
 
4085
            fetch_spec=vf_search.EverythingResult(remote_branch.repository))
 
4086
        self.assertEqual(['Repository.get_stream_1.19'], self.hpss_calls)
 
4087
 
 
4088
    def override_verb(self, verb_name, verb):
 
4089
        request_handlers = request.request_handlers
 
4090
        orig_verb = request_handlers.get(verb_name)
 
4091
        orig_info = request_handlers.get_info(verb_name)
 
4092
        request_handlers.register(verb_name, verb, override_existing=True)
 
4093
        self.addCleanup(request_handlers.register, verb_name, orig_verb,
 
4094
                override_existing=True, info=orig_info)
 
4095
 
 
4096
    def test_fetch_everything_backwards_compat(self):
 
4097
        """Can fetch with EverythingResult even with pre 2.4 servers.
 
4098
        
 
4099
        Pre-2.4 do not support 'everything' searches with the
 
4100
        Repository.get_stream_1.19 verb.
 
4101
        """
 
4102
        verb_log = []
 
4103
        class OldGetStreamVerb(SmartServerRepositoryGetStream_1_19):
 
4104
            """A version of the Repository.get_stream_1.19 verb patched to
 
4105
            reject 'everything' searches the way 2.3 and earlier do.
 
4106
            """
 
4107
            def recreate_search(self, repository, search_bytes,
 
4108
                                discard_excess=False):
 
4109
                verb_log.append(search_bytes.split('\n', 1)[0])
 
4110
                if search_bytes == 'everything':
 
4111
                    return (None,
 
4112
                            request.FailedSmartServerResponse(('BadSearch',)))
 
4113
                return super(OldGetStreamVerb,
 
4114
                        self).recreate_search(repository, search_bytes,
 
4115
                            discard_excess=discard_excess)
 
4116
        self.override_verb('Repository.get_stream_1.19', OldGetStreamVerb)
 
4117
        local = self.make_branch('local')
 
4118
        builder = self.make_branch_builder('remote')
 
4119
        builder.build_commit(message="Commit.")
 
4120
        remote_branch_url = self.smart_server.get_url() + 'remote'
 
4121
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
 
4122
        self.hpss_calls = []
 
4123
        local.repository.fetch(
 
4124
            remote_branch.repository,
 
4125
            fetch_spec=vf_search.EverythingResult(remote_branch.repository))
 
4126
        # make sure the overridden verb was used
 
4127
        self.assertLength(1, verb_log)
 
4128
        # more than one HPSS call is needed, but because it's a VFS callback
 
4129
        # its hard to predict exactly how many.
 
4130
        self.assertTrue(len(self.hpss_calls) > 1)
 
4131
 
 
4132
 
 
4133
class TestUpdateBoundBranchWithModifiedBoundLocation(
 
4134
    tests.TestCaseWithTransport):
 
4135
    """Ensure correct handling of bound_location modifications.
 
4136
 
 
4137
    This is tested against a smart server as http://pad.lv/786980 was about a
 
4138
    ReadOnlyError (write attempt during a read-only transaction) which can only
 
4139
    happen in this context.
 
4140
    """
 
4141
 
 
4142
    def setUp(self):
 
4143
        super(TestUpdateBoundBranchWithModifiedBoundLocation, self).setUp()
 
4144
        self.transport_server = test_server.SmartTCPServer_for_testing
 
4145
 
 
4146
    def make_master_and_checkout(self, master_name, checkout_name):
 
4147
        # Create the master branch and its associated checkout
 
4148
        self.master = self.make_branch_and_tree(master_name)
 
4149
        self.checkout = self.master.branch.create_checkout(checkout_name)
 
4150
        # Modify the master branch so there is something to update
 
4151
        self.master.commit('add stuff')
 
4152
        self.last_revid = self.master.commit('even more stuff')
 
4153
        self.bound_location = self.checkout.branch.get_bound_location()
 
4154
 
 
4155
    def assertUpdateSucceeds(self, new_location):
 
4156
        self.checkout.branch.set_bound_location(new_location)
 
4157
        self.checkout.update()
 
4158
        self.assertEqual(self.last_revid, self.checkout.last_revision())
 
4159
 
 
4160
    def test_without_final_slash(self):
 
4161
        self.make_master_and_checkout('master', 'checkout')
 
4162
        # For unclear reasons some users have a bound_location without a final
 
4163
        # '/', simulate that by forcing such a value
 
4164
        self.assertEndsWith(self.bound_location, '/')
 
4165
        self.assertUpdateSucceeds(self.bound_location.rstrip('/'))
 
4166
 
 
4167
    def test_plus_sign(self):
 
4168
        self.make_master_and_checkout('+master', 'checkout')
 
4169
        self.assertUpdateSucceeds(self.bound_location.replace('%2B', '+', 1))
 
4170
 
 
4171
    def test_tilda(self):
 
4172
        # Embed ~ in the middle of the path just to avoid any $HOME
 
4173
        # interpretation
 
4174
        self.make_master_and_checkout('mas~ter', 'checkout')
 
4175
        self.assertUpdateSucceeds(self.bound_location.replace('%2E', '~', 1))
 
4176
 
 
4177
 
 
4178
class TestWithCustomErrorHandler(RemoteBranchTestCase):
 
4179
 
 
4180
    def test_no_context(self):
 
4181
        class OutOfCoffee(errors.BzrError):
 
4182
            """A dummy exception for testing."""
 
4183
 
 
4184
            def __init__(self, urgency):
 
4185
                self.urgency = urgency
 
4186
        remote.no_context_error_translators.register("OutOfCoffee",
 
4187
            lambda err: OutOfCoffee(err.error_args[0]))
 
4188
        transport = MemoryTransport()
 
4189
        client = FakeClient(transport.base)
 
4190
        client.add_expected_call(
 
4191
            'Branch.get_stacked_on_url', ('quack/',),
 
4192
            'error', ('NotStacked',))
 
4193
        client.add_expected_call(
 
4194
            'Branch.last_revision_info',
 
4195
            ('quack/',),
 
4196
            'error', ('OutOfCoffee', 'low'))
 
4197
        transport.mkdir('quack')
 
4198
        transport = transport.clone('quack')
 
4199
        branch = self.make_remote_branch(transport, client)
 
4200
        self.assertRaises(OutOfCoffee, branch.last_revision_info)
 
4201
        self.assertFinished(client)
 
4202
 
 
4203
    def test_with_context(self):
 
4204
        class OutOfTea(errors.BzrError):
 
4205
            def __init__(self, branch, urgency):
 
4206
                self.branch = branch
 
4207
                self.urgency = urgency
 
4208
        remote.error_translators.register("OutOfTea",
 
4209
            lambda err, find, path: OutOfTea(err.error_args[0],
 
4210
                find("branch")))
 
4211
        transport = MemoryTransport()
 
4212
        client = FakeClient(transport.base)
 
4213
        client.add_expected_call(
 
4214
            'Branch.get_stacked_on_url', ('quack/',),
 
4215
            'error', ('NotStacked',))
 
4216
        client.add_expected_call(
 
4217
            'Branch.last_revision_info',
 
4218
            ('quack/',),
 
4219
            'error', ('OutOfTea', 'low'))
 
4220
        transport.mkdir('quack')
 
4221
        transport = transport.clone('quack')
 
4222
        branch = self.make_remote_branch(transport, client)
 
4223
        self.assertRaises(OutOfTea, branch.last_revision_info)
 
4224
        self.assertFinished(client)
 
4225
 
 
4226
 
 
4227
class TestRepositoryPack(TestRemoteRepository):
 
4228
 
 
4229
    def test_pack(self):
 
4230
        transport_path = 'quack'
 
4231
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4232
        client.add_expected_call(
 
4233
            'Repository.lock_write', ('quack/', ''),
 
4234
            'success', ('ok', 'token'))
 
4235
        client.add_expected_call(
 
4236
            'Repository.pack', ('quack/', 'token', 'False'),
 
4237
            'success', ('ok',), )
 
4238
        client.add_expected_call(
 
4239
            'Repository.unlock', ('quack/', 'token'),
 
4240
            'success', ('ok', ))
 
4241
        repo.pack()
 
4242
 
 
4243
    def test_pack_with_hint(self):
 
4244
        transport_path = 'quack'
 
4245
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4246
        client.add_expected_call(
 
4247
            'Repository.lock_write', ('quack/', ''),
 
4248
            'success', ('ok', 'token'))
 
4249
        client.add_expected_call(
 
4250
            'Repository.pack', ('quack/', 'token', 'False'),
 
4251
            'success', ('ok',), )
 
4252
        client.add_expected_call(
 
4253
            'Repository.unlock', ('quack/', 'token', 'False'),
 
4254
            'success', ('ok', ))
 
4255
        repo.pack(['hinta', 'hintb'])
 
4256
 
 
4257
 
 
4258
class TestRepositoryIterInventories(TestRemoteRepository):
 
4259
    """Test Repository.iter_inventories."""
 
4260
 
 
4261
    def _serialize_inv_delta(self, old_name, new_name, delta):
 
4262
        serializer = inventory_delta.InventoryDeltaSerializer(True, False)
 
4263
        return "".join(serializer.delta_to_lines(old_name, new_name, delta))
 
4264
 
 
4265
    def test_single_empty(self):
 
4266
        transport_path = 'quack'
 
4267
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4268
        fmt = controldir.format_registry.get('2a')().repository_format
 
4269
        repo._format = fmt
 
4270
        stream = [('inventory-deltas', [
 
4271
            versionedfile.FulltextContentFactory('somerevid', None, None,
 
4272
                self._serialize_inv_delta('null:', 'somerevid', []))])]
 
4273
        client.add_expected_call(
 
4274
            'VersionedFileRepository.get_inventories', ('quack/', 'unordered'),
 
4275
            'success', ('ok', ),
 
4276
            _stream_to_byte_stream(stream, fmt))
 
4277
        ret = list(repo.iter_inventories(["somerevid"]))
 
4278
        self.assertLength(1, ret)
 
4279
        inv = ret[0]
 
4280
        self.assertEqual("somerevid", inv.revision_id)
 
4281
 
 
4282
    def test_empty(self):
 
4283
        transport_path = 'quack'
 
4284
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4285
        ret = list(repo.iter_inventories([]))
 
4286
        self.assertEqual(ret, [])
 
4287
 
 
4288
    def test_missing(self):
 
4289
        transport_path = 'quack'
 
4290
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4291
        client.add_expected_call(
 
4292
            'VersionedFileRepository.get_inventories', ('quack/', 'unordered'),
 
4293
            'success', ('ok', ), iter([]))
 
4294
        self.assertRaises(errors.NoSuchRevision, list, repo.iter_inventories(
 
4295
            ["somerevid"]))