/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-05-22 00:56:52 UTC
  • mfrom: (6621.2.26 py3_pokes)
  • Revision ID: jelmer@jelmer.uk-20170522005652-yjahcr9hwmjkno7n
Merge Python3 porting work ('py3 pokes')

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