/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 brzlib/tests/test_remote.py

  • Committer: Jelmer Vernooij
  • Date: 2017-05-21 12:41:27 UTC
  • mto: This revision was merged to the branch mainline in revision 6623.
  • Revision ID: jelmer@jelmer.uk-20170521124127-iv8etg0vwymyai6y
s/bzr/brz/ in apport config.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
These tests correspond to tests.test_smart, which exercises the server side.
24
24
"""
25
25
 
26
 
import base64
27
26
import bz2
28
 
from io import BytesIO
29
 
import tarfile
 
27
from cStringIO import StringIO
30
28
import zlib
31
29
 
32
 
from .. import (
 
30
from brzlib import (
33
31
    bencode,
34
32
    branch,
 
33
    bzrdir,
35
34
    config,
36
35
    controldir,
37
36
    errors,
 
37
    inventory,
 
38
    inventory_delta,
 
39
    remote,
38
40
    repository,
39
41
    tests,
40
42
    transport,
41
43
    treebuilder,
42
 
    )
43
 
from ..branch import Branch
44
 
from ..bzr import (
45
 
    bzrdir,
46
 
    inventory,
47
 
    inventory_delta,
48
 
    remote,
49
44
    versionedfile,
50
45
    vf_search,
51
46
    )
52
 
from ..bzr.bzrdir import (
 
47
from brzlib.branch import Branch
 
48
from brzlib.bzrdir import (
53
49
    BzrDir,
54
50
    BzrDirFormat,
55
 
    )
56
 
from ..bzr import (
57
51
    RemoteBzrProber,
58
52
    )
59
 
from ..bzr.chk_serializer import chk_bencode_serializer
60
 
from ..bzr.remote import (
 
53
from brzlib.chk_serializer import chk_bencode_serializer
 
54
from brzlib.remote import (
61
55
    RemoteBranch,
62
56
    RemoteBranchFormat,
63
57
    RemoteBzrDir,
65
59
    RemoteRepository,
66
60
    RemoteRepositoryFormat,
67
61
    )
68
 
from ..bzr import groupcompress_repo, knitpack_repo
69
 
from ..revision import (
 
62
from brzlib.repofmt import groupcompress_repo, knitpack_repo
 
63
from brzlib.revision import (
70
64
    NULL_REVISION,
71
65
    Revision,
72
66
    )
73
 
from ..bzr.smart import medium, request
74
 
from ..bzr.smart.client import _SmartClient
75
 
from ..bzr.smart.repository import (
 
67
from brzlib.smart import medium, request
 
68
from brzlib.smart.client import _SmartClient
 
69
from brzlib.smart.repository import (
76
70
    SmartServerRepositoryGetParentMap,
77
71
    SmartServerRepositoryGetStream_1_19,
78
72
    _stream_to_byte_stream,
79
73
    )
80
 
from . import (
 
74
from brzlib.symbol_versioning import deprecated_in
 
75
from brzlib.tests import (
81
76
    test_server,
82
77
    )
83
 
from .scenarios import load_tests_apply_scenarios
84
 
from ..transport.memory import MemoryTransport
85
 
from ..transport.remote import (
 
78
from brzlib.tests.scenarios import load_tests_apply_scenarios
 
79
from brzlib.transport.memory import MemoryTransport
 
80
from brzlib.transport.remote import (
86
81
    RemoteTransport,
87
82
    RemoteSSHTransport,
88
83
    RemoteTCPTransport,
96
91
 
97
92
    scenarios = [
98
93
        ('HPSS-v2',
99
 
            {'transport_server':
100
 
                test_server.SmartTCPServer_for_testing_v2_only}),
 
94
            {'transport_server': test_server.SmartTCPServer_for_testing_v2_only}),
101
95
        ('HPSS-v3',
102
96
            {'transport_server': test_server.SmartTCPServer_for_testing})]
103
97
 
 
98
 
104
99
    def setUp(self):
105
100
        super(BasicRemoteObjectTests, self).setUp()
106
101
        self.transport = self.get_transport()
129
124
    def test_find_correct_format(self):
130
125
        """Should open a RemoteBzrDir over a RemoteTransport"""
131
126
        fmt = BzrDirFormat.find_format(self.transport)
132
 
        self.assertIn(RemoteBzrProber, controldir.ControlDirFormat._probers)
 
127
        self.assertTrue(bzrdir.RemoteBzrProber
 
128
                        in controldir.ControlDirFormat._server_probers)
133
129
        self.assertIsInstance(fmt, RemoteBzrDirFormat)
134
130
 
135
131
    def test_open_detected_smart_format(self):
156
152
 
157
153
    def test_remote_repo_format_supports_external_references(self):
158
154
        t = self.transport
159
 
        bd = self.make_controldir('unstackable', format='pack-0.92')
 
155
        bd = self.make_bzrdir('unstackable', format='pack-0.92')
160
156
        r = bd.create_repository()
161
157
        self.assertFalse(r._format.supports_external_lookups)
162
 
        r = BzrDir.open_from_transport(
163
 
            t.clone('unstackable')).open_repository()
 
158
        r = BzrDir.open_from_transport(t.clone('unstackable')).open_repository()
164
159
        self.assertFalse(r._format.supports_external_lookups)
165
 
        bd = self.make_controldir('stackable', format='1.9')
 
160
        bd = self.make_bzrdir('stackable', format='1.9')
166
161
        r = bd.create_repository()
167
162
        self.assertTrue(r._format.supports_external_lookups)
168
163
        r = BzrDir.open_from_transport(t.clone('stackable')).open_repository()
196
191
 
197
192
    def read_body_bytes(self, count=-1):
198
193
        if self._body_buffer is None:
199
 
            self._body_buffer = BytesIO(self.body)
 
194
            self._body_buffer = StringIO(self.body)
200
195
        bytes = self._body_buffer.read(count)
201
196
        if self._body_buffer.tell() == len(self._body_buffer.getvalue()):
202
197
            self._fake_client.expecting_body = False
225
220
        _SmartClient.__init__(self, FakeMedium(self._calls, fake_medium_base))
226
221
 
227
222
    def add_expected_call(self, call_name, call_args, response_type,
228
 
                          response_args, response_body=None):
 
223
        response_args, response_body=None):
229
224
        if self._expected_calls is None:
230
225
            self._expected_calls = []
231
226
        self._expected_calls.append((call_name, call_args))
232
227
        self.responses.append((response_type, response_args, response_body))
233
228
 
234
229
    def add_success_response(self, *args):
235
 
        self.responses.append((b'success', args, None))
 
230
        self.responses.append(('success', args, None))
236
231
 
237
232
    def add_success_response_with_body(self, body, *args):
238
 
        self.responses.append((b'success', args, body))
 
233
        self.responses.append(('success', args, body))
239
234
        if self._expected_calls is not None:
240
235
            self._expected_calls.append(None)
241
236
 
242
237
    def add_error_response(self, *args):
243
 
        self.responses.append((b'error', args))
 
238
        self.responses.append(('error', args))
244
239
 
245
240
    def add_unknown_method_response(self, verb):
246
 
        self.responses.append((b'unknown', verb))
 
241
        self.responses.append(('unknown', verb))
247
242
 
248
243
    def finished_test(self):
249
244
        if self._expected_calls:
250
245
            raise AssertionError("%r finished but was still expecting %r"
251
 
                                 % (self, self._expected_calls[0]))
 
246
                % (self, self._expected_calls[0]))
252
247
 
253
248
    def _get_next_response(self):
254
249
        try:
255
250
            response_tuple = self.responses.pop(0)
256
 
        except IndexError:
257
 
            raise AssertionError("%r didn't expect any more calls" % (self,))
258
 
        if response_tuple[0] == b'unknown':
 
251
        except IndexError, e:
 
252
            raise AssertionError("%r didn't expect any more calls"
 
253
                % (self,))
 
254
        if response_tuple[0] == 'unknown':
259
255
            raise errors.UnknownSmartMethod(response_tuple[1])
260
 
        elif response_tuple[0] == b'error':
 
256
        elif response_tuple[0] == 'error':
261
257
            raise errors.ErrorFromSmartServer(response_tuple[1])
262
258
        return response_tuple
263
259
 
269
265
            next_call = self._expected_calls.pop(0)
270
266
        except IndexError:
271
267
            raise AssertionError("%r didn't expect any more calls "
272
 
                                 "but got %r%r"
273
 
                                 % (self, method, args,))
 
268
                "but got %r%r"
 
269
                % (self, method, args,))
274
270
        if next_call is None:
275
271
            return
276
272
        if method != next_call[0] or args != next_call[1]:
277
 
            raise AssertionError(
278
 
                "%r expected %r%r but got %r%r" %
279
 
                (self, next_call[0], next_call[1], method, args,))
 
273
            raise AssertionError("%r expected %r%r "
 
274
                "but got %r%r"
 
275
                % (self, next_call[0], next_call[1], method, args,))
280
276
 
281
277
    def call(self, method, *args):
282
278
        self._check_call(method, args)
299
295
    def call_with_body_bytes_expecting_body(self, method, args, body):
300
296
        self._check_call(method, args)
301
297
        self._calls.append(('call_with_body_bytes_expecting_body', method,
302
 
                            args, body))
 
298
            args, body))
303
299
        result = self._get_next_response()
304
300
        self.expecting_body = True
305
301
        return result[1], FakeProtocol(result[2], self)
309
305
        # that's what happens a real medium.
310
306
        stream = list(stream)
311
307
        self._check_call(args[0], args[1:])
312
 
        self._calls.append(
313
 
            ('call_with_body_stream', args[0], args[1:], stream))
 
308
        self._calls.append(('call_with_body_stream', args[0], args[1:], stream))
314
309
        result = self._get_next_response()
315
310
        # The second value returned from call_with_body_stream is supposed to
316
311
        # be a response_handler object, but so far no tests depend on that.
317
 
        response_handler = None
 
312
        response_handler = None 
318
313
        return result[1], response_handler
319
314
 
320
315
 
332
327
 
333
328
    def test_unicode_path(self):
334
329
        client = FakeClient('/')
335
 
        client.add_success_response(b'yes',)
 
330
        client.add_success_response('yes',)
336
331
        transport = RemoteTransport('bzr://localhost/', _client=client)
337
 
        filename = u'/hell\u00d8'
 
332
        filename = u'/hell\u00d8'.encode('utf8')
338
333
        result = transport.has(filename)
339
334
        self.assertEqual(
340
 
            [('call', b'has', (filename.encode('utf-8'),))],
 
335
            [('call', 'has', (filename,))],
341
336
            client._calls)
342
337
        self.assertTrue(result)
343
338
 
437
432
 
438
433
    def test_backwards_compat(self):
439
434
        self.setup_smart_server_with_call_log()
440
 
        a_dir = self.make_controldir('.')
 
435
        a_dir = self.make_bzrdir('.')
441
436
        self.reset_smart_call_log()
442
 
        verb = b'BzrDir.cloning_metadir'
 
437
        verb = 'BzrDir.cloning_metadir'
443
438
        self.disable_verb(verb)
444
 
        a_dir.cloning_metadir()
 
439
        format = a_dir.cloning_metadir()
445
440
        call_count = len([call for call in self.hpss_calls if
446
 
                          call.call.method == verb])
 
441
            call.call.method == verb])
447
442
        self.assertEqual(1, call_count)
448
443
 
449
444
    def test_branch_reference(self):
450
445
        transport = self.get_transport('quack')
451
446
        referenced = self.make_branch('referenced')
452
 
        expected = referenced.controldir.cloning_metadir()
 
447
        expected = referenced.bzrdir.cloning_metadir()
453
448
        client = FakeClient(transport.base)
454
449
        client.add_expected_call(
455
 
            b'BzrDir.cloning_metadir', (b'quack/', b'False'),
456
 
            b'error', (b'BranchReference',)),
 
450
            'BzrDir.cloning_metadir', ('quack/', 'False'),
 
451
            'error', ('BranchReference',)),
457
452
        client.add_expected_call(
458
 
            b'BzrDir.open_branchV3', (b'quack/',),
459
 
            b'success', (b'ref', self.get_url('referenced').encode('utf-8'))),
460
 
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
461
 
                                    _client=client)
462
 
        result = a_controldir.cloning_metadir()
 
453
            'BzrDir.open_branchV3', ('quack/',),
 
454
            'success', ('ref', self.get_url('referenced'))),
 
455
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
456
            _client=client)
 
457
        result = a_bzrdir.cloning_metadir()
463
458
        # We should have got a control dir matching the referenced branch.
464
459
        self.assertEqual(bzrdir.BzrDirMetaFormat1, type(result))
465
 
        self.assertEqual(expected._repository_format,
466
 
                         result._repository_format)
 
460
        self.assertEqual(expected._repository_format, result._repository_format)
467
461
        self.assertEqual(expected._branch_format, result._branch_format)
468
462
        self.assertFinished(client)
469
463
 
470
464
    def test_current_server(self):
471
465
        transport = self.get_transport('.')
472
466
        transport = transport.clone('quack')
473
 
        self.make_controldir('quack')
 
467
        self.make_bzrdir('quack')
474
468
        client = FakeClient(transport.base)
475
469
        reference_bzrdir_format = controldir.format_registry.get('default')()
476
470
        control_name = reference_bzrdir_format.network_name()
477
471
        client.add_expected_call(
478
 
            b'BzrDir.cloning_metadir', (b'quack/', b'False'),
479
 
            b'success', (control_name, b'', (b'branch', b''))),
480
 
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
481
 
                                    _client=client)
482
 
        result = a_controldir.cloning_metadir()
 
472
            'BzrDir.cloning_metadir', ('quack/', 'False'),
 
473
            'success', (control_name, '', ('branch', ''))),
 
474
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
475
            _client=client)
 
476
        result = a_bzrdir.cloning_metadir()
483
477
        # We should have got a reference control dir with default branch and
484
478
        # repository formats.
485
479
        # This pokes a little, just to be sure.
491
485
    def test_unknown(self):
492
486
        transport = self.get_transport('quack')
493
487
        referenced = self.make_branch('referenced')
494
 
        referenced.controldir.cloning_metadir()
 
488
        expected = referenced.bzrdir.cloning_metadir()
495
489
        client = FakeClient(transport.base)
496
490
        client.add_expected_call(
497
 
            b'BzrDir.cloning_metadir', (b'quack/', b'False'),
498
 
            b'success', (b'unknown', b'unknown', (b'branch', b''))),
499
 
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
500
 
                                    _client=client)
501
 
        self.assertRaises(errors.UnknownFormatError,
502
 
                          a_controldir.cloning_metadir)
 
491
            'BzrDir.cloning_metadir', ('quack/', 'False'),
 
492
            'success', ('unknown', 'unknown', ('branch', ''))),
 
493
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
494
            _client=client)
 
495
        self.assertRaises(errors.UnknownFormatError, a_bzrdir.cloning_metadir)
503
496
 
504
497
 
505
498
class TestBzrDirCheckoutMetaDir(TestRemote):
510
503
        reference_bzrdir_format = controldir.format_registry.get('default')()
511
504
        control_name = reference_bzrdir_format.network_name()
512
505
        client.add_expected_call(
513
 
            b'BzrDir.checkout_metadir', (b'quack/', ),
514
 
            b'success', (control_name, b'', b''))
 
506
            'BzrDir.checkout_metadir', ('quack/', ),
 
507
            'success', (control_name, '', ''))
515
508
        transport.mkdir('quack')
516
509
        transport = transport.clone('quack')
517
 
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
518
 
                                    _client=client)
519
 
        result = a_controldir.checkout_metadir()
 
510
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
511
            _client=client)
 
512
        result = a_bzrdir.checkout_metadir()
520
513
        # We should have got a reference control dir with default branch and
521
514
        # repository formats.
522
515
        self.assertEqual(bzrdir.BzrDirMetaFormat1, type(result))
528
521
        transport = MemoryTransport()
529
522
        client = FakeClient(transport.base)
530
523
        client.add_expected_call(
531
 
            b'BzrDir.checkout_metadir', (b'quack/',),
532
 
            b'success', (b'dontknow', b'', b''))
 
524
            'BzrDir.checkout_metadir', ('quack/',),
 
525
            'success', ('dontknow', '', ''))
533
526
        transport.mkdir('quack')
534
527
        transport = transport.clone('quack')
535
 
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
536
 
                                    _client=client)
 
528
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
529
            _client=client)
537
530
        self.assertRaises(errors.UnknownFormatError,
538
 
                          a_controldir.checkout_metadir)
 
531
            a_bzrdir.checkout_metadir)
539
532
        self.assertFinished(client)
540
533
 
541
534
 
548
541
        branch_name = reference_bzrdir_format.get_branch_format().network_name()
549
542
        client.add_success_response_with_body(
550
543
            bencode.bencode({
551
 
                b"foo": (b"branch", branch_name),
552
 
                b"": (b"branch", branch_name)}), b"success")
553
 
        client.add_success_response(
554
 
            b'ok', b'', b'no', b'no', b'no',
555
 
            reference_bzrdir_format.repository_format.network_name())
556
 
        client.add_error_response(b'NotStacked')
557
 
        client.add_success_response(
558
 
            b'ok', b'', b'no', b'no', b'no',
559
 
            reference_bzrdir_format.repository_format.network_name())
560
 
        client.add_error_response(b'NotStacked')
 
544
                "foo": ("branch", branch_name),
 
545
                "": ("branch", branch_name)}), "success")
 
546
        client.add_success_response(
 
547
            'ok', '', 'no', 'no', 'no',
 
548
                reference_bzrdir_format.repository_format.network_name())
 
549
        client.add_error_response('NotStacked')
 
550
        client.add_success_response(
 
551
            'ok', '', 'no', 'no', 'no',
 
552
                reference_bzrdir_format.repository_format.network_name())
 
553
        client.add_error_response('NotStacked')
561
554
        transport.mkdir('quack')
562
555
        transport = transport.clone('quack')
563
 
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
564
 
                                    _client=client)
565
 
        result = a_controldir.get_branches()
566
 
        self.assertEqual({"", "foo"}, set(result.keys()))
 
556
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
557
            _client=client)
 
558
        result = a_bzrdir.get_branches()
 
559
        self.assertEqual(set(["", "foo"]), set(result.keys()))
567
560
        self.assertEqual(
568
 
            [('call_expecting_body', b'BzrDir.get_branches', (b'quack/',)),
569
 
             ('call', b'BzrDir.find_repositoryV3', (b'quack/', )),
570
 
             ('call', b'Branch.get_stacked_on_url', (b'quack/', )),
571
 
             ('call', b'BzrDir.find_repositoryV3', (b'quack/', )),
572
 
             ('call', b'Branch.get_stacked_on_url', (b'quack/', ))],
 
561
            [('call_expecting_body', 'BzrDir.get_branches', ('quack/',)),
 
562
             ('call', 'BzrDir.find_repositoryV3', ('quack/', )),
 
563
             ('call', 'Branch.get_stacked_on_url', ('quack/', )),
 
564
             ('call', 'BzrDir.find_repositoryV3', ('quack/', )),
 
565
             ('call', 'Branch.get_stacked_on_url', ('quack/', ))],
573
566
            client._calls)
574
567
 
575
568
 
577
570
 
578
571
    def test_destroy_default(self):
579
572
        transport = self.get_transport('quack')
580
 
        self.make_branch('referenced')
 
573
        referenced = self.make_branch('referenced')
581
574
        client = FakeClient(transport.base)
582
575
        client.add_expected_call(
583
 
            b'BzrDir.destroy_branch', (b'quack/', ),
584
 
            b'success', (b'ok',)),
585
 
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
586
 
                                    _client=client)
587
 
        a_controldir.destroy_branch()
 
576
            'BzrDir.destroy_branch', ('quack/', ),
 
577
            'success', ('ok',)),
 
578
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
579
            _client=client)
 
580
        a_bzrdir.destroy_branch()
588
581
        self.assertFinished(client)
589
582
 
590
583
 
594
587
        transport = self.get_transport('quack')
595
588
        client = FakeClient(transport.base)
596
589
        client.add_expected_call(
597
 
            b'BzrDir.has_workingtree', (b'quack/',),
598
 
            b'success', (b'yes',)),
599
 
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
600
 
                                    _client=client)
601
 
        self.assertTrue(a_controldir.has_workingtree())
 
590
            'BzrDir.has_workingtree', ('quack/',),
 
591
            'success', ('yes',)),
 
592
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
593
            _client=client)
 
594
        self.assertTrue(a_bzrdir.has_workingtree())
602
595
        self.assertFinished(client)
603
596
 
604
597
    def test_no_workingtree(self):
605
598
        transport = self.get_transport('quack')
606
599
        client = FakeClient(transport.base)
607
600
        client.add_expected_call(
608
 
            b'BzrDir.has_workingtree', (b'quack/',),
609
 
            b'success', (b'no',)),
610
 
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
611
 
                                    _client=client)
612
 
        self.assertFalse(a_controldir.has_workingtree())
 
601
            'BzrDir.has_workingtree', ('quack/',),
 
602
            'success', ('no',)),
 
603
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
604
            _client=client)
 
605
        self.assertFalse(a_bzrdir.has_workingtree())
613
606
        self.assertFinished(client)
614
607
 
615
608
 
619
612
        transport = self.get_transport('quack')
620
613
        client = FakeClient(transport.base)
621
614
        client.add_expected_call(
622
 
            b'BzrDir.destroy_repository', (b'quack/',),
623
 
            b'success', (b'ok',)),
624
 
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
625
 
                                    _client=client)
626
 
        a_controldir.destroy_repository()
 
615
            'BzrDir.destroy_repository', ('quack/',),
 
616
            'success', ('ok',)),
 
617
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
618
            _client=client)
 
619
        a_bzrdir.destroy_repository()
627
620
        self.assertFinished(client)
628
621
 
629
622
 
639
632
    def test_absent(self):
640
633
        client, transport = self.make_fake_client_and_transport()
641
634
        client.add_expected_call(
642
 
            b'BzrDir.open_2.1', (b'quack/',), b'success', (b'no',))
 
635
            'BzrDir.open_2.1', ('quack/',), 'success', ('no',))
643
636
        self.assertRaises(errors.NotBranchError, RemoteBzrDir, transport,
644
 
                          RemoteBzrDirFormat(), _client=client,
645
 
                          _force_probe=True)
 
637
                RemoteBzrDirFormat(), _client=client, _force_probe=True)
646
638
        self.assertFinished(client)
647
639
 
648
640
    def test_present_without_workingtree(self):
649
641
        client, transport = self.make_fake_client_and_transport()
650
642
        client.add_expected_call(
651
 
            b'BzrDir.open_2.1', (b'quack/',), b'success', (b'yes', b'no'))
 
643
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'no'))
652
644
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
653
 
                          _client=client, _force_probe=True)
 
645
            _client=client, _force_probe=True)
654
646
        self.assertIsInstance(bd, RemoteBzrDir)
655
647
        self.assertFalse(bd.has_workingtree())
656
648
        self.assertRaises(errors.NoWorkingTree, bd.open_workingtree)
659
651
    def test_present_with_workingtree(self):
660
652
        client, transport = self.make_fake_client_and_transport()
661
653
        client.add_expected_call(
662
 
            b'BzrDir.open_2.1', (b'quack/',), b'success', (b'yes', b'yes'))
 
654
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'yes'))
663
655
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
664
 
                          _client=client, _force_probe=True)
 
656
            _client=client, _force_probe=True)
665
657
        self.assertIsInstance(bd, RemoteBzrDir)
666
658
        self.assertTrue(bd.has_workingtree())
667
659
        self.assertRaises(errors.NotLocalUrl, bd.open_workingtree)
670
662
    def test_backwards_compat(self):
671
663
        client, transport = self.make_fake_client_and_transport()
672
664
        client.add_expected_call(
673
 
            b'BzrDir.open_2.1', (b'quack/',), b'unknown',
674
 
            (b'BzrDir.open_2.1',))
 
665
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
675
666
        client.add_expected_call(
676
 
            b'BzrDir.open', (b'quack/',), b'success', (b'yes',))
 
667
            'BzrDir.open', ('quack/',), 'success', ('yes',))
677
668
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
678
 
                          _client=client, _force_probe=True)
 
669
            _client=client, _force_probe=True)
679
670
        self.assertIsInstance(bd, RemoteBzrDir)
680
671
        self.assertFinished(client)
681
672
 
686
677
        # the version is 2 also do _remember_remote_is_before((1, 6)) before
687
678
        # continuing with the RPC.
688
679
        orig_check_call = client._check_call
689
 
 
690
680
        def check_call(method, args):
691
681
            client._medium._protocol_version = 2
692
682
            client._medium._remember_remote_is_before((1, 6))
694
684
            client._check_call(method, args)
695
685
        client._check_call = check_call
696
686
        client.add_expected_call(
697
 
            b'BzrDir.open_2.1', (b'quack/',), b'unknown',
698
 
            (b'BzrDir.open_2.1',))
 
687
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
699
688
        client.add_expected_call(
700
 
            b'BzrDir.open', (b'quack/',), b'success', (b'yes',))
 
689
            'BzrDir.open', ('quack/',), 'success', ('yes',))
701
690
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
702
 
                          _client=client, _force_probe=True)
 
691
            _client=client, _force_probe=True)
703
692
        self.assertIsInstance(bd, RemoteBzrDir)
704
693
        self.assertFinished(client)
705
694
 
711
700
        self.make_branch('.')
712
701
        a_dir = BzrDir.open(self.get_url('.'))
713
702
        self.reset_smart_call_log()
714
 
        verb = b'BzrDir.open_branchV3'
 
703
        verb = 'BzrDir.open_branchV3'
715
704
        self.disable_verb(verb)
716
 
        a_dir.open_branch()
 
705
        format = a_dir.open_branch()
717
706
        call_count = len([call for call in self.hpss_calls if
718
 
                          call.call.method == verb])
 
707
            call.call.method == verb])
719
708
        self.assertEqual(1, call_count)
720
709
 
721
710
    def test_branch_present(self):
727
716
        transport = transport.clone('quack')
728
717
        client = FakeClient(transport.base)
729
718
        client.add_expected_call(
730
 
            b'BzrDir.open_branchV3', (b'quack/',),
731
 
            b'success', (b'branch', branch_network_name))
732
 
        client.add_expected_call(
733
 
            b'BzrDir.find_repositoryV3', (b'quack/',),
734
 
            b'success', (b'ok', b'', b'no', b'no', b'no', network_name))
735
 
        client.add_expected_call(
736
 
            b'Branch.get_stacked_on_url', (b'quack/',),
737
 
            b'error', (b'NotStacked',))
 
719
            'BzrDir.open_branchV3', ('quack/',),
 
720
            'success', ('branch', branch_network_name))
 
721
        client.add_expected_call(
 
722
            'BzrDir.find_repositoryV3', ('quack/',),
 
723
            'success', ('ok', '', 'no', 'no', 'no', network_name))
 
724
        client.add_expected_call(
 
725
            'Branch.get_stacked_on_url', ('quack/',),
 
726
            'error', ('NotStacked',))
738
727
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
739
 
                              _client=client)
 
728
            _client=client)
740
729
        result = bzrdir.open_branch()
741
730
        self.assertIsInstance(result, RemoteBranch)
742
 
        self.assertEqual(bzrdir, result.controldir)
 
731
        self.assertEqual(bzrdir, result.bzrdir)
743
732
        self.assertFinished(client)
744
733
 
745
734
    def test_branch_missing(self):
747
736
        transport.mkdir('quack')
748
737
        transport = transport.clone('quack')
749
738
        client = FakeClient(transport.base)
750
 
        client.add_error_response(b'nobranch')
 
739
        client.add_error_response('nobranch')
751
740
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
752
 
                              _client=client)
 
741
            _client=client)
753
742
        self.assertRaises(errors.NotBranchError, bzrdir.open_branch)
754
743
        self.assertEqual(
755
 
            [('call', b'BzrDir.open_branchV3', (b'quack/',))],
 
744
            [('call', 'BzrDir.open_branchV3', ('quack/',))],
756
745
            client._calls)
757
746
 
758
747
    def test__get_tree_branch(self):
759
748
        # _get_tree_branch is a form of open_branch, but it should only ask for
760
749
        # branch opening, not any other network requests.
761
750
        calls = []
762
 
 
763
751
        def open_branch(name=None, possible_transports=None):
764
752
            calls.append("Called")
765
753
            return "a-branch"
767
755
        # no requests on the network - catches other api calls being made.
768
756
        client = FakeClient(transport.base)
769
757
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
770
 
                              _client=client)
 
758
            _client=client)
771
759
        # patch the open_branch call to record that it was called.
772
760
        bzrdir.open_branch = open_branch
773
761
        self.assertEqual((None, "a-branch"), bzrdir._get_tree_branch())
783
771
        network_name = reference_format.network_name()
784
772
        branch_network_name = self.get_branch_format().network_name()
785
773
        client.add_expected_call(
786
 
            b'BzrDir.open_branchV3', (b'~hello/',),
787
 
            b'success', (b'branch', branch_network_name))
788
 
        client.add_expected_call(
789
 
            b'BzrDir.find_repositoryV3', (b'~hello/',),
790
 
            b'success', (b'ok', b'', b'no', b'no', b'no', network_name))
791
 
        client.add_expected_call(
792
 
            b'Branch.get_stacked_on_url', (b'~hello/',),
793
 
            b'error', (b'NotStacked',))
 
774
            'BzrDir.open_branchV3', ('~hello/',),
 
775
            'success', ('branch', branch_network_name))
 
776
        client.add_expected_call(
 
777
            'BzrDir.find_repositoryV3', ('~hello/',),
 
778
            'success', ('ok', '', 'no', 'no', 'no', network_name))
 
779
        client.add_expected_call(
 
780
            'Branch.get_stacked_on_url', ('~hello/',),
 
781
            'error', ('NotStacked',))
794
782
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
795
 
                              _client=client)
796
 
        bzrdir.open_branch()
 
783
            _client=client)
 
784
        result = bzrdir.open_branch()
797
785
        self.assertFinished(client)
798
786
 
799
 
    def check_open_repository(self, rich_root, subtrees,
800
 
                              external_lookup=b'no'):
 
787
    def check_open_repository(self, rich_root, subtrees, external_lookup='no'):
801
788
        reference_format = self.get_repo_format()
802
789
        network_name = reference_format.network_name()
803
790
        transport = MemoryTransport()
804
791
        transport.mkdir('quack')
805
792
        transport = transport.clone('quack')
806
793
        if rich_root:
807
 
            rich_response = b'yes'
 
794
            rich_response = 'yes'
808
795
        else:
809
 
            rich_response = b'no'
 
796
            rich_response = 'no'
810
797
        if subtrees:
811
 
            subtree_response = b'yes'
 
798
            subtree_response = 'yes'
812
799
        else:
813
 
            subtree_response = b'no'
 
800
            subtree_response = 'no'
814
801
        client = FakeClient(transport.base)
815
802
        client.add_success_response(
816
 
            b'ok', b'', rich_response, subtree_response, external_lookup,
 
803
            'ok', '', rich_response, subtree_response, external_lookup,
817
804
            network_name)
818
805
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
819
 
                              _client=client)
 
806
            _client=client)
820
807
        result = bzrdir.open_repository()
821
808
        self.assertEqual(
822
 
            [('call', b'BzrDir.find_repositoryV3', (b'quack/',))],
 
809
            [('call', 'BzrDir.find_repositoryV3', ('quack/',))],
823
810
            client._calls)
824
811
        self.assertIsInstance(result, RemoteRepository)
825
 
        self.assertEqual(bzrdir, result.controldir)
 
812
        self.assertEqual(bzrdir, result.bzrdir)
826
813
        self.assertEqual(rich_root, result._format.rich_root_data)
827
814
        self.assertEqual(subtrees, result._format.supports_tree_reference)
828
815
 
831
818
        self.check_open_repository(False, True)
832
819
        self.check_open_repository(True, False)
833
820
        self.check_open_repository(False, False)
834
 
        self.check_open_repository(False, False, b'yes')
 
821
        self.check_open_repository(False, False, 'yes')
835
822
 
836
823
    def test_old_server(self):
837
824
        """RemoteBzrDirFormat should fail to probe if the server version is too
838
825
        old.
839
826
        """
840
 
        self.assertRaises(
841
 
            errors.NotBranchError,
 
827
        self.assertRaises(errors.NotBranchError,
842
828
            RemoteBzrProber.probe_transport, OldServerTransport())
843
829
 
844
830
 
848
834
        self.setup_smart_server_with_call_log()
849
835
        repo = self.make_repository('.')
850
836
        self.reset_smart_call_log()
851
 
        self.disable_verb(b'BzrDir.create_branch')
852
 
        repo.controldir.create_branch()
853
 
        create_branch_call_count = len(
854
 
            [call for call in self.hpss_calls
855
 
             if call.call.method == b'BzrDir.create_branch'])
 
837
        self.disable_verb('BzrDir.create_branch')
 
838
        branch = repo.bzrdir.create_branch()
 
839
        create_branch_call_count = len([call for call in self.hpss_calls if
 
840
            call.call.method == 'BzrDir.create_branch'])
856
841
        self.assertEqual(1, create_branch_call_count)
857
842
 
858
843
    def test_current_server(self):
866
851
        reference_repo_fmt = reference_bzrdir_format.repository_format
867
852
        reference_repo_name = reference_repo_fmt.network_name()
868
853
        client.add_expected_call(
869
 
            b'BzrDir.create_branch', (b'quack/', network_name),
870
 
            b'success', (b'ok', network_name, b'', b'no', b'no', b'yes',
871
 
                         reference_repo_name))
872
 
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
873
 
                                    _client=client)
874
 
        branch = a_controldir.create_branch()
 
854
            'BzrDir.create_branch', ('quack/', network_name),
 
855
            'success', ('ok', network_name, '', 'no', 'no', 'yes',
 
856
            reference_repo_name))
 
857
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
858
            _client=client)
 
859
        branch = a_bzrdir.create_branch()
875
860
        # We should have got a remote branch
876
861
        self.assertIsInstance(branch, remote.RemoteBranch)
877
862
        # its format should have the settings from the response
894
879
        reference_repo_fmt = reference_bzrdir_format.repository_format
895
880
        reference_repo_name = reference_repo_fmt.network_name()
896
881
        client.add_expected_call(
897
 
            b'BzrDir.create_branch', (b'extra/quack/', network_name),
898
 
            b'success', (b'ok', network_name, b'', b'no', b'no', b'yes',
899
 
                         reference_repo_name))
900
 
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
901
 
                                    _client=client)
902
 
        branch = a_controldir.create_branch(repository=repo)
 
882
            'BzrDir.create_branch', ('extra/quack/', network_name),
 
883
            'success', ('ok', network_name, '', 'no', 'no', 'yes',
 
884
            reference_repo_name))
 
885
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
886
            _client=client)
 
887
        branch = a_bzrdir.create_branch(repository=repo)
903
888
        # We should have got a remote branch
904
889
        self.assertIsInstance(branch, remote.RemoteBranch)
905
890
        # its format should have the settings from the response
911
896
 
912
897
    def test_backwards_compat(self):
913
898
        self.setup_smart_server_with_call_log()
914
 
        bzrdir = self.make_controldir('.')
 
899
        bzrdir = self.make_bzrdir('.')
915
900
        self.reset_smart_call_log()
916
 
        self.disable_verb(b'BzrDir.create_repository')
917
 
        bzrdir.create_repository()
 
901
        self.disable_verb('BzrDir.create_repository')
 
902
        repo = bzrdir.create_repository()
918
903
        create_repo_call_count = len([call for call in self.hpss_calls if
919
 
                                      call.call.method == b'BzrDir.create_repository'])
 
904
            call.call.method == 'BzrDir.create_repository'])
920
905
        self.assertEqual(1, create_repo_call_count)
921
906
 
922
907
    def test_current_server(self):
923
908
        transport = self.get_transport('.')
924
909
        transport = transport.clone('quack')
925
 
        self.make_controldir('quack')
 
910
        self.make_bzrdir('quack')
926
911
        client = FakeClient(transport.base)
927
912
        reference_bzrdir_format = controldir.format_registry.get('default')()
928
913
        reference_format = reference_bzrdir_format.repository_format
929
914
        network_name = reference_format.network_name()
930
915
        client.add_expected_call(
931
 
            b'BzrDir.create_repository', (b'quack/',
932
 
                                          b'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
933
 
                                          b'False'),
934
 
            b'success', (b'ok', b'yes', b'yes', b'yes', network_name))
935
 
        a_controldir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
936
 
                                    _client=client)
937
 
        repo = a_controldir.create_repository()
 
916
            'BzrDir.create_repository', ('quack/',
 
917
                'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
 
918
                'False'),
 
919
            'success', ('ok', 'yes', 'yes', 'yes', network_name))
 
920
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
921
            _client=client)
 
922
        repo = a_bzrdir.create_repository()
938
923
        # We should have got a remote repository
939
924
        self.assertIsInstance(repo, remote.RemoteRepository)
940
925
        # its format should have the settings from the response
954
939
        server_url = 'bzr://example.com/'
955
940
        self.permit_url(server_url)
956
941
        client = FakeClient(server_url)
957
 
        client.add_unknown_method_response(b'BzrDir.find_repositoryV3')
958
 
        client.add_unknown_method_response(b'BzrDir.find_repositoryV2')
959
 
        client.add_success_response(b'ok', b'', b'no', b'no')
 
942
        client.add_unknown_method_response('BzrDir.find_repositoryV3')
 
943
        client.add_unknown_method_response('BzrDir.find_repositoryV2')
 
944
        client.add_success_response('ok', '', 'no', 'no')
960
945
        # A real repository instance will be created to determine the network
961
946
        # name.
962
947
        client.add_success_response_with_body(
963
 
            b"Bazaar-NG meta directory, format 1\n", b'ok')
964
 
        client.add_success_response(b'stat', b'0', b'65535')
 
948
            "Bazaar-NG meta directory, format 1\n", 'ok')
 
949
        client.add_success_response('stat', '0', '65535')
965
950
        client.add_success_response_with_body(
966
 
            reference_format.get_format_string(), b'ok')
 
951
            reference_format.get_format_string(), 'ok')
967
952
        # PackRepository wants to do a stat
968
 
        client.add_success_response(b'stat', b'0', b'65535')
 
953
        client.add_success_response('stat', '0', '65535')
969
954
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
970
 
                                           _client=client)
 
955
            _client=client)
971
956
        bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
972
 
                              _client=client)
 
957
            _client=client)
973
958
        repo = bzrdir.open_repository()
974
959
        self.assertEqual(
975
 
            [('call', b'BzrDir.find_repositoryV3', (b'quack/',)),
976
 
             ('call', b'BzrDir.find_repositoryV2', (b'quack/',)),
977
 
             ('call', b'BzrDir.find_repository', (b'quack/',)),
978
 
             ('call_expecting_body', b'get', (b'/quack/.bzr/branch-format',)),
979
 
             ('call', b'stat', (b'/quack/.bzr',)),
980
 
             ('call_expecting_body', b'get', (b'/quack/.bzr/repository/format',)),
981
 
             ('call', b'stat', (b'/quack/.bzr/repository',)),
 
960
            [('call', 'BzrDir.find_repositoryV3', ('quack/',)),
 
961
             ('call', 'BzrDir.find_repositoryV2', ('quack/',)),
 
962
             ('call', 'BzrDir.find_repository', ('quack/',)),
 
963
             ('call_expecting_body', 'get', ('/quack/.bzr/branch-format',)),
 
964
             ('call', 'stat', ('/quack/.bzr',)),
 
965
             ('call_expecting_body', 'get', ('/quack/.bzr/repository/format',)),
 
966
             ('call', 'stat', ('/quack/.bzr/repository',)),
982
967
             ],
983
968
            client._calls)
984
969
        self.assertEqual(network_name, repo._format.network_name())
990
975
        server_url = 'bzr://example.com/'
991
976
        self.permit_url(server_url)
992
977
        client = FakeClient(server_url)
993
 
        client.add_unknown_method_response(b'BzrDir.find_repositoryV3')
994
 
        client.add_success_response(b'ok', b'', b'no', b'no', b'no')
 
978
        client.add_unknown_method_response('BzrDir.find_repositoryV3')
 
979
        client.add_success_response('ok', '', 'no', 'no', 'no')
995
980
        # A real repository instance will be created to determine the network
996
981
        # name.
997
982
        client.add_success_response_with_body(
998
 
            b"Bazaar-NG meta directory, format 1\n", b'ok')
999
 
        client.add_success_response(b'stat', b'0', b'65535')
 
983
            "Bazaar-NG meta directory, format 1\n", 'ok')
 
984
        client.add_success_response('stat', '0', '65535')
1000
985
        client.add_success_response_with_body(
1001
 
            reference_format.get_format_string(), b'ok')
 
986
            reference_format.get_format_string(), 'ok')
1002
987
        # PackRepository wants to do a stat
1003
 
        client.add_success_response(b'stat', b'0', b'65535')
 
988
        client.add_success_response('stat', '0', '65535')
1004
989
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
1005
 
                                           _client=client)
 
990
            _client=client)
1006
991
        bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
1007
 
                              _client=client)
 
992
            _client=client)
1008
993
        repo = bzrdir.open_repository()
1009
994
        self.assertEqual(
1010
 
            [('call', b'BzrDir.find_repositoryV3', (b'quack/',)),
1011
 
             ('call', b'BzrDir.find_repositoryV2', (b'quack/',)),
1012
 
             ('call_expecting_body', b'get', (b'/quack/.bzr/branch-format',)),
1013
 
             ('call', b'stat', (b'/quack/.bzr',)),
1014
 
             ('call_expecting_body', b'get',
1015
 
                 (b'/quack/.bzr/repository/format',)),
1016
 
             ('call', b'stat', (b'/quack/.bzr/repository',)),
 
995
            [('call', 'BzrDir.find_repositoryV3', ('quack/',)),
 
996
             ('call', 'BzrDir.find_repositoryV2', ('quack/',)),
 
997
             ('call_expecting_body', 'get', ('/quack/.bzr/branch-format',)),
 
998
             ('call', 'stat', ('/quack/.bzr',)),
 
999
             ('call_expecting_body', 'get', ('/quack/.bzr/repository/format',)),
 
1000
             ('call', 'stat', ('/quack/.bzr/repository',)),
1017
1001
             ],
1018
1002
            client._calls)
1019
1003
        self.assertEqual(network_name, repo._format.network_name())
1025
1009
        transport.mkdir('quack')
1026
1010
        transport = transport.clone('quack')
1027
1011
        client = FakeClient(transport.base)
1028
 
        client.add_success_response(
1029
 
            b'ok', b'', b'no', b'no', b'no', network_name)
 
1012
        client.add_success_response('ok', '', 'no', 'no', 'no', network_name)
1030
1013
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1031
 
                              _client=client)
 
1014
            _client=client)
1032
1015
        repo = bzrdir.open_repository()
1033
1016
        self.assertEqual(
1034
 
            [('call', b'BzrDir.find_repositoryV3', (b'quack/',))],
 
1017
            [('call', 'BzrDir.find_repositoryV3', ('quack/',))],
1035
1018
            client._calls)
1036
1019
        self.assertEqual(network_name, repo._format.network_name())
1037
1020
 
1045
1028
        transport = self.get_transport()
1046
1029
        client = FakeClient(transport.base)
1047
1030
        client.add_expected_call(
1048
 
            b'BzrDirFormat.initialize_ex_1.16',
1049
 
            (default_format_name, b'path', b'False', b'False', b'False', b'',
1050
 
             b'', b'', b'', b'False'),
1051
 
            b'success',
1052
 
            (b'.', b'no', b'no', b'yes', b'repo fmt', b'repo bzrdir fmt',
1053
 
             b'bzrdir fmt', b'False', b'', b'', b'repo lock token'))
 
1031
            'BzrDirFormat.initialize_ex_1.16',
 
1032
                (default_format_name, 'path', 'False', 'False', 'False', '',
 
1033
                 '', '', '', 'False'),
 
1034
            'success',
 
1035
                ('.', 'no', 'no', 'yes', 'repo fmt', 'repo bzrdir fmt',
 
1036
                 'bzrdir fmt', 'False', '', '', 'repo lock token'))
1054
1037
        # XXX: It would be better to call fmt.initialize_on_transport_ex, but
1055
1038
        # it's currently hard to test that without supplying a real remote
1056
1039
        # transport connected to a real server.
1057
 
        fmt._initialize_on_transport_ex_rpc(
1058
 
            client, b'path', transport, False, False, False, None, None, None,
1059
 
            None, False)
 
1040
        result = fmt._initialize_on_transport_ex_rpc(client, 'path',
 
1041
            transport, False, False, False, None, None, None, None, False)
1060
1042
        self.assertFinished(client)
1061
1043
 
1062
1044
    def test_error(self):
1068
1050
        transport = self.get_transport()
1069
1051
        client = FakeClient(transport.base)
1070
1052
        client.add_expected_call(
1071
 
            b'BzrDirFormat.initialize_ex_1.16',
1072
 
            (default_format_name, b'path', b'False', b'False', b'False', b'',
1073
 
             b'', b'', b'', b'False'),
1074
 
            b'error',
1075
 
            (b'PermissionDenied', b'path', b'extra info'))
 
1053
            'BzrDirFormat.initialize_ex_1.16',
 
1054
                (default_format_name, 'path', 'False', 'False', 'False', '',
 
1055
                 '', '', '', 'False'),
 
1056
            'error',
 
1057
                ('PermissionDenied', 'path', 'extra info'))
1076
1058
        # XXX: It would be better to call fmt.initialize_on_transport_ex, but
1077
1059
        # it's currently hard to test that without supplying a real remote
1078
1060
        # transport connected to a real server.
1079
 
        err = self.assertRaises(
1080
 
            errors.PermissionDenied,
1081
 
            fmt._initialize_on_transport_ex_rpc, client, b'path', transport,
 
1061
        err = self.assertRaises(errors.PermissionDenied,
 
1062
            fmt._initialize_on_transport_ex_rpc, client, 'path', transport,
1082
1063
            False, False, False, None, None, None, None, False)
1083
1064
        self.assertEqual('path', err.path)
1084
1065
        self.assertEqual(': extra info', err.extra)
1089
1070
        transport = self.make_smart_server('foo')
1090
1071
        transport = transport.clone('no-such-path')
1091
1072
        fmt = RemoteBzrDirFormat()
1092
 
        self.assertRaises(
1093
 
            errors.NoSuchFile, fmt.initialize_on_transport_ex, transport,
1094
 
            create_prefix=False)
 
1073
        err = self.assertRaises(errors.NoSuchFile,
 
1074
            fmt.initialize_on_transport_ex, transport, create_prefix=False)
1095
1075
 
1096
1076
 
1097
1077
class OldSmartClient(object):
1100
1080
    """
1101
1081
 
1102
1082
    def get_request(self):
1103
 
        input_file = BytesIO(b'ok\x011\n')
1104
 
        output_file = BytesIO()
 
1083
        input_file = StringIO('ok\x011\n')
 
1084
        output_file = StringIO()
1105
1085
        client_medium = medium.SmartSimplePipesClientMedium(
1106
1086
            input_file, output_file)
1107
1087
        return medium.SmartClientStreamMediumRequest(client_medium)
1127
1107
    def make_remote_bzrdir(self, transport, client):
1128
1108
        """Make a RemotebzrDir using 'client' as the _client."""
1129
1109
        return RemoteBzrDir(transport, RemoteBzrDirFormat(),
1130
 
                            _client=client)
 
1110
            _client=client)
1131
1111
 
1132
1112
 
1133
1113
class RemoteBranchTestCase(RemoteBzrDirTestCase):
1136
1116
        """Trick a RemoteBranch into thinking it is locked."""
1137
1117
        branch._lock_mode = 'w'
1138
1118
        branch._lock_count = 2
1139
 
        branch._lock_token = b'branch token'
1140
 
        branch._repo_lock_token = b'repo token'
 
1119
        branch._lock_token = 'branch token'
 
1120
        branch._repo_lock_token = 'repo token'
1141
1121
        branch.repository._lock_mode = 'w'
1142
1122
        branch.repository._lock_count = 2
1143
 
        branch.repository._lock_token = b'repo token'
 
1123
        branch.repository._lock_token = 'repo token'
1144
1124
 
1145
1125
    def make_remote_branch(self, transport, client):
1146
1126
        """Make a RemoteBranch using 'client' as its _SmartClient.
1161
1141
class TestBranchBreakLock(RemoteBranchTestCase):
1162
1142
 
1163
1143
    def test_break_lock(self):
 
1144
        transport_path = 'quack'
1164
1145
        transport = MemoryTransport()
1165
1146
        client = FakeClient(transport.base)
1166
1147
        client.add_expected_call(
1167
 
            b'Branch.get_stacked_on_url', (b'quack/',),
1168
 
            b'error', (b'NotStacked',))
 
1148
            'Branch.get_stacked_on_url', ('quack/',),
 
1149
            'error', ('NotStacked',))
1169
1150
        client.add_expected_call(
1170
 
            b'Branch.break_lock', (b'quack/',),
1171
 
            b'success', (b'ok',))
 
1151
            'Branch.break_lock', ('quack/',),
 
1152
            'success', ('ok',))
1172
1153
        transport.mkdir('quack')
1173
1154
        transport = transport.clone('quack')
1174
1155
        branch = self.make_remote_branch(transport, client)
1182
1163
        transport = MemoryTransport()
1183
1164
        client = FakeClient(transport.base)
1184
1165
        client.add_expected_call(
1185
 
            b'Branch.get_stacked_on_url', (b'quack/',),
1186
 
            b'error', (b'NotStacked',))
 
1166
            'Branch.get_stacked_on_url', ('quack/',),
 
1167
            'error', ('NotStacked',))
1187
1168
        client.add_expected_call(
1188
 
            b'Branch.get_physical_lock_status', (b'quack/',),
1189
 
            b'success', (b'yes',))
 
1169
            'Branch.get_physical_lock_status', ('quack/',),
 
1170
            'success', ('yes',))
1190
1171
        transport.mkdir('quack')
1191
1172
        transport = transport.clone('quack')
1192
1173
        branch = self.make_remote_branch(transport, client)
1198
1179
        transport = MemoryTransport()
1199
1180
        client = FakeClient(transport.base)
1200
1181
        client.add_expected_call(
1201
 
            b'Branch.get_stacked_on_url', (b'quack/',),
1202
 
            b'error', (b'NotStacked',))
 
1182
            'Branch.get_stacked_on_url', ('quack/',),
 
1183
            'error', ('NotStacked',))
1203
1184
        client.add_expected_call(
1204
 
            b'Branch.get_physical_lock_status', (b'quack/',),
1205
 
            b'success', (b'no',))
 
1185
            'Branch.get_physical_lock_status', ('quack/',),
 
1186
            'success', ('no',))
1206
1187
        transport.mkdir('quack')
1207
1188
        transport = transport.clone('quack')
1208
1189
        branch = self.make_remote_branch(transport, client)
1218
1199
        transport = MemoryTransport()
1219
1200
        client = FakeClient(transport.base)
1220
1201
        client.add_expected_call(
1221
 
            b'Branch.get_stacked_on_url', (b'quack/',),
1222
 
            b'error', (b'NotStacked',))
 
1202
            'Branch.get_stacked_on_url', ('quack/',),
 
1203
            'error', ('NotStacked',))
1223
1204
        client.add_expected_call(
1224
 
            b'Branch.get_parent', (b'quack/',),
1225
 
            b'success', (b'',))
 
1205
            'Branch.get_parent', ('quack/',),
 
1206
            'success', ('',))
1226
1207
        transport.mkdir('quack')
1227
1208
        transport = transport.clone('quack')
1228
1209
        branch = self.make_remote_branch(transport, client)
1234
1215
        transport = MemoryTransport()
1235
1216
        client = FakeClient(transport.base)
1236
1217
        client.add_expected_call(
1237
 
            b'Branch.get_stacked_on_url', (b'kwaak/',),
1238
 
            b'error', (b'NotStacked',))
 
1218
            'Branch.get_stacked_on_url', ('kwaak/',),
 
1219
            'error', ('NotStacked',))
1239
1220
        client.add_expected_call(
1240
 
            b'Branch.get_parent', (b'kwaak/',),
1241
 
            b'success', (b'../foo/',))
 
1221
            'Branch.get_parent', ('kwaak/',),
 
1222
            'success', ('../foo/',))
1242
1223
        transport.mkdir('kwaak')
1243
1224
        transport = transport.clone('kwaak')
1244
1225
        branch = self.make_remote_branch(transport, client)
1249
1230
        transport = MemoryTransport()
1250
1231
        client = FakeClient(transport.base)
1251
1232
        client.add_expected_call(
1252
 
            b'Branch.get_stacked_on_url', (b'kwaak/',),
1253
 
            b'error', (b'NotStacked',))
 
1233
            'Branch.get_stacked_on_url', ('kwaak/',),
 
1234
            'error', ('NotStacked',))
1254
1235
        client.add_expected_call(
1255
 
            b'Branch.get_parent', (b'kwaak/',),
1256
 
            b'success', (b'http://foo/',))
 
1236
            'Branch.get_parent', ('kwaak/',),
 
1237
            'success', ('http://foo/',))
1257
1238
        transport.mkdir('kwaak')
1258
1239
        transport = transport.clone('kwaak')
1259
1240
        branch = self.make_remote_branch(transport, client)
1269
1250
        transport = MemoryTransport()
1270
1251
        client = FakeClient(transport.base)
1271
1252
        client.add_expected_call(
1272
 
            b'Branch.get_stacked_on_url', (b'quack/',),
1273
 
            b'error', (b'NotStacked',))
 
1253
            'Branch.get_stacked_on_url', ('quack/',),
 
1254
            'error', ('NotStacked',))
1274
1255
        client.add_expected_call(
1275
 
            b'Branch.set_parent_location', (b'quack/', b'b', b'r', b''),
1276
 
            b'success', ())
 
1256
            'Branch.set_parent_location', ('quack/', 'b', 'r', ''),
 
1257
            'success', ())
1277
1258
        transport.mkdir('quack')
1278
1259
        transport = transport.clone('quack')
1279
1260
        branch = self.make_remote_branch(transport, client)
1280
 
        branch._lock_token = b'b'
1281
 
        branch._repo_lock_token = b'r'
 
1261
        branch._lock_token = 'b'
 
1262
        branch._repo_lock_token = 'r'
1282
1263
        branch._set_parent_location(None)
1283
1264
        self.assertFinished(client)
1284
1265
 
1286
1267
        transport = MemoryTransport()
1287
1268
        client = FakeClient(transport.base)
1288
1269
        client.add_expected_call(
1289
 
            b'Branch.get_stacked_on_url', (b'kwaak/',),
1290
 
            b'error', (b'NotStacked',))
 
1270
            'Branch.get_stacked_on_url', ('kwaak/',),
 
1271
            'error', ('NotStacked',))
1291
1272
        client.add_expected_call(
1292
 
            b'Branch.set_parent_location', (b'kwaak/', b'b', b'r', b'foo'),
1293
 
            b'success', ())
 
1273
            'Branch.set_parent_location', ('kwaak/', 'b', 'r', 'foo'),
 
1274
            'success', ())
1294
1275
        transport.mkdir('kwaak')
1295
1276
        transport = transport.clone('kwaak')
1296
1277
        branch = self.make_remote_branch(transport, client)
1297
 
        branch._lock_token = b'b'
1298
 
        branch._repo_lock_token = b'r'
 
1278
        branch._lock_token = 'b'
 
1279
        branch._repo_lock_token = 'r'
1299
1280
        branch._set_parent_location('foo')
1300
1281
        self.assertFinished(client)
1301
1282
 
1303
1284
        self.setup_smart_server_with_call_log()
1304
1285
        branch = self.make_branch('.')
1305
1286
        self.reset_smart_call_log()
1306
 
        verb = b'Branch.set_parent_location'
 
1287
        verb = 'Branch.set_parent_location'
1307
1288
        self.disable_verb(verb)
1308
1289
        branch.set_parent('http://foo/')
1309
1290
        self.assertLength(14, self.hpss_calls)
1315
1296
        self.setup_smart_server_with_call_log()
1316
1297
        branch = self.make_branch('.')
1317
1298
        self.reset_smart_call_log()
1318
 
        verb = b'Branch.get_tags_bytes'
 
1299
        verb = 'Branch.get_tags_bytes'
1319
1300
        self.disable_verb(verb)
1320
1301
        branch.tags.get_tag_dict()
1321
1302
        call_count = len([call for call in self.hpss_calls if
1322
 
                          call.call.method == verb])
 
1303
            call.call.method == verb])
1323
1304
        self.assertEqual(1, call_count)
1324
1305
 
1325
1306
    def test_trivial(self):
1326
1307
        transport = MemoryTransport()
1327
1308
        client = FakeClient(transport.base)
1328
1309
        client.add_expected_call(
1329
 
            b'Branch.get_stacked_on_url', (b'quack/',),
1330
 
            b'error', (b'NotStacked',))
 
1310
            'Branch.get_stacked_on_url', ('quack/',),
 
1311
            'error', ('NotStacked',))
1331
1312
        client.add_expected_call(
1332
 
            b'Branch.get_tags_bytes', (b'quack/',),
1333
 
            b'success', (b'',))
 
1313
            'Branch.get_tags_bytes', ('quack/',),
 
1314
            'success', ('',))
1334
1315
        transport.mkdir('quack')
1335
1316
        transport = transport.clone('quack')
1336
1317
        branch = self.make_remote_branch(transport, client)
1345
1326
        transport = MemoryTransport()
1346
1327
        client = FakeClient(transport.base)
1347
1328
        client.add_expected_call(
1348
 
            b'Branch.get_stacked_on_url', (b'quack/',),
1349
 
            b'error', (b'NotStacked',))
 
1329
            'Branch.get_stacked_on_url', ('quack/',),
 
1330
            'error', ('NotStacked',))
1350
1331
        client.add_expected_call(
1351
 
            b'Branch.set_tags_bytes', (b'quack/',
1352
 
                                       b'branch token', b'repo token'),
1353
 
            b'success', ('',))
 
1332
            'Branch.set_tags_bytes', ('quack/', 'branch token', 'repo token'),
 
1333
            'success', ('',))
1354
1334
        transport.mkdir('quack')
1355
1335
        transport = transport.clone('quack')
1356
1336
        branch = self.make_remote_branch(transport, client)
1357
1337
        self.lock_remote_branch(branch)
1358
 
        branch._set_tags_bytes(b'tags bytes')
 
1338
        branch._set_tags_bytes('tags bytes')
1359
1339
        self.assertFinished(client)
1360
 
        self.assertEqual(b'tags bytes', client._calls[-1][-1])
 
1340
        self.assertEqual('tags bytes', client._calls[-1][-1])
1361
1341
 
1362
1342
    def test_backwards_compatible(self):
1363
1343
        transport = MemoryTransport()
1364
1344
        client = FakeClient(transport.base)
1365
1345
        client.add_expected_call(
1366
 
            b'Branch.get_stacked_on_url', (b'quack/',),
1367
 
            b'error', (b'NotStacked',))
 
1346
            'Branch.get_stacked_on_url', ('quack/',),
 
1347
            'error', ('NotStacked',))
1368
1348
        client.add_expected_call(
1369
 
            b'Branch.set_tags_bytes', (b'quack/',
1370
 
                                       b'branch token', b'repo token'),
1371
 
            b'unknown', (b'Branch.set_tags_bytes',))
 
1349
            'Branch.set_tags_bytes', ('quack/', 'branch token', 'repo token'),
 
1350
            'unknown', ('Branch.set_tags_bytes',))
1372
1351
        transport.mkdir('quack')
1373
1352
        transport = transport.clone('quack')
1374
1353
        branch = self.make_remote_branch(transport, client)
1375
1354
        self.lock_remote_branch(branch)
1376
 
 
1377
1355
        class StubRealBranch(object):
1378
1356
            def __init__(self):
1379
1357
                self.calls = []
1380
 
 
1381
1358
            def _set_tags_bytes(self, bytes):
1382
1359
                self.calls.append(('set_tags_bytes', bytes))
1383
1360
        real_branch = StubRealBranch()
1384
1361
        branch._real_branch = real_branch
1385
 
        branch._set_tags_bytes(b'tags bytes')
 
1362
        branch._set_tags_bytes('tags bytes')
1386
1363
        # Call a second time, to exercise the 'remote version already inferred'
1387
1364
        # code path.
1388
 
        branch._set_tags_bytes(b'tags bytes')
 
1365
        branch._set_tags_bytes('tags bytes')
1389
1366
        self.assertFinished(client)
1390
1367
        self.assertEqual(
1391
 
            [('set_tags_bytes', b'tags bytes')] * 2, real_branch.calls)
 
1368
            [('set_tags_bytes', 'tags bytes')] * 2, real_branch.calls)
1392
1369
 
1393
1370
 
1394
1371
class TestBranchHeadsToFetch(RemoteBranchTestCase):
1397
1374
        transport = MemoryTransport()
1398
1375
        client = FakeClient(transport.base)
1399
1376
        client.add_expected_call(
1400
 
            b'Branch.get_stacked_on_url', (b'quack/',),
1401
 
            b'error', (b'NotStacked',))
1402
 
        client.add_expected_call(
1403
 
            b'Branch.last_revision_info', (b'quack/',),
1404
 
            b'success', (b'ok', b'1', b'rev-tip'))
1405
 
        client.add_expected_call(
1406
 
            b'Branch.get_config_file', (b'quack/',),
1407
 
            b'success', (b'ok',), b'')
 
1377
            'Branch.get_stacked_on_url', ('quack/',),
 
1378
            'error', ('NotStacked',))
 
1379
        client.add_expected_call(
 
1380
            'Branch.last_revision_info', ('quack/',),
 
1381
            'success', ('ok', '1', 'rev-tip'))
 
1382
        client.add_expected_call(
 
1383
            'Branch.get_config_file', ('quack/',),
 
1384
            'success', ('ok',), '')
1408
1385
        transport.mkdir('quack')
1409
1386
        transport = transport.clone('quack')
1410
1387
        branch = self.make_remote_branch(transport, client)
1411
1388
        result = branch.heads_to_fetch()
1412
1389
        self.assertFinished(client)
1413
 
        self.assertEqual(({b'rev-tip'}, set()), result)
 
1390
        self.assertEqual((set(['rev-tip']), set()), result)
1414
1391
 
1415
1392
    def test_uses_last_revision_info_and_tags_when_set(self):
1416
1393
        transport = MemoryTransport()
1417
1394
        client = FakeClient(transport.base)
1418
1395
        client.add_expected_call(
1419
 
            b'Branch.get_stacked_on_url', (b'quack/',),
1420
 
            b'error', (b'NotStacked',))
1421
 
        client.add_expected_call(
1422
 
            b'Branch.last_revision_info', (b'quack/',),
1423
 
            b'success', (b'ok', b'1', b'rev-tip'))
1424
 
        client.add_expected_call(
1425
 
            b'Branch.get_config_file', (b'quack/',),
1426
 
            b'success', (b'ok',), b'branch.fetch_tags = True')
 
1396
            'Branch.get_stacked_on_url', ('quack/',),
 
1397
            'error', ('NotStacked',))
 
1398
        client.add_expected_call(
 
1399
            'Branch.last_revision_info', ('quack/',),
 
1400
            'success', ('ok', '1', 'rev-tip'))
 
1401
        client.add_expected_call(
 
1402
            'Branch.get_config_file', ('quack/',),
 
1403
            'success', ('ok',), 'branch.fetch_tags = True')
1427
1404
        # XXX: this will break if the default format's serialization of tags
1428
1405
        # changes, or if the RPC for fetching tags changes from get_tags_bytes.
1429
1406
        client.add_expected_call(
1430
 
            b'Branch.get_tags_bytes', (b'quack/',),
1431
 
            b'success', (b'd5:tag-17:rev-foo5:tag-27:rev-bare',))
 
1407
            'Branch.get_tags_bytes', ('quack/',),
 
1408
            'success', ('d5:tag-17:rev-foo5:tag-27:rev-bare',))
1432
1409
        transport.mkdir('quack')
1433
1410
        transport = transport.clone('quack')
1434
1411
        branch = self.make_remote_branch(transport, client)
1435
1412
        result = branch.heads_to_fetch()
1436
1413
        self.assertFinished(client)
1437
1414
        self.assertEqual(
1438
 
            ({b'rev-tip'}, {b'rev-foo', b'rev-bar'}), result)
 
1415
            (set(['rev-tip']), set(['rev-foo', 'rev-bar'])), result)
1439
1416
 
1440
1417
    def test_uses_rpc_for_formats_with_non_default_heads_to_fetch(self):
1441
1418
        transport = MemoryTransport()
1442
1419
        client = FakeClient(transport.base)
1443
1420
        client.add_expected_call(
1444
 
            b'Branch.get_stacked_on_url', (b'quack/',),
1445
 
            b'error', (b'NotStacked',))
 
1421
            'Branch.get_stacked_on_url', ('quack/',),
 
1422
            'error', ('NotStacked',))
1446
1423
        client.add_expected_call(
1447
 
            b'Branch.heads_to_fetch', (b'quack/',),
1448
 
            b'success', ([b'tip'], [b'tagged-1', b'tagged-2']))
 
1424
            'Branch.heads_to_fetch', ('quack/',),
 
1425
            'success', (['tip'], ['tagged-1', 'tagged-2']))
1449
1426
        transport.mkdir('quack')
1450
1427
        transport = transport.clone('quack')
1451
1428
        branch = self.make_remote_branch(transport, client)
1452
1429
        branch._format._use_default_local_heads_to_fetch = lambda: False
1453
1430
        result = branch.heads_to_fetch()
1454
1431
        self.assertFinished(client)
1455
 
        self.assertEqual(({b'tip'}, {b'tagged-1', b'tagged-2'}), result)
 
1432
        self.assertEqual((set(['tip']), set(['tagged-1', 'tagged-2'])), result)
1456
1433
 
1457
1434
    def make_branch_with_tags(self):
1458
1435
        self.setup_smart_server_with_call_log()
1459
1436
        # Make a branch with a single revision.
1460
1437
        builder = self.make_branch_builder('foo')
1461
1438
        builder.start_series()
1462
 
        builder.build_snapshot(None, [
1463
 
            ('add', ('', b'root-id', 'directory', ''))],
1464
 
            revision_id=b'tip')
 
1439
        builder.build_snapshot('tip', None, [
 
1440
            ('add', ('', 'root-id', 'directory', ''))])
1465
1441
        builder.finish_series()
1466
1442
        branch = builder.get_branch()
1467
1443
        # Add two tags to that branch
1468
 
        branch.tags.set_tag('tag-1', b'rev-1')
1469
 
        branch.tags.set_tag('tag-2', b'rev-2')
 
1444
        branch.tags.set_tag('tag-1', 'rev-1')
 
1445
        branch.tags.set_tag('tag-2', 'rev-2')
1470
1446
        return branch
1471
1447
 
1472
1448
    def test_backwards_compatible(self):
1474
1450
        br.get_config_stack().set('branch.fetch_tags', True)
1475
1451
        self.addCleanup(br.lock_read().unlock)
1476
1452
        # Disable the heads_to_fetch verb
1477
 
        verb = b'Branch.heads_to_fetch'
 
1453
        verb = 'Branch.heads_to_fetch'
1478
1454
        self.disable_verb(verb)
1479
1455
        self.reset_smart_call_log()
1480
1456
        result = br.heads_to_fetch()
1481
 
        self.assertEqual(({b'tip'}, {b'rev-1', b'rev-2'}), result)
 
1457
        self.assertEqual((set(['tip']), set(['rev-1', 'rev-2'])), result)
1482
1458
        self.assertEqual(
1483
 
            [b'Branch.last_revision_info', b'Branch.get_tags_bytes'],
 
1459
            ['Branch.last_revision_info', 'Branch.get_tags_bytes'],
1484
1460
            [call.call.method for call in self.hpss_calls])
1485
1461
 
1486
1462
    def test_backwards_compatible_no_tags(self):
1488
1464
        br.get_config_stack().set('branch.fetch_tags', False)
1489
1465
        self.addCleanup(br.lock_read().unlock)
1490
1466
        # Disable the heads_to_fetch verb
1491
 
        verb = b'Branch.heads_to_fetch'
 
1467
        verb = 'Branch.heads_to_fetch'
1492
1468
        self.disable_verb(verb)
1493
1469
        self.reset_smart_call_log()
1494
1470
        result = br.heads_to_fetch()
1495
 
        self.assertEqual(({b'tip'}, set()), result)
 
1471
        self.assertEqual((set(['tip']), set()), result)
1496
1472
        self.assertEqual(
1497
 
            [b'Branch.last_revision_info'],
 
1473
            ['Branch.last_revision_info'],
1498
1474
            [call.call.method for call in self.hpss_calls])
1499
1475
 
1500
1476
 
1505
1481
        transport = MemoryTransport()
1506
1482
        client = FakeClient(transport.base)
1507
1483
        client.add_expected_call(
1508
 
            b'Branch.get_stacked_on_url', (b'quack/',),
1509
 
            b'error', (b'NotStacked',))
 
1484
            'Branch.get_stacked_on_url', ('quack/',),
 
1485
            'error', ('NotStacked',))
1510
1486
        client.add_expected_call(
1511
 
            b'Branch.last_revision_info', (b'quack/',),
1512
 
            b'success', (b'ok', b'0', b'null:'))
 
1487
            'Branch.last_revision_info', ('quack/',),
 
1488
            'success', ('ok', '0', 'null:'))
1513
1489
        transport.mkdir('quack')
1514
1490
        transport = transport.clone('quack')
1515
1491
        branch = self.make_remote_branch(transport, client)
1523
1499
        transport = MemoryTransport()
1524
1500
        client = FakeClient(transport.base)
1525
1501
        client.add_expected_call(
1526
 
            b'Branch.get_stacked_on_url', (b'kwaak/',),
1527
 
            b'error', (b'NotStacked',))
 
1502
            'Branch.get_stacked_on_url', ('kwaak/',),
 
1503
            'error', ('NotStacked',))
1528
1504
        client.add_expected_call(
1529
 
            b'Branch.last_revision_info', (b'kwaak/',),
1530
 
            b'success', (b'ok', b'2', revid))
 
1505
            'Branch.last_revision_info', ('kwaak/',),
 
1506
            'success', ('ok', '2', revid))
1531
1507
        transport.mkdir('kwaak')
1532
1508
        transport = transport.clone('kwaak')
1533
1509
        branch = self.make_remote_branch(transport, client)
1545
1521
        # doesn't just open in - this test probably needs to be rewritten using
1546
1522
        # a spawn()ed server.
1547
1523
        stacked_branch = self.make_branch('stacked', format='1.9')
1548
 
        self.make_branch('base', format='1.9')
 
1524
        memory_branch = self.make_branch('base', format='1.9')
1549
1525
        vfs_url = self.get_vfs_only_url('base')
1550
1526
        stacked_branch.set_stacked_on_url(vfs_url)
1551
 
        transport = stacked_branch.controldir.root_transport
 
1527
        transport = stacked_branch.bzrdir.root_transport
1552
1528
        client = FakeClient(transport.base)
1553
1529
        client.add_expected_call(
1554
 
            b'Branch.get_stacked_on_url', (b'stacked/',),
1555
 
            b'success', (b'ok', vfs_url.encode('utf-8')))
 
1530
            'Branch.get_stacked_on_url', ('stacked/',),
 
1531
            'success', ('ok', vfs_url))
1556
1532
        # XXX: Multiple calls are bad, this second call documents what is
1557
1533
        # today.
1558
1534
        client.add_expected_call(
1559
 
            b'Branch.get_stacked_on_url', (b'stacked/',),
1560
 
            b'success', (b'ok', vfs_url.encode('utf-8')))
 
1535
            'Branch.get_stacked_on_url', ('stacked/',),
 
1536
            'success', ('ok', vfs_url))
1561
1537
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
1562
 
                              _client=client)
 
1538
            _client=client)
1563
1539
        repo_fmt = remote.RemoteRepositoryFormat()
1564
1540
        repo_fmt._custom_format = stacked_branch.repository._format
1565
1541
        branch = RemoteBranch(bzrdir, RemoteRepository(bzrdir, repo_fmt),
1566
 
                              _client=client)
 
1542
            _client=client)
1567
1543
        result = branch.get_stacked_on_url()
1568
1544
        self.assertEqual(vfs_url, result)
1569
1545
 
1570
1546
    def test_backwards_compatible(self):
1571
1547
        # like with bzr1.6 with no Branch.get_stacked_on_url rpc
1572
 
        self.make_branch('base', format='1.6')
 
1548
        base_branch = self.make_branch('base', format='1.6')
1573
1549
        stacked_branch = self.make_branch('stacked', format='1.6')
1574
1550
        stacked_branch.set_stacked_on_url('../base')
1575
1551
        client = FakeClient(self.get_url())
1576
1552
        branch_network_name = self.get_branch_format().network_name()
1577
1553
        client.add_expected_call(
1578
 
            b'BzrDir.open_branchV3', (b'stacked/',),
1579
 
            b'success', (b'branch', branch_network_name))
 
1554
            'BzrDir.open_branchV3', ('stacked/',),
 
1555
            'success', ('branch', branch_network_name))
1580
1556
        client.add_expected_call(
1581
 
            b'BzrDir.find_repositoryV3', (b'stacked/',),
1582
 
            b'success', (b'ok', b'', b'no', b'no', b'yes',
1583
 
                         stacked_branch.repository._format.network_name()))
 
1557
            'BzrDir.find_repositoryV3', ('stacked/',),
 
1558
            'success', ('ok', '', 'no', 'no', 'yes',
 
1559
                stacked_branch.repository._format.network_name()))
1584
1560
        # called twice, once from constructor and then again by us
1585
1561
        client.add_expected_call(
1586
 
            b'Branch.get_stacked_on_url', (b'stacked/',),
1587
 
            b'unknown', (b'Branch.get_stacked_on_url',))
 
1562
            'Branch.get_stacked_on_url', ('stacked/',),
 
1563
            'unknown', ('Branch.get_stacked_on_url',))
1588
1564
        client.add_expected_call(
1589
 
            b'Branch.get_stacked_on_url', (b'stacked/',),
1590
 
            b'unknown', (b'Branch.get_stacked_on_url',))
 
1565
            'Branch.get_stacked_on_url', ('stacked/',),
 
1566
            'unknown', ('Branch.get_stacked_on_url',))
1591
1567
        # this will also do vfs access, but that goes direct to the transport
1592
1568
        # and isn't seen by the FakeClient.
1593
1569
        bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1594
 
                              RemoteBzrDirFormat(), _client=client)
 
1570
            RemoteBzrDirFormat(), _client=client)
1595
1571
        branch = bzrdir.open_branch()
1596
1572
        result = branch.get_stacked_on_url()
1597
1573
        self.assertEqual('../base', result)
1600
1576
        # repository
1601
1577
        self.assertEqual(1, len(branch.repository._fallback_repositories))
1602
1578
        self.assertEqual(1,
1603
 
                         len(branch.repository._real_repository._fallback_repositories))
 
1579
            len(branch.repository._real_repository._fallback_repositories))
1604
1580
 
1605
1581
    def test_get_stacked_on_real_branch(self):
1606
 
        self.make_branch('base')
 
1582
        base_branch = self.make_branch('base')
1607
1583
        stacked_branch = self.make_branch('stacked')
1608
1584
        stacked_branch.set_stacked_on_url('../base')
1609
1585
        reference_format = self.get_repo_format()
1611
1587
        client = FakeClient(self.get_url())
1612
1588
        branch_network_name = self.get_branch_format().network_name()
1613
1589
        client.add_expected_call(
1614
 
            b'BzrDir.open_branchV3', (b'stacked/',),
1615
 
            b'success', (b'branch', branch_network_name))
 
1590
            'BzrDir.open_branchV3', ('stacked/',),
 
1591
            'success', ('branch', branch_network_name))
1616
1592
        client.add_expected_call(
1617
 
            b'BzrDir.find_repositoryV3', (b'stacked/',),
1618
 
            b'success', (b'ok', b'', b'yes', b'no', b'yes', network_name))
 
1593
            'BzrDir.find_repositoryV3', ('stacked/',),
 
1594
            'success', ('ok', '', 'yes', 'no', 'yes', network_name))
1619
1595
        # called twice, once from constructor and then again by us
1620
1596
        client.add_expected_call(
1621
 
            b'Branch.get_stacked_on_url', (b'stacked/',),
1622
 
            b'success', (b'ok', b'../base'))
 
1597
            'Branch.get_stacked_on_url', ('stacked/',),
 
1598
            'success', ('ok', '../base'))
1623
1599
        client.add_expected_call(
1624
 
            b'Branch.get_stacked_on_url', (b'stacked/',),
1625
 
            b'success', (b'ok', b'../base'))
 
1600
            'Branch.get_stacked_on_url', ('stacked/',),
 
1601
            'success', ('ok', '../base'))
1626
1602
        bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1627
 
                              RemoteBzrDirFormat(), _client=client)
 
1603
            RemoteBzrDirFormat(), _client=client)
1628
1604
        branch = bzrdir.open_branch()
1629
1605
        result = branch.get_stacked_on_url()
1630
1606
        self.assertEqual('../base', result)
1646
1622
 
1647
1623
        client = FakeClient(transport.base)
1648
1624
        client.add_expected_call(
1649
 
            b'Branch.get_stacked_on_url', (b'branch/',),
1650
 
            b'error', (b'NotStacked',))
1651
 
        client.add_expected_call(
1652
 
            b'Branch.lock_write', (b'branch/', b'', b''),
1653
 
            b'success', (b'ok', b'branch token', b'repo token'))
1654
 
        client.add_expected_call(
1655
 
            b'Branch.last_revision_info',
1656
 
            (b'branch/',),
1657
 
            b'success', (b'ok', b'0', b'null:'))
1658
 
        client.add_expected_call(
1659
 
            b'Branch.set_last_revision', (b'branch/',
1660
 
                                          b'branch token', b'repo token', b'null:',),
1661
 
            b'success', (b'ok',))
1662
 
        client.add_expected_call(
1663
 
            b'Branch.unlock', (b'branch/', b'branch token', b'repo token'),
1664
 
            b'success', (b'ok',))
 
1625
            'Branch.get_stacked_on_url', ('branch/',),
 
1626
            'error', ('NotStacked',))
 
1627
        client.add_expected_call(
 
1628
            'Branch.lock_write', ('branch/', '', ''),
 
1629
            'success', ('ok', 'branch token', 'repo token'))
 
1630
        client.add_expected_call(
 
1631
            'Branch.last_revision_info',
 
1632
            ('branch/',),
 
1633
            'success', ('ok', '0', 'null:'))
 
1634
        client.add_expected_call(
 
1635
            'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'null:',),
 
1636
            'success', ('ok',))
 
1637
        client.add_expected_call(
 
1638
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
 
1639
            'success', ('ok',))
1665
1640
        branch = self.make_remote_branch(transport, client)
1666
1641
        branch.lock_write()
1667
1642
        result = branch._set_last_revision(NULL_REVISION)
1678
1653
 
1679
1654
        client = FakeClient(transport.base)
1680
1655
        client.add_expected_call(
1681
 
            b'Branch.get_stacked_on_url', (b'branch/',),
1682
 
            b'error', (b'NotStacked',))
1683
 
        client.add_expected_call(
1684
 
            b'Branch.lock_write', (b'branch/', b'', b''),
1685
 
            b'success', (b'ok', b'branch token', b'repo token'))
1686
 
        client.add_expected_call(
1687
 
            b'Branch.last_revision_info',
1688
 
            (b'branch/',),
1689
 
            b'success', (b'ok', b'0', b'null:'))
1690
 
        lines = [b'rev-id2']
1691
 
        encoded_body = bz2.compress(b'\n'.join(lines))
1692
 
        client.add_success_response_with_body(encoded_body, b'ok')
1693
 
        client.add_expected_call(
1694
 
            b'Branch.set_last_revision', (b'branch/',
1695
 
                                          b'branch token', b'repo token', b'rev-id2',),
1696
 
            b'success', (b'ok',))
1697
 
        client.add_expected_call(
1698
 
            b'Branch.unlock', (b'branch/', b'branch token', b'repo token'),
1699
 
            b'success', (b'ok',))
 
1656
            'Branch.get_stacked_on_url', ('branch/',),
 
1657
            'error', ('NotStacked',))
 
1658
        client.add_expected_call(
 
1659
            'Branch.lock_write', ('branch/', '', ''),
 
1660
            'success', ('ok', 'branch token', 'repo token'))
 
1661
        client.add_expected_call(
 
1662
            'Branch.last_revision_info',
 
1663
            ('branch/',),
 
1664
            'success', ('ok', '0', 'null:'))
 
1665
        lines = ['rev-id2']
 
1666
        encoded_body = bz2.compress('\n'.join(lines))
 
1667
        client.add_success_response_with_body(encoded_body, 'ok')
 
1668
        client.add_expected_call(
 
1669
            'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'rev-id2',),
 
1670
            'success', ('ok',))
 
1671
        client.add_expected_call(
 
1672
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
 
1673
            'success', ('ok',))
1700
1674
        branch = self.make_remote_branch(transport, client)
1701
1675
        # Lock the branch, reset the record of remote calls.
1702
1676
        branch.lock_write()
1703
 
        result = branch._set_last_revision(b'rev-id2')
 
1677
        result = branch._set_last_revision('rev-id2')
1704
1678
        branch.unlock()
1705
1679
        self.assertEqual(None, result)
1706
1680
        self.assertFinished(client)
1712
1686
        # A response of 'NoSuchRevision' is translated into an exception.
1713
1687
        client = FakeClient(transport.base)
1714
1688
        client.add_expected_call(
1715
 
            b'Branch.get_stacked_on_url', (b'branch/',),
1716
 
            b'error', (b'NotStacked',))
1717
 
        client.add_expected_call(
1718
 
            b'Branch.lock_write', (b'branch/', b'', b''),
1719
 
            b'success', (b'ok', b'branch token', b'repo token'))
1720
 
        client.add_expected_call(
1721
 
            b'Branch.last_revision_info',
1722
 
            (b'branch/',),
1723
 
            b'success', (b'ok', b'0', b'null:'))
 
1689
            'Branch.get_stacked_on_url', ('branch/',),
 
1690
            'error', ('NotStacked',))
 
1691
        client.add_expected_call(
 
1692
            'Branch.lock_write', ('branch/', '', ''),
 
1693
            'success', ('ok', 'branch token', 'repo token'))
 
1694
        client.add_expected_call(
 
1695
            'Branch.last_revision_info',
 
1696
            ('branch/',),
 
1697
            'success', ('ok', '0', 'null:'))
1724
1698
        # get_graph calls to construct the revision history, for the set_rh
1725
1699
        # hook
1726
 
        lines = [b'rev-id']
1727
 
        encoded_body = bz2.compress(b'\n'.join(lines))
1728
 
        client.add_success_response_with_body(encoded_body, b'ok')
1729
 
        client.add_expected_call(
1730
 
            b'Branch.set_last_revision', (b'branch/',
1731
 
                                          b'branch token', b'repo token', b'rev-id',),
1732
 
            b'error', (b'NoSuchRevision', b'rev-id'))
1733
 
        client.add_expected_call(
1734
 
            b'Branch.unlock', (b'branch/', b'branch token', b'repo token'),
1735
 
            b'success', (b'ok',))
 
1700
        lines = ['rev-id']
 
1701
        encoded_body = bz2.compress('\n'.join(lines))
 
1702
        client.add_success_response_with_body(encoded_body, 'ok')
 
1703
        client.add_expected_call(
 
1704
            'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'rev-id',),
 
1705
            'error', ('NoSuchRevision', 'rev-id'))
 
1706
        client.add_expected_call(
 
1707
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
 
1708
            'success', ('ok',))
1736
1709
 
1737
1710
        branch = self.make_remote_branch(transport, client)
1738
1711
        branch.lock_write()
1739
1712
        self.assertRaises(
1740
 
            errors.NoSuchRevision, branch._set_last_revision, b'rev-id')
 
1713
            errors.NoSuchRevision, branch._set_last_revision, 'rev-id')
1741
1714
        branch.unlock()
1742
1715
        self.assertFinished(client)
1743
1716
 
1752
1725
        rejection_msg_unicode = u'rejection message\N{INTERROBANG}'
1753
1726
        rejection_msg_utf8 = rejection_msg_unicode.encode('utf8')
1754
1727
        client.add_expected_call(
1755
 
            b'Branch.get_stacked_on_url', (b'branch/',),
1756
 
            b'error', (b'NotStacked',))
1757
 
        client.add_expected_call(
1758
 
            b'Branch.lock_write', (b'branch/', b'', b''),
1759
 
            b'success', (b'ok', b'branch token', b'repo token'))
1760
 
        client.add_expected_call(
1761
 
            b'Branch.last_revision_info',
1762
 
            (b'branch/',),
1763
 
            b'success', (b'ok', b'0', b'null:'))
1764
 
        lines = [b'rev-id']
1765
 
        encoded_body = bz2.compress(b'\n'.join(lines))
1766
 
        client.add_success_response_with_body(encoded_body, b'ok')
1767
 
        client.add_expected_call(
1768
 
            b'Branch.set_last_revision', (b'branch/',
1769
 
                                          b'branch token', b'repo token', b'rev-id',),
1770
 
            b'error', (b'TipChangeRejected', rejection_msg_utf8))
1771
 
        client.add_expected_call(
1772
 
            b'Branch.unlock', (b'branch/', b'branch token', b'repo token'),
1773
 
            b'success', (b'ok',))
 
1728
            'Branch.get_stacked_on_url', ('branch/',),
 
1729
            'error', ('NotStacked',))
 
1730
        client.add_expected_call(
 
1731
            'Branch.lock_write', ('branch/', '', ''),
 
1732
            'success', ('ok', 'branch token', 'repo token'))
 
1733
        client.add_expected_call(
 
1734
            'Branch.last_revision_info',
 
1735
            ('branch/',),
 
1736
            'success', ('ok', '0', 'null:'))
 
1737
        lines = ['rev-id']
 
1738
        encoded_body = bz2.compress('\n'.join(lines))
 
1739
        client.add_success_response_with_body(encoded_body, 'ok')
 
1740
        client.add_expected_call(
 
1741
            'Branch.set_last_revision', ('branch/', 'branch token', 'repo token', 'rev-id',),
 
1742
            'error', ('TipChangeRejected', rejection_msg_utf8))
 
1743
        client.add_expected_call(
 
1744
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
 
1745
            'success', ('ok',))
1774
1746
        branch = self.make_remote_branch(transport, client)
1775
1747
        branch.lock_write()
1776
1748
        # The 'TipChangeRejected' error response triggered by calling
1777
1749
        # set_last_revision_info causes a TipChangeRejected exception.
1778
1750
        err = self.assertRaises(
1779
1751
            errors.TipChangeRejected,
1780
 
            branch._set_last_revision, b'rev-id')
 
1752
            branch._set_last_revision, 'rev-id')
1781
1753
        # The UTF-8 message from the response has been decoded into a unicode
1782
1754
        # object.
1783
 
        self.assertIsInstance(err.msg, str)
 
1755
        self.assertIsInstance(err.msg, unicode)
1784
1756
        self.assertEqual(rejection_msg_unicode, err.msg)
1785
1757
        branch.unlock()
1786
1758
        self.assertFinished(client)
1789
1761
class TestBranchSetLastRevisionInfo(RemoteBranchTestCase):
1790
1762
 
1791
1763
    def test_set_last_revision_info(self):
1792
 
        # set_last_revision_info(num, b'rev-id') is translated to calling
 
1764
        # set_last_revision_info(num, 'rev-id') is translated to calling
1793
1765
        # Branch.set_last_revision_info(num, 'rev-id') on the wire.
1794
1766
        transport = MemoryTransport()
1795
1767
        transport.mkdir('branch')
1796
1768
        transport = transport.clone('branch')
1797
1769
        client = FakeClient(transport.base)
1798
1770
        # get_stacked_on_url
1799
 
        client.add_error_response(b'NotStacked')
 
1771
        client.add_error_response('NotStacked')
1800
1772
        # lock_write
1801
 
        client.add_success_response(b'ok', b'branch token', b'repo token')
 
1773
        client.add_success_response('ok', 'branch token', 'repo token')
1802
1774
        # query the current revision
1803
 
        client.add_success_response(b'ok', b'0', b'null:')
 
1775
        client.add_success_response('ok', '0', 'null:')
1804
1776
        # set_last_revision
1805
 
        client.add_success_response(b'ok')
 
1777
        client.add_success_response('ok')
1806
1778
        # unlock
1807
 
        client.add_success_response(b'ok')
 
1779
        client.add_success_response('ok')
1808
1780
 
1809
1781
        branch = self.make_remote_branch(transport, client)
1810
1782
        # Lock the branch, reset the record of remote calls.
1811
1783
        branch.lock_write()
1812
1784
        client._calls = []
1813
 
        result = branch.set_last_revision_info(1234, b'a-revision-id')
 
1785
        result = branch.set_last_revision_info(1234, 'a-revision-id')
1814
1786
        self.assertEqual(
1815
 
            [('call', b'Branch.last_revision_info', (b'branch/',)),
1816
 
             ('call', b'Branch.set_last_revision_info',
1817
 
                (b'branch/', b'branch token', b'repo token',
1818
 
                 b'1234', b'a-revision-id'))],
 
1787
            [('call', 'Branch.last_revision_info', ('branch/',)),
 
1788
             ('call', 'Branch.set_last_revision_info',
 
1789
                ('branch/', 'branch token', 'repo token',
 
1790
                 '1234', 'a-revision-id'))],
1819
1791
            client._calls)
1820
1792
        self.assertEqual(None, result)
1821
1793
 
1826
1798
        transport = transport.clone('branch')
1827
1799
        client = FakeClient(transport.base)
1828
1800
        # get_stacked_on_url
1829
 
        client.add_error_response(b'NotStacked')
 
1801
        client.add_error_response('NotStacked')
1830
1802
        # lock_write
1831
 
        client.add_success_response(b'ok', b'branch token', b'repo token')
 
1803
        client.add_success_response('ok', 'branch token', 'repo token')
1832
1804
        # set_last_revision
1833
 
        client.add_error_response(b'NoSuchRevision', b'revid')
 
1805
        client.add_error_response('NoSuchRevision', 'revid')
1834
1806
        # unlock
1835
 
        client.add_success_response(b'ok')
 
1807
        client.add_success_response('ok')
1836
1808
 
1837
1809
        branch = self.make_remote_branch(transport, client)
1838
1810
        # Lock the branch, reset the record of remote calls.
1840
1812
        client._calls = []
1841
1813
 
1842
1814
        self.assertRaises(
1843
 
            errors.NoSuchRevision, branch.set_last_revision_info, 123, b'revid')
 
1815
            errors.NoSuchRevision, branch.set_last_revision_info, 123, 'revid')
1844
1816
        branch.unlock()
1845
1817
 
1846
1818
    def test_backwards_compatibility(self):
1860
1832
        transport = transport.clone('branch')
1861
1833
        client = FakeClient(transport.base)
1862
1834
        client.add_expected_call(
1863
 
            b'Branch.get_stacked_on_url', (b'branch/',),
1864
 
            b'error', (b'NotStacked',))
1865
 
        client.add_expected_call(
1866
 
            b'Branch.last_revision_info',
1867
 
            (b'branch/',),
1868
 
            b'success', (b'ok', b'0', b'null:'))
1869
 
        client.add_expected_call(
1870
 
            b'Branch.set_last_revision_info',
1871
 
            (b'branch/', b'branch token', b'repo token', b'1234', b'a-revision-id',),
1872
 
            b'unknown', b'Branch.set_last_revision_info')
 
1835
            'Branch.get_stacked_on_url', ('branch/',),
 
1836
            'error', ('NotStacked',))
 
1837
        client.add_expected_call(
 
1838
            'Branch.last_revision_info',
 
1839
            ('branch/',),
 
1840
            'success', ('ok', '0', 'null:'))
 
1841
        client.add_expected_call(
 
1842
            'Branch.set_last_revision_info',
 
1843
            ('branch/', 'branch token', 'repo token', '1234', 'a-revision-id',),
 
1844
            'unknown', 'Branch.set_last_revision_info')
1873
1845
 
1874
1846
        branch = self.make_remote_branch(transport, client)
1875
 
 
1876
1847
        class StubRealBranch(object):
1877
1848
            def __init__(self):
1878
1849
                self.calls = []
1879
 
 
1880
1850
            def set_last_revision_info(self, revno, revision_id):
1881
1851
                self.calls.append(
1882
1852
                    ('set_last_revision_info', revno, revision_id))
1883
 
 
1884
1853
            def _clear_cached_state(self):
1885
1854
                pass
1886
1855
        real_branch = StubRealBranch()
1888
1857
        self.lock_remote_branch(branch)
1889
1858
 
1890
1859
        # Call set_last_revision_info, and verify it behaved as expected.
1891
 
        branch.set_last_revision_info(1234, b'a-revision-id')
 
1860
        result = branch.set_last_revision_info(1234, 'a-revision-id')
1892
1861
        self.assertEqual(
1893
 
            [('set_last_revision_info', 1234, b'a-revision-id')],
 
1862
            [('set_last_revision_info', 1234, 'a-revision-id')],
1894
1863
            real_branch.calls)
1895
1864
        self.assertFinished(client)
1896
1865
 
1903
1872
        transport = transport.clone('branch')
1904
1873
        client = FakeClient(transport.base)
1905
1874
        # get_stacked_on_url
1906
 
        client.add_error_response(b'NotStacked')
 
1875
        client.add_error_response('NotStacked')
1907
1876
        # lock_write
1908
 
        client.add_success_response(b'ok', b'branch token', b'repo token')
 
1877
        client.add_success_response('ok', 'branch token', 'repo token')
1909
1878
        # set_last_revision
1910
 
        client.add_error_response(b'UnexpectedError')
 
1879
        client.add_error_response('UnexpectedError')
1911
1880
        # unlock
1912
 
        client.add_success_response(b'ok')
 
1881
        client.add_success_response('ok')
1913
1882
 
1914
1883
        branch = self.make_remote_branch(transport, client)
1915
1884
        # Lock the branch, reset the record of remote calls.
1918
1887
 
1919
1888
        err = self.assertRaises(
1920
1889
            errors.UnknownErrorFromSmartServer,
1921
 
            branch.set_last_revision_info, 123, b'revid')
1922
 
        self.assertEqual((b'UnexpectedError',), err.error_tuple)
 
1890
            branch.set_last_revision_info, 123, 'revid')
 
1891
        self.assertEqual(('UnexpectedError',), err.error_tuple)
1923
1892
        branch.unlock()
1924
1893
 
1925
1894
    def test_tip_change_rejected(self):
1931
1900
        transport = transport.clone('branch')
1932
1901
        client = FakeClient(transport.base)
1933
1902
        # get_stacked_on_url
1934
 
        client.add_error_response(b'NotStacked')
 
1903
        client.add_error_response('NotStacked')
1935
1904
        # lock_write
1936
 
        client.add_success_response(b'ok', b'branch token', b'repo token')
 
1905
        client.add_success_response('ok', 'branch token', 'repo token')
1937
1906
        # set_last_revision
1938
 
        client.add_error_response(b'TipChangeRejected', b'rejection message')
 
1907
        client.add_error_response('TipChangeRejected', 'rejection message')
1939
1908
        # unlock
1940
 
        client.add_success_response(b'ok')
 
1909
        client.add_success_response('ok')
1941
1910
 
1942
1911
        branch = self.make_remote_branch(transport, client)
1943
1912
        # Lock the branch, reset the record of remote calls.
1949
1918
        # set_last_revision_info causes a TipChangeRejected exception.
1950
1919
        err = self.assertRaises(
1951
1920
            errors.TipChangeRejected,
1952
 
            branch.set_last_revision_info, 123, b'revid')
 
1921
            branch.set_last_revision_info, 123, 'revid')
1953
1922
        self.assertEqual('rejection message', err.msg)
1954
1923
 
1955
1924
 
1959
1928
        # in an empty branch we decode the response properly
1960
1929
        client = FakeClient()
1961
1930
        client.add_expected_call(
1962
 
            b'Branch.get_stacked_on_url', (b'memory:///',),
1963
 
            b'error', (b'NotStacked',),)
1964
 
        client.add_success_response_with_body(b'# config file body', b'ok')
 
1931
            'Branch.get_stacked_on_url', ('memory:///',),
 
1932
            'error', ('NotStacked',),)
 
1933
        client.add_success_response_with_body('# config file body', 'ok')
1965
1934
        transport = MemoryTransport()
1966
1935
        branch = self.make_remote_branch(transport, client)
1967
1936
        config = branch.get_config()
1968
1937
        config.has_explicit_nickname()
1969
1938
        self.assertEqual(
1970
 
            [('call', b'Branch.get_stacked_on_url', (b'memory:///',)),
1971
 
             ('call_expecting_body', b'Branch.get_config_file', (b'memory:///',))],
 
1939
            [('call', 'Branch.get_stacked_on_url', ('memory:///',)),
 
1940
             ('call_expecting_body', 'Branch.get_config_file', ('memory:///',))],
1972
1941
            client._calls)
1973
1942
 
1974
1943
    def test_get_multi_line_branch_conf(self):
1977
1946
        # https://bugs.launchpad.net/bzr/+bug/354075
1978
1947
        client = FakeClient()
1979
1948
        client.add_expected_call(
1980
 
            b'Branch.get_stacked_on_url', (b'memory:///',),
1981
 
            b'error', (b'NotStacked',),)
1982
 
        client.add_success_response_with_body(b'a = 1\nb = 2\nc = 3\n', b'ok')
 
1949
            'Branch.get_stacked_on_url', ('memory:///',),
 
1950
            'error', ('NotStacked',),)
 
1951
        client.add_success_response_with_body('a = 1\nb = 2\nc = 3\n', 'ok')
1983
1952
        transport = MemoryTransport()
1984
1953
        branch = self.make_remote_branch(transport, client)
1985
1954
        config = branch.get_config()
1988
1957
    def test_set_option(self):
1989
1958
        client = FakeClient()
1990
1959
        client.add_expected_call(
1991
 
            b'Branch.get_stacked_on_url', (b'memory:///',),
1992
 
            b'error', (b'NotStacked',),)
1993
 
        client.add_expected_call(
1994
 
            b'Branch.lock_write', (b'memory:///', b'', b''),
1995
 
            b'success', (b'ok', b'branch token', b'repo token'))
1996
 
        client.add_expected_call(
1997
 
            b'Branch.set_config_option', (b'memory:///', b'branch token',
1998
 
                                          b'repo token', b'foo', b'bar', b''),
1999
 
            b'success', ())
2000
 
        client.add_expected_call(
2001
 
            b'Branch.unlock', (b'memory:///', b'branch token', b'repo token'),
2002
 
            b'success', (b'ok',))
 
1960
            'Branch.get_stacked_on_url', ('memory:///',),
 
1961
            'error', ('NotStacked',),)
 
1962
        client.add_expected_call(
 
1963
            'Branch.lock_write', ('memory:///', '', ''),
 
1964
            'success', ('ok', 'branch token', 'repo token'))
 
1965
        client.add_expected_call(
 
1966
            'Branch.set_config_option', ('memory:///', 'branch token',
 
1967
            'repo token', 'foo', 'bar', ''),
 
1968
            'success', ())
 
1969
        client.add_expected_call(
 
1970
            'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
 
1971
            'success', ('ok',))
2003
1972
        transport = MemoryTransport()
2004
1973
        branch = self.make_remote_branch(transport, client)
2005
1974
        branch.lock_write()
2011
1980
    def test_set_option_with_dict(self):
2012
1981
        client = FakeClient()
2013
1982
        client.add_expected_call(
2014
 
            b'Branch.get_stacked_on_url', (b'memory:///',),
2015
 
            b'error', (b'NotStacked',),)
2016
 
        client.add_expected_call(
2017
 
            b'Branch.lock_write', (b'memory:///', b'', b''),
2018
 
            b'success', (b'ok', b'branch token', b'repo token'))
2019
 
        encoded_dict_value = b'd5:ascii1:a11:unicode \xe2\x8c\x9a3:\xe2\x80\xbde'
2020
 
        client.add_expected_call(
2021
 
            b'Branch.set_config_option_dict', (b'memory:///', b'branch token',
2022
 
                                               b'repo token', encoded_dict_value, b'foo', b''),
2023
 
            b'success', ())
2024
 
        client.add_expected_call(
2025
 
            b'Branch.unlock', (b'memory:///', b'branch token', b'repo token'),
2026
 
            b'success', (b'ok',))
 
1983
            'Branch.get_stacked_on_url', ('memory:///',),
 
1984
            'error', ('NotStacked',),)
 
1985
        client.add_expected_call(
 
1986
            'Branch.lock_write', ('memory:///', '', ''),
 
1987
            'success', ('ok', 'branch token', 'repo token'))
 
1988
        encoded_dict_value = 'd5:ascii1:a11:unicode \xe2\x8c\x9a3:\xe2\x80\xbde'
 
1989
        client.add_expected_call(
 
1990
            'Branch.set_config_option_dict', ('memory:///', 'branch token',
 
1991
            'repo token', encoded_dict_value, 'foo', ''),
 
1992
            'success', ())
 
1993
        client.add_expected_call(
 
1994
            'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
 
1995
            'success', ('ok',))
2027
1996
        transport = MemoryTransport()
2028
1997
        branch = self.make_remote_branch(transport, client)
2029
1998
        branch.lock_write()
2034
2003
        branch.unlock()
2035
2004
        self.assertFinished(client)
2036
2005
 
2037
 
    def test_set_option_with_bool(self):
2038
 
        client = FakeClient()
2039
 
        client.add_expected_call(
2040
 
            b'Branch.get_stacked_on_url', (b'memory:///',),
2041
 
            b'error', (b'NotStacked',),)
2042
 
        client.add_expected_call(
2043
 
            b'Branch.lock_write', (b'memory:///', b'', b''),
2044
 
            b'success', (b'ok', b'branch token', b'repo token'))
2045
 
        client.add_expected_call(
2046
 
            b'Branch.set_config_option', (b'memory:///', b'branch token',
2047
 
                                          b'repo token', b'True', b'foo', b''),
2048
 
            b'success', ())
2049
 
        client.add_expected_call(
2050
 
            b'Branch.unlock', (b'memory:///', b'branch token', b'repo token'),
2051
 
            b'success', (b'ok',))
2052
 
        transport = MemoryTransport()
2053
 
        branch = self.make_remote_branch(transport, client)
2054
 
        branch.lock_write()
2055
 
        config = branch._get_config()
2056
 
        config.set_option(True, 'foo')
2057
 
        branch.unlock()
2058
 
        self.assertFinished(client)
2059
 
 
2060
2006
    def test_backwards_compat_set_option(self):
2061
2007
        self.setup_smart_server_with_call_log()
2062
2008
        branch = self.make_branch('.')
2063
 
        verb = b'Branch.set_config_option'
 
2009
        verb = 'Branch.set_config_option'
2064
2010
        self.disable_verb(verb)
2065
2011
        branch.lock_write()
2066
2012
        self.addCleanup(branch.unlock)
2072
2018
    def test_backwards_compat_set_option_with_dict(self):
2073
2019
        self.setup_smart_server_with_call_log()
2074
2020
        branch = self.make_branch('.')
2075
 
        verb = b'Branch.set_config_option_dict'
 
2021
        verb = 'Branch.set_config_option_dict'
2076
2022
        self.disable_verb(verb)
2077
2023
        branch.lock_write()
2078
2024
        self.addCleanup(branch.unlock)
2090
2036
        # in an empty branch we decode the response properly
2091
2037
        client = FakeClient()
2092
2038
        client.add_expected_call(
2093
 
            b'Branch.get_stacked_on_url', (b'memory:///',),
2094
 
            b'error', (b'NotStacked',),)
2095
 
        client.add_success_response_with_body(b'# config file body', b'ok')
 
2039
            'Branch.get_stacked_on_url', ('memory:///',),
 
2040
            'error', ('NotStacked',),)
 
2041
        client.add_success_response_with_body('# config file body', 'ok')
2096
2042
        transport = MemoryTransport()
2097
2043
        branch = self.make_remote_branch(transport, client)
2098
2044
        config = branch.get_config_stack()
2099
2045
        config.get("email")
2100
2046
        config.get("log_format")
2101
2047
        self.assertEqual(
2102
 
            [('call', b'Branch.get_stacked_on_url', (b'memory:///',)),
2103
 
             ('call_expecting_body', b'Branch.get_config_file', (b'memory:///',))],
 
2048
            [('call', 'Branch.get_stacked_on_url', ('memory:///',)),
 
2049
             ('call_expecting_body', 'Branch.get_config_file', ('memory:///',))],
2104
2050
            client._calls)
2105
2051
 
2106
2052
    def test_set_branch_conf(self):
2107
2053
        client = FakeClient()
2108
2054
        client.add_expected_call(
2109
 
            b'Branch.get_stacked_on_url', (b'memory:///',),
2110
 
            b'error', (b'NotStacked',),)
2111
 
        client.add_expected_call(
2112
 
            b'Branch.lock_write', (b'memory:///', b'', b''),
2113
 
            b'success', (b'ok', b'branch token', b'repo token'))
2114
 
        client.add_expected_call(
2115
 
            b'Branch.get_config_file', (b'memory:///', ),
2116
 
            b'success', (b'ok', ), b"# line 1\n")
2117
 
        client.add_expected_call(
2118
 
            b'Branch.get_config_file', (b'memory:///', ),
2119
 
            b'success', (b'ok', ), b"# line 1\n")
2120
 
        client.add_expected_call(
2121
 
            b'Branch.put_config_file', (b'memory:///', b'branch token',
2122
 
                                        b'repo token'),
2123
 
            b'success', (b'ok',))
2124
 
        client.add_expected_call(
2125
 
            b'Branch.unlock', (b'memory:///', b'branch token', b'repo token'),
2126
 
            b'success', (b'ok',))
 
2055
            'Branch.get_stacked_on_url', ('memory:///',),
 
2056
            'error', ('NotStacked',),)
 
2057
        client.add_expected_call(
 
2058
            'Branch.lock_write', ('memory:///', '', ''),
 
2059
            'success', ('ok', 'branch token', 'repo token'))
 
2060
        client.add_expected_call(
 
2061
            'Branch.get_config_file', ('memory:///', ),
 
2062
            'success', ('ok', ), "# line 1\n")
 
2063
        client.add_expected_call(
 
2064
            'Branch.get_config_file', ('memory:///', ),
 
2065
            'success', ('ok', ), "# line 1\n")
 
2066
        client.add_expected_call(
 
2067
            'Branch.put_config_file', ('memory:///', 'branch token',
 
2068
            'repo token'),
 
2069
            'success', ('ok',))
 
2070
        client.add_expected_call(
 
2071
            'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
 
2072
            'success', ('ok',))
2127
2073
        transport = MemoryTransport()
2128
2074
        branch = self.make_remote_branch(transport, client)
2129
2075
        branch.lock_write()
2132
2078
        branch.unlock()
2133
2079
        self.assertFinished(client)
2134
2080
        self.assertEqual(
2135
 
            [('call', b'Branch.get_stacked_on_url', (b'memory:///',)),
2136
 
             ('call', b'Branch.lock_write', (b'memory:///', b'', b'')),
2137
 
             ('call_expecting_body', b'Branch.get_config_file',
2138
 
                 (b'memory:///',)),
2139
 
             ('call_expecting_body', b'Branch.get_config_file',
2140
 
                 (b'memory:///',)),
2141
 
             ('call_with_body_bytes_expecting_body', b'Branch.put_config_file',
2142
 
                 (b'memory:///', b'branch token', b'repo token'),
2143
 
                 b'# line 1\nemail = The Dude <lebowski@example.com>\n'),
2144
 
             ('call', b'Branch.unlock',
2145
 
                 (b'memory:///', b'branch token', b'repo token'))],
 
2081
            [('call', 'Branch.get_stacked_on_url', ('memory:///',)),
 
2082
             ('call', 'Branch.lock_write', ('memory:///', '', '')),
 
2083
             ('call_expecting_body', 'Branch.get_config_file', ('memory:///',)),
 
2084
             ('call_expecting_body', 'Branch.get_config_file', ('memory:///',)),
 
2085
             ('call_with_body_bytes_expecting_body', 'Branch.put_config_file',
 
2086
                 ('memory:///', 'branch token', 'repo token'),
 
2087
                 '# line 1\nemail = The Dude <lebowski@example.com>\n'),
 
2088
             ('call', 'Branch.unlock', ('memory:///', 'branch token', 'repo token'))],
2146
2089
            client._calls)
2147
2090
 
2148
2091
 
2152
2095
        transport = MemoryTransport()
2153
2096
        client = FakeClient(transport.base)
2154
2097
        client.add_expected_call(
2155
 
            b'Branch.get_stacked_on_url', (b'quack/',),
2156
 
            b'error', (b'NotStacked',),)
 
2098
            'Branch.get_stacked_on_url', ('quack/',),
 
2099
            'error', ('NotStacked',),)
2157
2100
        client.add_expected_call(
2158
 
            b'Branch.lock_write', (b'quack/', b'', b''),
2159
 
            b'error', (b'UnlockableTransport',))
 
2101
            'Branch.lock_write', ('quack/', '', ''),
 
2102
            'error', ('UnlockableTransport',))
2160
2103
        transport.mkdir('quack')
2161
2104
        transport = transport.clone('quack')
2162
2105
        branch = self.make_remote_branch(transport, client)
2170
2113
        transport = MemoryTransport()
2171
2114
        client = FakeClient(transport.base)
2172
2115
        client.add_expected_call(
2173
 
            b'Branch.get_stacked_on_url', (b'quack/',),
2174
 
            b'error', (b'NotStacked',),)
2175
 
        client.add_expected_call(
2176
 
            b'Branch.revision_id_to_revno', (b'quack/', b'null:'),
2177
 
            b'success', (b'ok', b'0',),)
2178
 
        client.add_expected_call(
2179
 
            b'Branch.revision_id_to_revno', (b'quack/', b'unknown'),
2180
 
            b'error', (b'NoSuchRevision', b'unknown',),)
 
2116
            'Branch.get_stacked_on_url', ('quack/',),
 
2117
            'error', ('NotStacked',),)
 
2118
        client.add_expected_call(
 
2119
            'Branch.revision_id_to_revno', ('quack/', 'null:'),
 
2120
            'success', ('ok', '0',),)
 
2121
        client.add_expected_call(
 
2122
            'Branch.revision_id_to_revno', ('quack/', 'unknown'),
 
2123
            'error', ('NoSuchRevision', 'unknown',),)
2181
2124
        transport.mkdir('quack')
2182
2125
        transport = transport.clone('quack')
2183
2126
        branch = self.make_remote_branch(transport, client)
2184
 
        self.assertEqual(0, branch.revision_id_to_revno(b'null:'))
 
2127
        self.assertEqual(0, branch.revision_id_to_revno('null:'))
2185
2128
        self.assertRaises(errors.NoSuchRevision,
2186
 
                          branch.revision_id_to_revno, b'unknown')
 
2129
            branch.revision_id_to_revno, 'unknown')
2187
2130
        self.assertFinished(client)
2188
2131
 
2189
2132
    def test_dotted(self):
2190
2133
        transport = MemoryTransport()
2191
2134
        client = FakeClient(transport.base)
2192
2135
        client.add_expected_call(
2193
 
            b'Branch.get_stacked_on_url', (b'quack/',),
2194
 
            b'error', (b'NotStacked',),)
2195
 
        client.add_expected_call(
2196
 
            b'Branch.revision_id_to_revno', (b'quack/', b'null:'),
2197
 
            b'success', (b'ok', b'0',),)
2198
 
        client.add_expected_call(
2199
 
            b'Branch.revision_id_to_revno', (b'quack/', b'unknown'),
2200
 
            b'error', (b'NoSuchRevision', b'unknown',),)
 
2136
            'Branch.get_stacked_on_url', ('quack/',),
 
2137
            'error', ('NotStacked',),)
 
2138
        client.add_expected_call(
 
2139
            'Branch.revision_id_to_revno', ('quack/', 'null:'),
 
2140
            'success', ('ok', '0',),)
 
2141
        client.add_expected_call(
 
2142
            'Branch.revision_id_to_revno', ('quack/', 'unknown'),
 
2143
            'error', ('NoSuchRevision', 'unknown',),)
2201
2144
        transport.mkdir('quack')
2202
2145
        transport = transport.clone('quack')
2203
2146
        branch = self.make_remote_branch(transport, client)
2204
 
        self.assertEqual((0, ), branch.revision_id_to_dotted_revno(b'null:'))
 
2147
        self.assertEqual((0, ), branch.revision_id_to_dotted_revno('null:'))
2205
2148
        self.assertRaises(errors.NoSuchRevision,
2206
 
                          branch.revision_id_to_dotted_revno, b'unknown')
2207
 
        self.assertFinished(client)
2208
 
 
2209
 
    def test_ghost_revid(self):
2210
 
        transport = MemoryTransport()
2211
 
        client = FakeClient(transport.base)
2212
 
        client.add_expected_call(
2213
 
            b'Branch.get_stacked_on_url', (b'quack/',),
2214
 
            b'error', (b'NotStacked',),)
2215
 
        # Some older versions of bzr/brz didn't explicitly return
2216
 
        # GhostRevisionsHaveNoRevno
2217
 
        client.add_expected_call(
2218
 
            b'Branch.revision_id_to_revno', (b'quack/', b'revid'),
2219
 
            b'error', (b'error', b'GhostRevisionsHaveNoRevno',
2220
 
                       b'The reivison {revid} was not found because there was '
2221
 
                       b'a ghost at {ghost-revid}'))
2222
 
        client.add_expected_call(
2223
 
            b'Branch.revision_id_to_revno', (b'quack/', b'revid'),
2224
 
            b'error', (b'GhostRevisionsHaveNoRevno', b'revid', b'ghost-revid',))
2225
 
        transport.mkdir('quack')
2226
 
        transport = transport.clone('quack')
2227
 
        branch = self.make_remote_branch(transport, client)
2228
 
        self.assertRaises(errors.GhostRevisionsHaveNoRevno,
2229
 
                          branch.revision_id_to_dotted_revno, b'revid')
2230
 
        self.assertRaises(errors.GhostRevisionsHaveNoRevno,
2231
 
                          branch.revision_id_to_dotted_revno, b'revid')
 
2149
            branch.revision_id_to_dotted_revno, 'unknown')
2232
2150
        self.assertFinished(client)
2233
2151
 
2234
2152
    def test_dotted_no_smart_verb(self):
2235
2153
        self.setup_smart_server_with_call_log()
2236
2154
        branch = self.make_branch('.')
2237
 
        self.disable_verb(b'Branch.revision_id_to_revno')
 
2155
        self.disable_verb('Branch.revision_id_to_revno')
2238
2156
        self.reset_smart_call_log()
2239
2157
        self.assertEqual((0, ),
2240
 
                         branch.revision_id_to_dotted_revno(b'null:'))
 
2158
            branch.revision_id_to_dotted_revno('null:'))
2241
2159
        self.assertLength(8, self.hpss_calls)
2242
2160
 
2243
2161
 
2245
2163
 
2246
2164
    def test__get_config(self):
2247
2165
        client = FakeClient()
2248
 
        client.add_success_response_with_body(b'default_stack_on = /\n', b'ok')
 
2166
        client.add_success_response_with_body('default_stack_on = /\n', 'ok')
2249
2167
        transport = MemoryTransport()
2250
2168
        bzrdir = self.make_remote_bzrdir(transport, client)
2251
2169
        config = bzrdir.get_config()
2252
2170
        self.assertEqual('/', config.get_default_stack_on())
2253
2171
        self.assertEqual(
2254
 
            [('call_expecting_body', b'BzrDir.get_config_file',
2255
 
                (b'memory:///',))],
 
2172
            [('call_expecting_body', 'BzrDir.get_config_file', ('memory:///',))],
2256
2173
            client._calls)
2257
2174
 
2258
2175
    def test_set_option_uses_vfs(self):
2259
2176
        self.setup_smart_server_with_call_log()
2260
 
        bzrdir = self.make_controldir('.')
 
2177
        bzrdir = self.make_bzrdir('.')
2261
2178
        self.reset_smart_call_log()
2262
2179
        config = bzrdir.get_config()
2263
2180
        config.set_default_stack_on('/')
2265
2182
 
2266
2183
    def test_backwards_compat_get_option(self):
2267
2184
        self.setup_smart_server_with_call_log()
2268
 
        bzrdir = self.make_controldir('.')
2269
 
        verb = b'BzrDir.get_config_file'
 
2185
        bzrdir = self.make_bzrdir('.')
 
2186
        verb = 'BzrDir.get_config_file'
2270
2187
        self.disable_verb(verb)
2271
2188
        self.reset_smart_call_log()
2272
2189
        self.assertEqual(None,
2273
 
                         bzrdir._get_config().get_option('default_stack_on'))
 
2190
            bzrdir._get_config().get_option('default_stack_on'))
2274
2191
        self.assertLength(4, self.hpss_calls)
2275
2192
 
2276
2193
 
2278
2195
 
2279
2196
    def test_true(self):
2280
2197
        client = FakeClient()
2281
 
        client.add_success_response(b'yes')
 
2198
        client.add_success_response('yes')
2282
2199
        transport = RemoteTransport('bzr://example.com/', medium=False,
2283
2200
                                    _client=client)
2284
2201
        self.assertEqual(True, transport.is_readonly())
2285
2202
        self.assertEqual(
2286
 
            [('call', b'Transport.is_readonly', ())],
 
2203
            [('call', 'Transport.is_readonly', ())],
2287
2204
            client._calls)
2288
2205
 
2289
2206
    def test_false(self):
2290
2207
        client = FakeClient()
2291
 
        client.add_success_response(b'no')
 
2208
        client.add_success_response('no')
2292
2209
        transport = RemoteTransport('bzr://example.com/', medium=False,
2293
2210
                                    _client=client)
2294
2211
        self.assertEqual(False, transport.is_readonly())
2295
2212
        self.assertEqual(
2296
 
            [('call', b'Transport.is_readonly', ())],
 
2213
            [('call', 'Transport.is_readonly', ())],
2297
2214
            client._calls)
2298
2215
 
2299
2216
    def test_error_from_old_server(self):
2304
2221
        underlying filesystem could be readonly anyway).
2305
2222
        """
2306
2223
        client = FakeClient()
2307
 
        client.add_unknown_method_response(b'Transport.is_readonly')
 
2224
        client.add_unknown_method_response('Transport.is_readonly')
2308
2225
        transport = RemoteTransport('bzr://example.com/', medium=False,
2309
2226
                                    _client=client)
2310
2227
        self.assertEqual(False, transport.is_readonly())
2311
2228
        self.assertEqual(
2312
 
            [('call', b'Transport.is_readonly', ())],
 
2229
            [('call', 'Transport.is_readonly', ())],
2313
2230
            client._calls)
2314
2231
 
2315
2232
 
2317
2234
 
2318
2235
    def test_permissiondenied(self):
2319
2236
        client = FakeClient()
2320
 
        client.add_error_response(
2321
 
            b'PermissionDenied', b'remote path', b'extra')
 
2237
        client.add_error_response('PermissionDenied', 'remote path', 'extra')
2322
2238
        transport = RemoteTransport('bzr://example.com/', medium=False,
2323
2239
                                    _client=client)
2324
2240
        exc = self.assertRaises(
2337
2253
        conf = config.AuthenticationConfig()
2338
2254
        conf._get_config().update(
2339
2255
            {'bzr+sshtest': {'scheme': 'ssh', 'user': 'bar', 'host':
2340
 
                             'example.com'}})
 
2256
            'example.com'}})
2341
2257
        conf._save()
2342
2258
        t = RemoteSSHTransport('bzr+ssh://example.com')
2343
2259
        self.assertEqual('bar', t._get_credentials()[0])
2366
2282
        transport = transport.clone(transport_path)
2367
2283
        # we do not want bzrdir to make any remote calls
2368
2284
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
2369
 
                              _client=False)
 
2285
            _client=False)
2370
2286
        repo = RemoteRepository(bzrdir, None, _client=client)
2371
2287
        return repo, client
2372
2288
 
2382
2298
        real_format = branch.format_registry.get_default()
2383
2299
        remote_format._network_name = real_format.network_name()
2384
2300
        self.assertEqual(remoted_description(real_format),
2385
 
                         remote_format.get_format_description())
 
2301
            remote_format.get_format_description())
2386
2302
 
2387
2303
 
2388
2304
class TestRepositoryFormat(TestRemoteRepository):
2402
2318
        real_format = repository.format_registry.get_default()
2403
2319
        remote_repo_format._network_name = real_format.network_name()
2404
2320
        self.assertEqual(remoted_description(real_format),
2405
 
                         remote_repo_format.get_format_description())
 
2321
            remote_repo_format.get_format_description())
2406
2322
 
2407
2323
 
2408
2324
class TestRepositoryAllRevisionIds(TestRemoteRepository):
2410
2326
    def test_empty(self):
2411
2327
        transport_path = 'quack'
2412
2328
        repo, client = self.setup_fake_client_and_repository(transport_path)
2413
 
        client.add_success_response_with_body(b'', b'ok')
 
2329
        client.add_success_response_with_body('', 'ok')
2414
2330
        self.assertEqual([], repo.all_revision_ids())
2415
2331
        self.assertEqual(
2416
 
            [('call_expecting_body', b'Repository.all_revision_ids',
2417
 
              (b'quack/',))],
 
2332
            [('call_expecting_body', 'Repository.all_revision_ids',
 
2333
             ('quack/',))],
2418
2334
            client._calls)
2419
2335
 
2420
2336
    def test_with_some_content(self):
2421
2337
        transport_path = 'quack'
2422
2338
        repo, client = self.setup_fake_client_and_repository(transport_path)
2423
2339
        client.add_success_response_with_body(
2424
 
            b'rev1\nrev2\nanotherrev\n', b'ok')
2425
 
        self.assertEqual(
2426
 
            set([b"rev1", b"rev2", b"anotherrev"]),
2427
 
            set(repo.all_revision_ids()))
2428
 
        self.assertEqual(
2429
 
            [('call_expecting_body', b'Repository.all_revision_ids',
2430
 
              (b'quack/',))],
 
2340
            'rev1\nrev2\nanotherrev\n', 'ok')
 
2341
        self.assertEqual(["rev1", "rev2", "anotherrev"],
 
2342
            repo.all_revision_ids())
 
2343
        self.assertEqual(
 
2344
            [('call_expecting_body', 'Repository.all_revision_ids',
 
2345
             ('quack/',))],
2431
2346
            client._calls)
2432
2347
 
2433
2348
 
2438
2353
        transport_path = 'quack'
2439
2354
        repo, client = self.setup_fake_client_and_repository(transport_path)
2440
2355
        client.add_success_response_with_body(
2441
 
            b'revisions: 2\nsize: 18\n', b'ok')
 
2356
            'revisions: 2\nsize: 18\n', 'ok')
2442
2357
        result = repo.gather_stats(None)
2443
2358
        self.assertEqual(
2444
 
            [('call_expecting_body', b'Repository.gather_stats',
2445
 
              (b'quack/', b'', b'no'))],
 
2359
            [('call_expecting_body', 'Repository.gather_stats',
 
2360
             ('quack/','','no'))],
2446
2361
            client._calls)
2447
2362
        self.assertEqual({'revisions': 2, 'size': 18}, result)
2448
2363
 
2449
2364
    def test_revid_no_committers(self):
2450
2365
        # ('ok',), body without committers
2451
 
        body = (b'firstrev: 123456.300 3600\n'
2452
 
                b'latestrev: 654231.400 0\n'
2453
 
                b'revisions: 2\n'
2454
 
                b'size: 18\n')
 
2366
        body = ('firstrev: 123456.300 3600\n'
 
2367
                'latestrev: 654231.400 0\n'
 
2368
                'revisions: 2\n'
 
2369
                'size: 18\n')
2455
2370
        transport_path = 'quick'
2456
2371
        revid = u'\xc8'.encode('utf8')
2457
2372
        repo, client = self.setup_fake_client_and_repository(transport_path)
2458
 
        client.add_success_response_with_body(body, b'ok')
 
2373
        client.add_success_response_with_body(body, 'ok')
2459
2374
        result = repo.gather_stats(revid)
2460
2375
        self.assertEqual(
2461
 
            [('call_expecting_body', b'Repository.gather_stats',
2462
 
              (b'quick/', revid, b'no'))],
 
2376
            [('call_expecting_body', 'Repository.gather_stats',
 
2377
              ('quick/', revid, 'no'))],
2463
2378
            client._calls)
2464
2379
        self.assertEqual({'revisions': 2, 'size': 18,
2465
2380
                          'firstrev': (123456.300, 3600),
2466
 
                          'latestrev': (654231.400, 0), },
 
2381
                          'latestrev': (654231.400, 0),},
2467
2382
                         result)
2468
2383
 
2469
2384
    def test_revid_with_committers(self):
2470
2385
        # ('ok',), body with committers
2471
 
        body = (b'committers: 128\n'
2472
 
                b'firstrev: 123456.300 3600\n'
2473
 
                b'latestrev: 654231.400 0\n'
2474
 
                b'revisions: 2\n'
2475
 
                b'size: 18\n')
 
2386
        body = ('committers: 128\n'
 
2387
                'firstrev: 123456.300 3600\n'
 
2388
                'latestrev: 654231.400 0\n'
 
2389
                'revisions: 2\n'
 
2390
                'size: 18\n')
2476
2391
        transport_path = 'buick'
2477
2392
        revid = u'\xc8'.encode('utf8')
2478
2393
        repo, client = self.setup_fake_client_and_repository(transport_path)
2479
 
        client.add_success_response_with_body(body, b'ok')
 
2394
        client.add_success_response_with_body(body, 'ok')
2480
2395
        result = repo.gather_stats(revid, True)
2481
2396
        self.assertEqual(
2482
 
            [('call_expecting_body', b'Repository.gather_stats',
2483
 
              (b'buick/', revid, b'yes'))],
 
2397
            [('call_expecting_body', 'Repository.gather_stats',
 
2398
              ('buick/', revid, 'yes'))],
2484
2399
            client._calls)
2485
2400
        self.assertEqual({'revisions': 2, 'size': 18,
2486
2401
                          'committers': 128,
2487
2402
                          'firstrev': (123456.300, 3600),
2488
 
                          'latestrev': (654231.400, 0), },
 
2403
                          'latestrev': (654231.400, 0),},
2489
2404
                         result)
2490
2405
 
2491
2406
 
2494
2409
    def test_break_lock(self):
2495
2410
        transport_path = 'quack'
2496
2411
        repo, client = self.setup_fake_client_and_repository(transport_path)
2497
 
        client.add_success_response(b'ok')
 
2412
        client.add_success_response('ok')
2498
2413
        repo.break_lock()
2499
2414
        self.assertEqual(
2500
 
            [('call', b'Repository.break_lock', (b'quack/',))],
 
2415
            [('call', 'Repository.break_lock', ('quack/',))],
2501
2416
            client._calls)
2502
2417
 
2503
2418
 
2506
2421
    def test_get_serializer_format(self):
2507
2422
        transport_path = 'hill'
2508
2423
        repo, client = self.setup_fake_client_and_repository(transport_path)
2509
 
        client.add_success_response(b'ok', b'7')
2510
 
        self.assertEqual(b'7', repo.get_serializer_format())
 
2424
        client.add_success_response('ok', '7')
 
2425
        self.assertEqual('7', repo.get_serializer_format())
2511
2426
        self.assertEqual(
2512
 
            [('call', b'VersionedFileRepository.get_serializer_format',
2513
 
              (b'hill/', ))],
 
2427
            [('call', 'VersionedFileRepository.get_serializer_format',
 
2428
              ('hill/', ))],
2514
2429
            client._calls)
2515
2430
 
2516
2431
 
2519
2434
    def test_reconcile(self):
2520
2435
        transport_path = 'hill'
2521
2436
        repo, client = self.setup_fake_client_and_repository(transport_path)
2522
 
        body = (b"garbage_inventories: 2\n"
2523
 
                b"inconsistent_parents: 3\n")
 
2437
        body = ("garbage_inventories: 2\n"
 
2438
                "inconsistent_parents: 3\n")
2524
2439
        client.add_expected_call(
2525
 
            b'Repository.lock_write', (b'hill/', b''),
2526
 
            b'success', (b'ok', b'a token'))
2527
 
        client.add_success_response_with_body(body, b'ok')
 
2440
            'Repository.lock_write', ('hill/', ''),
 
2441
            'success', ('ok', 'a token'))
 
2442
        client.add_success_response_with_body(body, 'ok')
2528
2443
        reconciler = repo.reconcile()
2529
2444
        self.assertEqual(
2530
 
            [('call', b'Repository.lock_write', (b'hill/', b'')),
2531
 
             ('call_expecting_body', b'Repository.reconcile',
2532
 
                (b'hill/', b'a token'))],
 
2445
            [('call', 'Repository.lock_write', ('hill/', '')),
 
2446
             ('call_expecting_body', 'Repository.reconcile',
 
2447
                ('hill/', 'a token'))],
2533
2448
            client._calls)
2534
2449
        self.assertEqual(2, reconciler.garbage_inventories)
2535
2450
        self.assertEqual(3, reconciler.inconsistent_parents)
2542
2457
        transport_path = 'quack'
2543
2458
        repo, client = self.setup_fake_client_and_repository(transport_path)
2544
2459
        client.add_success_response_with_body(
2545
 
            b'THETEXT', b'ok')
2546
 
        self.assertEqual(b"THETEXT", repo.get_signature_text(b"revid"))
 
2460
            'THETEXT', 'ok')
 
2461
        self.assertEqual("THETEXT", repo.get_signature_text("revid"))
2547
2462
        self.assertEqual(
2548
 
            [('call_expecting_body', b'Repository.get_revision_signature_text',
2549
 
              (b'quack/', b'revid'))],
 
2463
            [('call_expecting_body', 'Repository.get_revision_signature_text',
 
2464
             ('quack/', 'revid'))],
2550
2465
            client._calls)
2551
2466
 
2552
2467
    def test_no_signature(self):
2553
2468
        transport_path = 'quick'
2554
2469
        repo, client = self.setup_fake_client_and_repository(transport_path)
2555
 
        client.add_error_response(b'nosuchrevision', b'unknown')
 
2470
        client.add_error_response('nosuchrevision', 'unknown')
2556
2471
        self.assertRaises(errors.NoSuchRevision, repo.get_signature_text,
2557
 
                          b"unknown")
 
2472
                "unknown")
2558
2473
        self.assertEqual(
2559
 
            [('call_expecting_body', b'Repository.get_revision_signature_text',
2560
 
              (b'quick/', b'unknown'))],
 
2474
            [('call_expecting_body', 'Repository.get_revision_signature_text',
 
2475
              ('quick/', 'unknown'))],
2561
2476
            client._calls)
2562
2477
 
2563
2478
 
2577
2492
        transport_path = 'quack'
2578
2493
        repo, client = self.setup_fake_client_and_repository(transport_path)
2579
2494
        client.add_expected_call(
2580
 
            b'Repository.lock_write', (b'quack/', b''),
2581
 
            b'success', (b'ok', b'a token'))
2582
 
        client.add_expected_call(
2583
 
            b'Repository.start_write_group', (b'quack/', b'a token'),
2584
 
            b'success', (b'ok', (b'token1', )))
2585
 
        client.add_expected_call(
2586
 
            b'Repository.add_signature_text', (b'quack/', b'a token', b'rev1',
2587
 
                                               b'token1'),
2588
 
            b'success', (b'ok', ), None)
 
2495
            'Repository.lock_write', ('quack/', ''),
 
2496
            'success', ('ok', 'a token'))
 
2497
        client.add_expected_call(
 
2498
            'Repository.start_write_group', ('quack/', 'a token'),
 
2499
            'success', ('ok', ('token1', )))
 
2500
        client.add_expected_call(
 
2501
            'Repository.add_signature_text', ('quack/', 'a token', 'rev1',
 
2502
                'token1'),
 
2503
            'success', ('ok', ), None)
2589
2504
        repo.lock_write()
2590
2505
        repo.start_write_group()
2591
 
        self.assertIs(
2592
 
            None, repo.add_signature_text(b"rev1", b"every bloody emperor"))
 
2506
        self.assertIs(None,
 
2507
            repo.add_signature_text("rev1", "every bloody emperor"))
2593
2508
        self.assertEqual(
2594
2509
            ('call_with_body_bytes_expecting_body',
2595
 
             b'Repository.add_signature_text',
2596
 
                (b'quack/', b'a token', b'rev1', b'token1'),
2597
 
             b'every bloody emperor'),
 
2510
              'Repository.add_signature_text',
 
2511
                ('quack/', 'a token', 'rev1', 'token1'),
 
2512
              'every bloody emperor'),
2598
2513
            client._calls[-1])
2599
2514
 
2600
2515
 
2605
2520
        # setup a reponse with two revisions
2606
2521
        r1 = u'\u0e33'.encode('utf8')
2607
2522
        r2 = u'\u0dab'.encode('utf8')
2608
 
        lines = [b' '.join([r2, r1]), r1]
2609
 
        encoded_body = bz2.compress(b'\n'.join(lines))
 
2523
        lines = [' '.join([r2, r1]), r1]
 
2524
        encoded_body = bz2.compress('\n'.join(lines))
2610
2525
 
2611
2526
        transport_path = 'quack'
2612
2527
        repo, client = self.setup_fake_client_and_repository(transport_path)
2613
 
        client.add_success_response_with_body(encoded_body, b'ok')
2614
 
        client.add_success_response_with_body(encoded_body, b'ok')
 
2528
        client.add_success_response_with_body(encoded_body, 'ok')
 
2529
        client.add_success_response_with_body(encoded_body, 'ok')
2615
2530
        repo.lock_read()
2616
2531
        graph = repo.get_graph()
2617
2532
        parents = graph.get_parent_map([r2])
2623
2538
        self.assertEqual({r1: (NULL_REVISION,)}, parents)
2624
2539
        self.assertEqual(
2625
2540
            [('call_with_body_bytes_expecting_body',
2626
 
              b'Repository.get_parent_map', (b'quack/',
2627
 
                                             b'include-missing:', r2),
2628
 
              b'\n\n0')],
 
2541
              'Repository.get_parent_map', ('quack/', 'include-missing:', r2),
 
2542
              '\n\n0')],
2629
2543
            client._calls)
2630
2544
        repo.unlock()
2631
2545
        # now we call again, and it should use the second response.
2635
2549
        self.assertEqual({r1: (NULL_REVISION,)}, parents)
2636
2550
        self.assertEqual(
2637
2551
            [('call_with_body_bytes_expecting_body',
2638
 
              b'Repository.get_parent_map', (b'quack/',
2639
 
                                             b'include-missing:', r2),
2640
 
              b'\n\n0'),
 
2552
              'Repository.get_parent_map', ('quack/', 'include-missing:', r2),
 
2553
              '\n\n0'),
2641
2554
             ('call_with_body_bytes_expecting_body',
2642
 
              b'Repository.get_parent_map', (b'quack/',
2643
 
                                             b'include-missing:', r1),
2644
 
              b'\n\n0'),
2645
 
             ],
 
2555
              'Repository.get_parent_map', ('quack/', 'include-missing:', r1),
 
2556
              '\n\n0'),
 
2557
            ],
2646
2558
            client._calls)
2647
2559
        repo.unlock()
2648
2560
 
2649
2561
    def test_get_parent_map_reconnects_if_unknown_method(self):
2650
2562
        transport_path = 'quack'
2651
 
        rev_id = b'revision-id'
 
2563
        rev_id = 'revision-id'
2652
2564
        repo, client = self.setup_fake_client_and_repository(transport_path)
2653
 
        client.add_unknown_method_response(b'Repository.get_parent_map')
2654
 
        client.add_success_response_with_body(rev_id, b'ok')
 
2565
        client.add_unknown_method_response('Repository.get_parent_map')
 
2566
        client.add_success_response_with_body(rev_id, 'ok')
2655
2567
        self.assertFalse(client._medium._is_remote_before((1, 2)))
2656
2568
        parents = repo.get_parent_map([rev_id])
2657
2569
        self.assertEqual(
2658
2570
            [('call_with_body_bytes_expecting_body',
2659
 
              b'Repository.get_parent_map',
2660
 
              (b'quack/', b'include-missing:', rev_id), b'\n\n0'),
 
2571
              'Repository.get_parent_map',
 
2572
              ('quack/', 'include-missing:', rev_id), '\n\n0'),
2661
2573
             ('disconnect medium',),
2662
 
             ('call_expecting_body', b'Repository.get_revision_graph',
2663
 
              (b'quack/', b''))],
 
2574
             ('call_expecting_body', 'Repository.get_revision_graph',
 
2575
              ('quack/', ''))],
2664
2576
            client._calls)
2665
2577
        # The medium is now marked as being connected to an older server
2666
2578
        self.assertTrue(client._medium._is_remote_before((1, 2)))
2667
 
        self.assertEqual({rev_id: (b'null:',)}, parents)
 
2579
        self.assertEqual({rev_id: ('null:',)}, parents)
2668
2580
 
2669
2581
    def test_get_parent_map_fallback_parentless_node(self):
2670
2582
        """get_parent_map falls back to get_revision_graph on old servers.  The
2677
2589
 
2678
2590
        This is the test for https://bugs.launchpad.net/bzr/+bug/214894
2679
2591
        """
2680
 
        rev_id = b'revision-id'
 
2592
        rev_id = 'revision-id'
2681
2593
        transport_path = 'quack'
2682
2594
        repo, client = self.setup_fake_client_and_repository(transport_path)
2683
 
        client.add_success_response_with_body(rev_id, b'ok')
 
2595
        client.add_success_response_with_body(rev_id, 'ok')
2684
2596
        client._medium._remember_remote_is_before((1, 2))
2685
2597
        parents = repo.get_parent_map([rev_id])
2686
2598
        self.assertEqual(
2687
 
            [('call_expecting_body', b'Repository.get_revision_graph',
2688
 
              (b'quack/', b''))],
 
2599
            [('call_expecting_body', 'Repository.get_revision_graph',
 
2600
             ('quack/', ''))],
2689
2601
            client._calls)
2690
 
        self.assertEqual({rev_id: (b'null:',)}, parents)
 
2602
        self.assertEqual({rev_id: ('null:',)}, parents)
2691
2603
 
2692
2604
    def test_get_parent_map_unexpected_response(self):
2693
2605
        repo, client = self.setup_fake_client_and_repository('path')
2694
 
        client.add_success_response(b'something unexpected!')
 
2606
        client.add_success_response('something unexpected!')
2695
2607
        self.assertRaises(
2696
2608
            errors.UnexpectedSmartServerResponse,
2697
 
            repo.get_parent_map, [b'a-revision-id'])
 
2609
            repo.get_parent_map, ['a-revision-id'])
2698
2610
 
2699
2611
    def test_get_parent_map_negative_caches_missing_keys(self):
2700
2612
        self.setup_smart_server_with_call_log()
2704
2616
        self.addCleanup(repo.unlock)
2705
2617
        self.reset_smart_call_log()
2706
2618
        graph = repo.get_graph()
2707
 
        self.assertEqual(
2708
 
            {}, graph.get_parent_map([b'some-missing', b'other-missing']))
 
2619
        self.assertEqual({},
 
2620
            graph.get_parent_map(['some-missing', 'other-missing']))
2709
2621
        self.assertLength(1, self.hpss_calls)
2710
2622
        # No call if we repeat this
2711
2623
        self.reset_smart_call_log()
2712
2624
        graph = repo.get_graph()
2713
 
        self.assertEqual(
2714
 
            {}, graph.get_parent_map([b'some-missing', b'other-missing']))
 
2625
        self.assertEqual({},
 
2626
            graph.get_parent_map(['some-missing', 'other-missing']))
2715
2627
        self.assertLength(0, self.hpss_calls)
2716
2628
        # Asking for more unknown keys makes a request.
2717
2629
        self.reset_smart_call_log()
2718
2630
        graph = repo.get_graph()
2719
 
        self.assertEqual(
2720
 
            {}, graph.get_parent_map([b'some-missing', b'other-missing',
2721
 
                                     b'more-missing']))
 
2631
        self.assertEqual({},
 
2632
            graph.get_parent_map(['some-missing', 'other-missing',
 
2633
                'more-missing']))
2722
2634
        self.assertLength(1, self.hpss_calls)
2723
2635
 
2724
2636
    def disableExtraResults(self):
2730
2642
        # Make a branch with a single revision.
2731
2643
        builder = self.make_branch_builder('foo')
2732
2644
        builder.start_series()
2733
 
        builder.build_snapshot(None, [
2734
 
            ('add', ('', b'root-id', 'directory', ''))],
2735
 
            revision_id=b'first')
 
2645
        builder.build_snapshot('first', None, [
 
2646
            ('add', ('', 'root-id', 'directory', ''))])
2736
2647
        builder.finish_series()
2737
2648
        branch = builder.get_branch()
2738
2649
        repo = branch.repository
2743
2654
        self.addCleanup(repo.unlock)
2744
2655
        self.reset_smart_call_log()
2745
2656
        graph = repo.get_graph()
2746
 
        # Query for b'first' and b'null:'.  Because b'null:' is a parent of
 
2657
        # Query for 'first' and 'null:'.  Because 'null:' is a parent of
2747
2658
        # 'first' it will be a candidate for the stop_keys of subsequent
2748
 
        # requests, and because b'null:' was queried but not returned it will
2749
 
        # be cached as missing.
2750
 
        self.assertEqual({b'first': (b'null:',)},
2751
 
                         graph.get_parent_map([b'first', b'null:']))
 
2659
        # requests, and because 'null:' was queried but not returned it will be
 
2660
        # cached as missing.
 
2661
        self.assertEqual({'first': ('null:',)},
 
2662
            graph.get_parent_map(['first', 'null:']))
2752
2663
        # Now query for another key.  This request will pass along a recipe of
2753
2664
        # start and stop keys describing the already cached results, and this
2754
2665
        # recipe's revision count must be correct (or else it will trigger an
2755
2666
        # error from the server).
2756
 
        self.assertEqual({}, graph.get_parent_map([b'another-key']))
 
2667
        self.assertEqual({}, graph.get_parent_map(['another-key']))
2757
2668
        # This assertion guards against disableExtraResults silently failing to
2758
2669
        # work, thus invalidating the test.
2759
2670
        self.assertLength(2, self.hpss_calls)
2763
2674
        # ancestry.
2764
2675
        self.setup_smart_server_with_call_log()
2765
2676
        tree = self.make_branch_and_memory_tree('foo')
2766
 
        with tree.lock_write():
 
2677
        tree.lock_write()
 
2678
        try:
2767
2679
            builder = treebuilder.TreeBuilder()
2768
2680
            builder.start_tree(tree)
2769
2681
            builder.build([])
2770
2682
            builder.finish_tree()
2771
 
            tree.set_parent_ids([b'non-existant'],
2772
 
                                allow_leftmost_as_ghost=True)
 
2683
            tree.set_parent_ids(['non-existant'], allow_leftmost_as_ghost=True)
2773
2684
            rev_id = tree.commit('')
 
2685
        finally:
 
2686
            tree.unlock()
2774
2687
        tree.lock_read()
2775
2688
        self.addCleanup(tree.unlock)
2776
2689
        repo = tree.branch.repository
2779
2692
        repo.get_parent_map([rev_id])
2780
2693
        self.reset_smart_call_log()
2781
2694
        # Now asking for rev_id's ghost parent should not make calls
2782
 
        self.assertEqual({}, repo.get_parent_map([b'non-existant']))
 
2695
        self.assertEqual({}, repo.get_parent_map(['non-existant']))
2783
2696
        self.assertLength(0, self.hpss_calls)
2784
2697
 
2785
2698
    def test_exposes_get_cached_parent_map(self):
2788
2701
        """
2789
2702
        r1 = u'\u0e33'.encode('utf8')
2790
2703
        r2 = u'\u0dab'.encode('utf8')
2791
 
        lines = [b' '.join([r2, r1]), r1]
2792
 
        encoded_body = bz2.compress(b'\n'.join(lines))
 
2704
        lines = [' '.join([r2, r1]), r1]
 
2705
        encoded_body = bz2.compress('\n'.join(lines))
2793
2706
 
2794
2707
        transport_path = 'quack'
2795
2708
        repo, client = self.setup_fake_client_and_repository(transport_path)
2796
 
        client.add_success_response_with_body(encoded_body, b'ok')
 
2709
        client.add_success_response_with_body(encoded_body, 'ok')
2797
2710
        repo.lock_read()
2798
2711
        # get_cached_parent_map should *not* trigger an RPC
2799
2712
        self.assertEqual({}, repo.get_cached_parent_map([r1]))
2800
2713
        self.assertEqual([], client._calls)
2801
2714
        self.assertEqual({r2: (r1,)}, repo.get_parent_map([r2]))
2802
2715
        self.assertEqual({r1: (NULL_REVISION,)},
2803
 
                         repo.get_cached_parent_map([r1]))
 
2716
            repo.get_cached_parent_map([r1]))
2804
2717
        self.assertEqual(
2805
2718
            [('call_with_body_bytes_expecting_body',
2806
 
              b'Repository.get_parent_map', (b'quack/',
2807
 
                                             b'include-missing:', r2),
2808
 
              b'\n\n0')],
 
2719
              'Repository.get_parent_map', ('quack/', 'include-missing:', r2),
 
2720
              '\n\n0')],
2809
2721
            client._calls)
2810
2722
        repo.unlock()
2811
2723
 
2823
2735
        self.addCleanup(tree.unlock)
2824
2736
        graph = tree.branch.repository.get_graph()
2825
2737
        # This provides an opportunity for the missing rev-id to be cached.
2826
 
        self.assertEqual({}, graph.get_parent_map([b'rev1']))
2827
 
        tree.commit('message', rev_id=b'rev1')
 
2738
        self.assertEqual({}, graph.get_parent_map(['rev1']))
 
2739
        tree.commit('message', rev_id='rev1')
2828
2740
        graph = tree.branch.repository.get_graph()
2829
 
        self.assertEqual({b'rev1': (b'null:',)},
2830
 
                         graph.get_parent_map([b'rev1']))
 
2741
        self.assertEqual({'rev1': ('null:',)}, graph.get_parent_map(['rev1']))
2831
2742
 
2832
2743
 
2833
2744
class TestRepositoryGetRevisions(TestRemoteRepository):
2836
2747
        transport_path = 'quack'
2837
2748
        repo, client = self.setup_fake_client_and_repository(transport_path)
2838
2749
        client.add_success_response_with_body(
2839
 
            b'', b'ok', b'10')
 
2750
            '', 'ok', '10')
2840
2751
        self.assertRaises(errors.NoSuchRevision, repo.get_revisions,
2841
 
                          [b'somerev1', b'anotherrev2'])
 
2752
            ['somerev1', 'anotherrev2'])
2842
2753
        self.assertEqual(
2843
 
            [('call_with_body_bytes_expecting_body',
2844
 
              b'Repository.iter_revisions', (b'quack/', ),
2845
 
              b"somerev1\nanotherrev2")],
 
2754
            [('call_with_body_bytes_expecting_body', 'Repository.iter_revisions',
 
2755
             ('quack/', ), "somerev1\nanotherrev2")],
2846
2756
            client._calls)
2847
2757
 
2848
2758
    def test_hpss_get_single_revision(self):
2849
2759
        transport_path = 'quack'
2850
2760
        repo, client = self.setup_fake_client_and_repository(transport_path)
2851
 
        somerev1 = Revision(b"somerev1")
 
2761
        somerev1 = Revision("somerev1")
2852
2762
        somerev1.committer = "Joe Committer <joe@example.com>"
2853
2763
        somerev1.timestamp = 1321828927
2854
2764
        somerev1.timezone = -60
2855
 
        somerev1.inventory_sha1 = b"691b39be74c67b1212a75fcb19c433aaed903c2b"
 
2765
        somerev1.inventory_sha1 = "691b39be74c67b1212a75fcb19c433aaed903c2b"
2856
2766
        somerev1.message = "Message"
2857
 
        body = zlib.compress(b''.join(chk_bencode_serializer.write_revision_to_lines(
2858
 
            somerev1)))
 
2767
        body = zlib.compress(chk_bencode_serializer.write_revision_to_string(
 
2768
            somerev1))
2859
2769
        # Split up body into two bits to make sure the zlib compression object
2860
2770
        # gets data fed twice.
2861
2771
        client.add_success_response_with_body(
2862
 
            [body[:10], body[10:]], b'ok', b'10')
2863
 
        revs = repo.get_revisions([b'somerev1'])
 
2772
                [body[:10], body[10:]], 'ok', '10')
 
2773
        revs = repo.get_revisions(['somerev1'])
2864
2774
        self.assertEqual(revs, [somerev1])
2865
2775
        self.assertEqual(
2866
 
            [('call_with_body_bytes_expecting_body',
2867
 
              b'Repository.iter_revisions',
2868
 
              (b'quack/', ), b"somerev1")],
 
2776
            [('call_with_body_bytes_expecting_body', 'Repository.iter_revisions',
 
2777
             ('quack/', ), "somerev1")],
2869
2778
            client._calls)
2870
2779
 
2871
2780
 
2876
2785
        # traffic when calling it with this argument
2877
2786
        transport_path = 'empty'
2878
2787
        repo, client = self.setup_fake_client_and_repository(transport_path)
2879
 
        client.add_success_response(b'notused')
 
2788
        client.add_success_response('notused')
2880
2789
        # actual RemoteRepository.get_revision_graph is gone, but there's an
2881
2790
        # equivalent private method for testing
2882
2791
        result = repo._get_revision_graph(NULL_REVISION)
2887
2796
        # with none we want the entire graph
2888
2797
        r1 = u'\u0e33'.encode('utf8')
2889
2798
        r2 = u'\u0dab'.encode('utf8')
2890
 
        lines = [b' '.join([r2, r1]), r1]
2891
 
        encoded_body = b'\n'.join(lines)
 
2799
        lines = [' '.join([r2, r1]), r1]
 
2800
        encoded_body = '\n'.join(lines)
2892
2801
 
2893
2802
        transport_path = 'sinhala'
2894
2803
        repo, client = self.setup_fake_client_and_repository(transport_path)
2895
 
        client.add_success_response_with_body(encoded_body, b'ok')
 
2804
        client.add_success_response_with_body(encoded_body, 'ok')
2896
2805
        # actual RemoteRepository.get_revision_graph is gone, but there's an
2897
2806
        # equivalent private method for testing
2898
2807
        result = repo._get_revision_graph(None)
2899
2808
        self.assertEqual(
2900
 
            [('call_expecting_body', b'Repository.get_revision_graph',
2901
 
              (b'sinhala/', b''))],
 
2809
            [('call_expecting_body', 'Repository.get_revision_graph',
 
2810
             ('sinhala/', ''))],
2902
2811
            client._calls)
2903
2812
        self.assertEqual({r1: (), r2: (r1, )}, result)
2904
2813
 
2908
2817
        r11 = u'\u0e33'.encode('utf8')
2909
2818
        r12 = u'\xc9'.encode('utf8')
2910
2819
        r2 = u'\u0dab'.encode('utf8')
2911
 
        lines = [b' '.join([r2, r11, r12]), r11, r12]
2912
 
        encoded_body = b'\n'.join(lines)
 
2820
        lines = [' '.join([r2, r11, r12]), r11, r12]
 
2821
        encoded_body = '\n'.join(lines)
2913
2822
 
2914
2823
        transport_path = 'sinhala'
2915
2824
        repo, client = self.setup_fake_client_and_repository(transport_path)
2916
 
        client.add_success_response_with_body(encoded_body, b'ok')
 
2825
        client.add_success_response_with_body(encoded_body, 'ok')
2917
2826
        result = repo._get_revision_graph(r2)
2918
2827
        self.assertEqual(
2919
 
            [('call_expecting_body', b'Repository.get_revision_graph',
2920
 
              (b'sinhala/', r2))],
 
2828
            [('call_expecting_body', 'Repository.get_revision_graph',
 
2829
             ('sinhala/', r2))],
2921
2830
            client._calls)
2922
2831
        self.assertEqual({r11: (), r12: (), r2: (r11, r12), }, result)
2923
2832
 
2924
2833
    def test_no_such_revision(self):
2925
 
        revid = b'123'
 
2834
        revid = '123'
2926
2835
        transport_path = 'sinhala'
2927
2836
        repo, client = self.setup_fake_client_and_repository(transport_path)
2928
 
        client.add_error_response(b'nosuchrevision', revid)
 
2837
        client.add_error_response('nosuchrevision', revid)
2929
2838
        # also check that the right revision is reported in the error
2930
2839
        self.assertRaises(errors.NoSuchRevision,
2931
 
                          repo._get_revision_graph, revid)
 
2840
            repo._get_revision_graph, revid)
2932
2841
        self.assertEqual(
2933
 
            [('call_expecting_body', b'Repository.get_revision_graph',
2934
 
              (b'sinhala/', revid))],
 
2842
            [('call_expecting_body', 'Repository.get_revision_graph',
 
2843
             ('sinhala/', revid))],
2935
2844
            client._calls)
2936
2845
 
2937
2846
    def test_unexpected_error(self):
2938
2847
        revid = '123'
2939
2848
        transport_path = 'sinhala'
2940
2849
        repo, client = self.setup_fake_client_and_repository(transport_path)
2941
 
        client.add_error_response(b'AnUnexpectedError')
 
2850
        client.add_error_response('AnUnexpectedError')
2942
2851
        e = self.assertRaises(errors.UnknownErrorFromSmartServer,
2943
 
                              repo._get_revision_graph, revid)
2944
 
        self.assertEqual((b'AnUnexpectedError',), e.error_tuple)
 
2852
            repo._get_revision_graph, revid)
 
2853
        self.assertEqual(('AnUnexpectedError',), e.error_tuple)
2945
2854
 
2946
2855
 
2947
2856
class TestRepositoryGetRevIdForRevno(TestRemoteRepository):
2949
2858
    def test_ok(self):
2950
2859
        repo, client = self.setup_fake_client_and_repository('quack')
2951
2860
        client.add_expected_call(
2952
 
            b'Repository.get_rev_id_for_revno', (b'quack/',
2953
 
                                                 5, (42, b'rev-foo')),
2954
 
            b'success', (b'ok', b'rev-five'))
2955
 
        result = repo.get_rev_id_for_revno(5, (42, b'rev-foo'))
2956
 
        self.assertEqual((True, b'rev-five'), result)
 
2861
            'Repository.get_rev_id_for_revno', ('quack/', 5, (42, 'rev-foo')),
 
2862
            'success', ('ok', 'rev-five'))
 
2863
        result = repo.get_rev_id_for_revno(5, (42, 'rev-foo'))
 
2864
        self.assertEqual((True, 'rev-five'), result)
2957
2865
        self.assertFinished(client)
2958
2866
 
2959
2867
    def test_history_incomplete(self):
2960
2868
        repo, client = self.setup_fake_client_and_repository('quack')
2961
2869
        client.add_expected_call(
2962
 
            b'Repository.get_rev_id_for_revno', (b'quack/',
2963
 
                                                 5, (42, b'rev-foo')),
2964
 
            b'success', (b'history-incomplete', 10, b'rev-ten'))
2965
 
        result = repo.get_rev_id_for_revno(5, (42, b'rev-foo'))
2966
 
        self.assertEqual((False, (10, b'rev-ten')), result)
 
2870
            'Repository.get_rev_id_for_revno', ('quack/', 5, (42, 'rev-foo')),
 
2871
            'success', ('history-incomplete', 10, 'rev-ten'))
 
2872
        result = repo.get_rev_id_for_revno(5, (42, 'rev-foo'))
 
2873
        self.assertEqual((False, (10, 'rev-ten')), result)
2967
2874
        self.assertFinished(client)
2968
2875
 
2969
2876
    def test_history_incomplete_with_fallback(self):
2972
2879
        """
2973
2880
        # Make a repo with a fallback repo, both using a FakeClient.
2974
2881
        format = remote.response_tuple_to_repo_format(
2975
 
            (b'yes', b'no', b'yes', self.get_repo_format().network_name()))
 
2882
            ('yes', 'no', 'yes', self.get_repo_format().network_name()))
2976
2883
        repo, client = self.setup_fake_client_and_repository('quack')
2977
2884
        repo._format = format
2978
2885
        fallback_repo, ignored = self.setup_fake_client_and_repository(
2982
2889
        repo.add_fallback_repository(fallback_repo)
2983
2890
        # First the client should ask the primary repo
2984
2891
        client.add_expected_call(
2985
 
            b'Repository.get_rev_id_for_revno', (b'quack/',
2986
 
                                                 1, (42, b'rev-foo')),
2987
 
            b'success', (b'history-incomplete', 2, b'rev-two'))
 
2892
            'Repository.get_rev_id_for_revno', ('quack/', 1, (42, 'rev-foo')),
 
2893
            'success', ('history-incomplete', 2, 'rev-two'))
2988
2894
        # Then it should ask the fallback, using revno/revid from the
2989
2895
        # history-incomplete response as the known revno/revid.
2990
2896
        client.add_expected_call(
2991
 
            b'Repository.get_rev_id_for_revno', (
2992
 
                b'fallback/', 1, (2, b'rev-two')),
2993
 
            b'success', (b'ok', b'rev-one'))
2994
 
        result = repo.get_rev_id_for_revno(1, (42, b'rev-foo'))
2995
 
        self.assertEqual((True, b'rev-one'), result)
 
2897
            'Repository.get_rev_id_for_revno',('fallback/', 1, (2, 'rev-two')),
 
2898
            'success', ('ok', 'rev-one'))
 
2899
        result = repo.get_rev_id_for_revno(1, (42, 'rev-foo'))
 
2900
        self.assertEqual((True, 'rev-one'), result)
2996
2901
        self.assertFinished(client)
2997
2902
 
2998
2903
    def test_nosuchrevision(self):
3000
2905
        # remote repo.  The client translates that response to NoSuchRevision.
3001
2906
        repo, client = self.setup_fake_client_and_repository('quack')
3002
2907
        client.add_expected_call(
3003
 
            b'Repository.get_rev_id_for_revno', (b'quack/',
3004
 
                                                 5, (42, b'rev-foo')),
3005
 
            b'error', (b'nosuchrevision', b'rev-foo'))
 
2908
            'Repository.get_rev_id_for_revno', ('quack/', 5, (42, 'rev-foo')),
 
2909
            'error', ('nosuchrevision', 'rev-foo'))
3006
2910
        self.assertRaises(
3007
2911
            errors.NoSuchRevision,
3008
 
            repo.get_rev_id_for_revno, 5, (42, b'rev-foo'))
3009
 
        self.assertFinished(client)
3010
 
 
3011
 
    def test_outofbounds(self):
3012
 
        repo, client = self.setup_fake_client_and_repository('quack')
3013
 
        client.add_expected_call(
3014
 
            b'Repository.get_rev_id_for_revno', (b'quack/',
3015
 
                                                 43, (42, b'rev-foo')),
3016
 
            b'error', (b'revno-outofbounds', 43, 0, 42))
3017
 
        self.assertRaises(
3018
 
            errors.RevnoOutOfBounds,
3019
 
            repo.get_rev_id_for_revno, 43, (42, b'rev-foo'))
3020
 
        self.assertFinished(client)
3021
 
 
3022
 
    def test_outofbounds_old(self):
3023
 
        # Older versions of bzr didn't support RevnoOutOfBounds
3024
 
        repo, client = self.setup_fake_client_and_repository('quack')
3025
 
        client.add_expected_call(
3026
 
            b'Repository.get_rev_id_for_revno', (b'quack/',
3027
 
                                                 43, (42, b'rev-foo')),
3028
 
            b'error', (
3029
 
                b'error', b'ValueError',
3030
 
                b'requested revno (43) is later than given known revno (42)'))
3031
 
        self.assertRaises(
3032
 
            errors.RevnoOutOfBounds,
3033
 
            repo.get_rev_id_for_revno, 43, (42, b'rev-foo'))
 
2912
            repo.get_rev_id_for_revno, 5, (42, 'rev-foo'))
3034
2913
        self.assertFinished(client)
3035
2914
 
3036
2915
    def test_branch_fallback_locking(self):
3043
2922
        tree.lock_write()
3044
2923
        tree.add('')
3045
2924
        rev1 = tree.commit('First')
3046
 
        tree.commit('Second')
 
2925
        rev2 = tree.commit('Second')
3047
2926
        tree.unlock()
3048
2927
        branch = tree.branch
3049
2928
        self.assertFalse(branch.is_locked())
3050
2929
        self.reset_smart_call_log()
3051
 
        verb = b'Repository.get_rev_id_for_revno'
 
2930
        verb = 'Repository.get_rev_id_for_revno'
3052
2931
        self.disable_verb(verb)
3053
2932
        self.assertEqual(rev1, branch.get_rev_id(1))
3054
2933
        self.assertLength(1, [call for call in self.hpss_calls if
3061
2940
        # ('yes', ) for Repository.has_signature_for_revision_id -> 'True'.
3062
2941
        transport_path = 'quack'
3063
2942
        repo, client = self.setup_fake_client_and_repository(transport_path)
3064
 
        client.add_success_response(b'yes')
3065
 
        result = repo.has_signature_for_revision_id(b'A')
 
2943
        client.add_success_response('yes')
 
2944
        result = repo.has_signature_for_revision_id('A')
3066
2945
        self.assertEqual(
3067
 
            [('call', b'Repository.has_signature_for_revision_id',
3068
 
              (b'quack/', b'A'))],
 
2946
            [('call', 'Repository.has_signature_for_revision_id',
 
2947
              ('quack/', 'A'))],
3069
2948
            client._calls)
3070
2949
        self.assertEqual(True, result)
3071
2950
 
3073
2952
        # ('no', ) for Repository.has_signature_for_revision_id -> 'False'.
3074
2953
        transport_path = 'qwack'
3075
2954
        repo, client = self.setup_fake_client_and_repository(transport_path)
3076
 
        client.add_success_response(b'no')
3077
 
        result = repo.has_signature_for_revision_id(b'A')
 
2955
        client.add_success_response('no')
 
2956
        result = repo.has_signature_for_revision_id('A')
3078
2957
        self.assertEqual(
3079
 
            [('call', b'Repository.has_signature_for_revision_id',
3080
 
              (b'qwack/', b'A'))],
 
2958
            [('call', 'Repository.has_signature_for_revision_id',
 
2959
              ('qwack/', 'A'))],
3081
2960
            client._calls)
3082
2961
        self.assertEqual(False, result)
3083
2962
 
3087
2966
    def test_get_physical_lock_status_yes(self):
3088
2967
        transport_path = 'qwack'
3089
2968
        repo, client = self.setup_fake_client_and_repository(transport_path)
3090
 
        client.add_success_response(b'yes')
 
2969
        client.add_success_response('yes')
3091
2970
        result = repo.get_physical_lock_status()
3092
2971
        self.assertEqual(
3093
 
            [('call', b'Repository.get_physical_lock_status',
3094
 
              (b'qwack/', ))],
 
2972
            [('call', 'Repository.get_physical_lock_status',
 
2973
              ('qwack/', ))],
3095
2974
            client._calls)
3096
2975
        self.assertEqual(True, result)
3097
2976
 
3098
2977
    def test_get_physical_lock_status_no(self):
3099
2978
        transport_path = 'qwack'
3100
2979
        repo, client = self.setup_fake_client_and_repository(transport_path)
3101
 
        client.add_success_response(b'no')
 
2980
        client.add_success_response('no')
3102
2981
        result = repo.get_physical_lock_status()
3103
2982
        self.assertEqual(
3104
 
            [('call', b'Repository.get_physical_lock_status',
3105
 
              (b'qwack/', ))],
 
2983
            [('call', 'Repository.get_physical_lock_status',
 
2984
              ('qwack/', ))],
3106
2985
            client._calls)
3107
2986
        self.assertEqual(False, result)
3108
2987
 
3113
2992
        # ('yes', ) for Repository.is_shared -> 'True'.
3114
2993
        transport_path = 'quack'
3115
2994
        repo, client = self.setup_fake_client_and_repository(transport_path)
3116
 
        client.add_success_response(b'yes')
 
2995
        client.add_success_response('yes')
3117
2996
        result = repo.is_shared()
3118
2997
        self.assertEqual(
3119
 
            [('call', b'Repository.is_shared', (b'quack/',))],
 
2998
            [('call', 'Repository.is_shared', ('quack/',))],
3120
2999
            client._calls)
3121
3000
        self.assertEqual(True, result)
3122
3001
 
3124
3003
        # ('no', ) for Repository.is_shared -> 'False'.
3125
3004
        transport_path = 'qwack'
3126
3005
        repo, client = self.setup_fake_client_and_repository(transport_path)
3127
 
        client.add_success_response(b'no')
 
3006
        client.add_success_response('no')
3128
3007
        result = repo.is_shared()
3129
3008
        self.assertEqual(
3130
 
            [('call', b'Repository.is_shared', (b'qwack/',))],
 
3009
            [('call', 'Repository.is_shared', ('qwack/',))],
3131
3010
            client._calls)
3132
3011
        self.assertEqual(False, result)
3133
3012
 
3138
3017
        # ('yes', ) for Repository.make_working_trees -> 'True'.
3139
3018
        transport_path = 'quack'
3140
3019
        repo, client = self.setup_fake_client_and_repository(transport_path)
3141
 
        client.add_success_response(b'yes')
 
3020
        client.add_success_response('yes')
3142
3021
        result = repo.make_working_trees()
3143
3022
        self.assertEqual(
3144
 
            [('call', b'Repository.make_working_trees', (b'quack/',))],
 
3023
            [('call', 'Repository.make_working_trees', ('quack/',))],
3145
3024
            client._calls)
3146
3025
        self.assertEqual(True, result)
3147
3026
 
3149
3028
        # ('no', ) for Repository.make_working_trees -> 'False'.
3150
3029
        transport_path = 'qwack'
3151
3030
        repo, client = self.setup_fake_client_and_repository(transport_path)
3152
 
        client.add_success_response(b'no')
 
3031
        client.add_success_response('no')
3153
3032
        result = repo.make_working_trees()
3154
3033
        self.assertEqual(
3155
 
            [('call', b'Repository.make_working_trees', (b'qwack/',))],
 
3034
            [('call', 'Repository.make_working_trees', ('qwack/',))],
3156
3035
            client._calls)
3157
3036
        self.assertEqual(False, result)
3158
3037
 
3162
3041
    def test_lock_write(self):
3163
3042
        transport_path = 'quack'
3164
3043
        repo, client = self.setup_fake_client_and_repository(transport_path)
3165
 
        client.add_success_response(b'ok', b'a token')
 
3044
        client.add_success_response('ok', 'a token')
3166
3045
        token = repo.lock_write().repository_token
3167
3046
        self.assertEqual(
3168
 
            [('call', b'Repository.lock_write', (b'quack/', b''))],
 
3047
            [('call', 'Repository.lock_write', ('quack/', ''))],
3169
3048
            client._calls)
3170
 
        self.assertEqual(b'a token', token)
 
3049
        self.assertEqual('a token', token)
3171
3050
 
3172
3051
    def test_lock_write_already_locked(self):
3173
3052
        transport_path = 'quack'
3174
3053
        repo, client = self.setup_fake_client_and_repository(transport_path)
3175
 
        client.add_error_response(b'LockContention')
 
3054
        client.add_error_response('LockContention')
3176
3055
        self.assertRaises(errors.LockContention, repo.lock_write)
3177
3056
        self.assertEqual(
3178
 
            [('call', b'Repository.lock_write', (b'quack/', b''))],
 
3057
            [('call', 'Repository.lock_write', ('quack/', ''))],
3179
3058
            client._calls)
3180
3059
 
3181
3060
    def test_lock_write_unlockable(self):
3182
3061
        transport_path = 'quack'
3183
3062
        repo, client = self.setup_fake_client_and_repository(transport_path)
3184
 
        client.add_error_response(b'UnlockableTransport')
 
3063
        client.add_error_response('UnlockableTransport')
3185
3064
        self.assertRaises(errors.UnlockableTransport, repo.lock_write)
3186
3065
        self.assertEqual(
3187
 
            [('call', b'Repository.lock_write', (b'quack/', b''))],
 
3066
            [('call', 'Repository.lock_write', ('quack/', ''))],
3188
3067
            client._calls)
3189
3068
 
3190
3069
 
3194
3073
        transport_path = 'quack'
3195
3074
        repo, client = self.setup_fake_client_and_repository(transport_path)
3196
3075
        client.add_expected_call(
3197
 
            b'Repository.lock_write', (b'quack/', b''),
3198
 
            b'success', (b'ok', b'a token'))
 
3076
            'Repository.lock_write', ('quack/', ''),
 
3077
            'success', ('ok', 'a token'))
3199
3078
        client.add_expected_call(
3200
 
            b'Repository.start_write_group', (b'quack/', b'a token'),
3201
 
            b'success', (b'ok', (b'token1', )))
 
3079
            'Repository.start_write_group', ('quack/', 'a token'),
 
3080
            'success', ('ok', ('token1', )))
3202
3081
        repo.lock_write()
3203
3082
        repo.start_write_group()
3204
3083
 
3207
3086
        # groups. For those, fall back to the "real" repository.
3208
3087
        transport_path = 'quack'
3209
3088
        repo, client = self.setup_fake_client_and_repository(transport_path)
3210
 
 
3211
3089
        def stub_ensure_real():
3212
3090
            client._calls.append(('_ensure_real',))
3213
3091
            repo._real_repository = _StubRealPackRepository(client._calls)
3214
3092
        repo._ensure_real = stub_ensure_real
3215
3093
        client.add_expected_call(
3216
 
            b'Repository.lock_write', (b'quack/', b''),
3217
 
            b'success', (b'ok', b'a token'))
 
3094
            'Repository.lock_write', ('quack/', ''),
 
3095
            'success', ('ok', 'a token'))
3218
3096
        client.add_expected_call(
3219
 
            b'Repository.start_write_group', (b'quack/', b'a token'),
3220
 
            b'error', (b'UnsuspendableWriteGroup',))
 
3097
            'Repository.start_write_group', ('quack/', 'a token'),
 
3098
            'error', ('UnsuspendableWriteGroup',))
3221
3099
        repo.lock_write()
3222
3100
        repo.start_write_group()
3223
 
        self.assertEqual(client._calls[-2:], [
 
3101
        self.assertEqual(client._calls[-2:], [ 
3224
3102
            ('_ensure_real',),
3225
3103
            ('start_write_group',)])
3226
3104
 
3228
3106
        transport_path = 'quack'
3229
3107
        repo, client = self.setup_fake_client_and_repository(transport_path)
3230
3108
        client.add_expected_call(
3231
 
            b'Repository.lock_write', (b'quack/', b''),
3232
 
            b'success', (b'ok', b'a token'))
3233
 
        client.add_expected_call(
3234
 
            b'Repository.start_write_group', (b'quack/', b'a token'),
3235
 
            b'success', (b'ok', [b'token1']))
3236
 
        client.add_expected_call(
3237
 
            b'Repository.commit_write_group', (b'quack/',
3238
 
                                               b'a token', [b'token1']),
3239
 
            b'success', (b'ok',))
 
3109
            'Repository.lock_write', ('quack/', ''),
 
3110
            'success', ('ok', 'a token'))
 
3111
        client.add_expected_call(
 
3112
            'Repository.start_write_group', ('quack/', 'a token'),
 
3113
            'success', ('ok', ['token1']))
 
3114
        client.add_expected_call(
 
3115
            'Repository.commit_write_group', ('quack/', 'a token', ['token1']),
 
3116
            'success', ('ok',))
3240
3117
        repo.lock_write()
3241
3118
        repo.start_write_group()
3242
3119
        repo.commit_write_group()
3245
3122
        transport_path = 'quack'
3246
3123
        repo, client = self.setup_fake_client_and_repository(transport_path)
3247
3124
        client.add_expected_call(
3248
 
            b'Repository.lock_write', (b'quack/', b''),
3249
 
            b'success', (b'ok', b'a token'))
3250
 
        client.add_expected_call(
3251
 
            b'Repository.start_write_group', (b'quack/', b'a token'),
3252
 
            b'success', (b'ok', [b'token1']))
3253
 
        client.add_expected_call(
3254
 
            b'Repository.abort_write_group', (b'quack/',
3255
 
                                              b'a token', [b'token1']),
3256
 
            b'success', (b'ok',))
 
3125
            'Repository.lock_write', ('quack/', ''),
 
3126
            'success', ('ok', 'a token'))
 
3127
        client.add_expected_call(
 
3128
            'Repository.start_write_group', ('quack/', 'a token'),
 
3129
            'success', ('ok', ['token1']))
 
3130
        client.add_expected_call(
 
3131
            'Repository.abort_write_group', ('quack/', 'a token', ['token1']),
 
3132
            'success', ('ok',))
3257
3133
        repo.lock_write()
3258
3134
        repo.start_write_group()
3259
3135
        repo.abort_write_group(False)
3267
3143
        transport_path = 'quack'
3268
3144
        repo, client = self.setup_fake_client_and_repository(transport_path)
3269
3145
        client.add_expected_call(
3270
 
            b'Repository.lock_write', (b'quack/', b''),
3271
 
            b'success', (b'ok', b'a token'))
 
3146
            'Repository.lock_write', ('quack/', ''),
 
3147
            'success', ('ok', 'a token'))
3272
3148
        client.add_expected_call(
3273
 
            b'Repository.check_write_group', (b'quack/',
3274
 
                                              b'a token', [b'token1']),
3275
 
            b'success', (b'ok',))
 
3149
            'Repository.check_write_group', ('quack/', 'a token', ['token1']),
 
3150
            'success', ('ok',))
3276
3151
        repo.lock_write()
3277
3152
        repo.resume_write_group(['token1'])
3278
3153
 
3283
3158
        self.setup_smart_server_with_call_log()
3284
3159
        repo = self.make_repository('.')
3285
3160
        self.reset_smart_call_log()
3286
 
        verb = b'Repository.set_make_working_trees'
 
3161
        verb = 'Repository.set_make_working_trees'
3287
3162
        self.disable_verb(verb)
3288
3163
        repo.set_make_working_trees(True)
3289
3164
        call_count = len([call for call in self.hpss_calls if
3290
 
                          call.call.method == verb])
 
3165
            call.call.method == verb])
3291
3166
        self.assertEqual(1, call_count)
3292
3167
 
3293
3168
    def test_current(self):
3294
3169
        transport_path = 'quack'
3295
3170
        repo, client = self.setup_fake_client_and_repository(transport_path)
3296
3171
        client.add_expected_call(
3297
 
            b'Repository.set_make_working_trees', (b'quack/', b'True'),
3298
 
            b'success', (b'ok',))
 
3172
            'Repository.set_make_working_trees', ('quack/', 'True'),
 
3173
            'success', ('ok',))
3299
3174
        client.add_expected_call(
3300
 
            b'Repository.set_make_working_trees', (b'quack/', b'False'),
3301
 
            b'success', (b'ok',))
 
3175
            'Repository.set_make_working_trees', ('quack/', 'False'),
 
3176
            'success', ('ok',))
3302
3177
        repo.set_make_working_trees(True)
3303
3178
        repo.set_make_working_trees(False)
3304
3179
 
3308
3183
    def test_unlock(self):
3309
3184
        transport_path = 'quack'
3310
3185
        repo, client = self.setup_fake_client_and_repository(transport_path)
3311
 
        client.add_success_response(b'ok', b'a token')
3312
 
        client.add_success_response(b'ok')
 
3186
        client.add_success_response('ok', 'a token')
 
3187
        client.add_success_response('ok')
3313
3188
        repo.lock_write()
3314
3189
        repo.unlock()
3315
3190
        self.assertEqual(
3316
 
            [('call', b'Repository.lock_write', (b'quack/', b'')),
3317
 
             ('call', b'Repository.unlock', (b'quack/', b'a token'))],
 
3191
            [('call', 'Repository.lock_write', ('quack/', '')),
 
3192
             ('call', 'Repository.unlock', ('quack/', 'a token'))],
3318
3193
            client._calls)
3319
3194
 
3320
3195
    def test_unlock_wrong_token(self):
3321
3196
        # If somehow the token is wrong, unlock will raise TokenMismatch.
3322
3197
        transport_path = 'quack'
3323
3198
        repo, client = self.setup_fake_client_and_repository(transport_path)
3324
 
        client.add_success_response(b'ok', b'a token')
3325
 
        client.add_error_response(b'TokenMismatch')
 
3199
        client.add_success_response('ok', 'a token')
 
3200
        client.add_error_response('TokenMismatch')
3326
3201
        repo.lock_write()
3327
3202
        self.assertRaises(errors.TokenMismatch, repo.unlock)
3328
3203
 
3348
3223
        transport_path = 'quack'
3349
3224
        repo, client = self.setup_fake_client_and_repository(transport_path)
3350
3225
        client.add_expected_call(
3351
 
            b'Repository.iter_files_bytes', (b'quack/', ),
3352
 
            b'success', (b'ok',), iter([b"ok\x000", b"\n", zlib.compress(b"mydata" * 10)]))
3353
 
        for (identifier, byte_stream) in repo.iter_files_bytes([(b"somefile",
3354
 
                                                                 b"somerev", b"myid")]):
3355
 
            self.assertEqual(b"myid", identifier)
3356
 
            self.assertEqual(b"".join(byte_stream), b"mydata" * 10)
 
3226
            'Repository.iter_files_bytes', ('quack/', ),
 
3227
            'success', ('ok',), iter(["ok\x000", "\n", zlib.compress("mydata" * 10)]))
 
3228
        for (identifier, byte_stream) in repo.iter_files_bytes([("somefile",
 
3229
                "somerev", "myid")]):
 
3230
            self.assertEqual("myid", identifier)
 
3231
            self.assertEqual("".join(byte_stream), "mydata" * 10)
3357
3232
 
3358
3233
    def test_missing(self):
3359
3234
        transport_path = 'quack'
3360
3235
        repo, client = self.setup_fake_client_and_repository(transport_path)
3361
3236
        client.add_expected_call(
3362
 
            b'Repository.iter_files_bytes',
3363
 
            (b'quack/', ),
3364
 
            b'error', (b'RevisionNotPresent', b'somefile', b'somerev'),
3365
 
            iter([b"absent\0somefile\0somerev\n"]))
 
3237
            'Repository.iter_files_bytes',
 
3238
                ('quack/', ),
 
3239
            'error', ('RevisionNotPresent', 'somefile', 'somerev'),
 
3240
            iter(["absent\0somefile\0somerev\n"]))
3366
3241
        self.assertRaises(errors.RevisionNotPresent, list,
3367
 
                          repo.iter_files_bytes(
3368
 
                              [(b"somefile", b"somerev", b"myid")]))
 
3242
                repo.iter_files_bytes(
 
3243
                [("somefile", "somerev", "myid")]))
3369
3244
 
3370
3245
 
3371
3246
class TestRepositoryInsertStreamBase(TestRemoteRepository):
3372
3247
    """Base class for Repository.insert_stream and .insert_stream_1.19
3373
3248
    tests.
3374
3249
    """
3375
 
 
 
3250
    
3376
3251
    def checkInsertEmptyStream(self, repo, client):
3377
3252
        """Insert an empty stream, checking the result.
3378
3253
 
3396
3271
 
3397
3272
    def setUp(self):
3398
3273
        super(TestRepositoryInsertStream, self).setUp()
3399
 
        self.disable_verb(b'Repository.insert_stream_1.19')
 
3274
        self.disable_verb('Repository.insert_stream_1.19')
3400
3275
 
3401
3276
    def test_unlocked_repo(self):
3402
3277
        transport_path = 'quack'
3403
3278
        repo, client = self.setup_fake_client_and_repository(transport_path)
3404
3279
        client.add_expected_call(
3405
 
            b'Repository.insert_stream_1.19', (b'quack/', b''),
3406
 
            b'unknown', (b'Repository.insert_stream_1.19',))
3407
 
        client.add_expected_call(
3408
 
            b'Repository.insert_stream', (b'quack/', b''),
3409
 
            b'success', (b'ok',))
3410
 
        client.add_expected_call(
3411
 
            b'Repository.insert_stream', (b'quack/', b''),
3412
 
            b'success', (b'ok',))
 
3280
            'Repository.insert_stream_1.19', ('quack/', ''),
 
3281
            'unknown', ('Repository.insert_stream_1.19',))
 
3282
        client.add_expected_call(
 
3283
            'Repository.insert_stream', ('quack/', ''),
 
3284
            'success', ('ok',))
 
3285
        client.add_expected_call(
 
3286
            'Repository.insert_stream', ('quack/', ''),
 
3287
            'success', ('ok',))
3413
3288
        self.checkInsertEmptyStream(repo, client)
3414
3289
 
3415
3290
    def test_locked_repo_with_no_lock_token(self):
3416
3291
        transport_path = 'quack'
3417
3292
        repo, client = self.setup_fake_client_and_repository(transport_path)
3418
3293
        client.add_expected_call(
3419
 
            b'Repository.lock_write', (b'quack/', b''),
3420
 
            b'success', (b'ok', b''))
3421
 
        client.add_expected_call(
3422
 
            b'Repository.insert_stream_1.19', (b'quack/', b''),
3423
 
            b'unknown', (b'Repository.insert_stream_1.19',))
3424
 
        client.add_expected_call(
3425
 
            b'Repository.insert_stream', (b'quack/', b''),
3426
 
            b'success', (b'ok',))
3427
 
        client.add_expected_call(
3428
 
            b'Repository.insert_stream', (b'quack/', b''),
3429
 
            b'success', (b'ok',))
 
3294
            'Repository.lock_write', ('quack/', ''),
 
3295
            'success', ('ok', ''))
 
3296
        client.add_expected_call(
 
3297
            'Repository.insert_stream_1.19', ('quack/', ''),
 
3298
            'unknown', ('Repository.insert_stream_1.19',))
 
3299
        client.add_expected_call(
 
3300
            'Repository.insert_stream', ('quack/', ''),
 
3301
            'success', ('ok',))
 
3302
        client.add_expected_call(
 
3303
            'Repository.insert_stream', ('quack/', ''),
 
3304
            'success', ('ok',))
3430
3305
        repo.lock_write()
3431
3306
        self.checkInsertEmptyStream(repo, client)
3432
3307
 
3434
3309
        transport_path = 'quack'
3435
3310
        repo, client = self.setup_fake_client_and_repository(transport_path)
3436
3311
        client.add_expected_call(
3437
 
            b'Repository.lock_write', (b'quack/', b''),
3438
 
            b'success', (b'ok', b'a token'))
3439
 
        client.add_expected_call(
3440
 
            b'Repository.insert_stream_1.19', (b'quack/', b'', b'a token'),
3441
 
            b'unknown', (b'Repository.insert_stream_1.19',))
3442
 
        client.add_expected_call(
3443
 
            b'Repository.insert_stream_locked', (b'quack/', b'', b'a token'),
3444
 
            b'success', (b'ok',))
3445
 
        client.add_expected_call(
3446
 
            b'Repository.insert_stream_locked', (b'quack/', b'', b'a token'),
3447
 
            b'success', (b'ok',))
 
3312
            'Repository.lock_write', ('quack/', ''),
 
3313
            'success', ('ok', 'a token'))
 
3314
        client.add_expected_call(
 
3315
            'Repository.insert_stream_1.19', ('quack/', '', 'a token'),
 
3316
            'unknown', ('Repository.insert_stream_1.19',))
 
3317
        client.add_expected_call(
 
3318
            'Repository.insert_stream_locked', ('quack/', '', 'a token'),
 
3319
            'success', ('ok',))
 
3320
        client.add_expected_call(
 
3321
            'Repository.insert_stream_locked', ('quack/', '', 'a token'),
 
3322
            'success', ('ok',))
3448
3323
        repo.lock_write()
3449
3324
        self.checkInsertEmptyStream(repo, client)
3450
3325
 
3457
3332
        transport_path = 'quack'
3458
3333
        repo, client = self.setup_fake_client_and_repository(transport_path)
3459
3334
        client.add_expected_call(
3460
 
            b'Repository.insert_stream_1.19', (b'quack/', b''),
3461
 
            b'unknown', (b'Repository.insert_stream_1.19',))
3462
 
        client.add_expected_call(
3463
 
            b'Repository.insert_stream', (b'quack/', b''),
3464
 
            b'success', (b'ok',))
3465
 
        client.add_expected_call(
3466
 
            b'Repository.insert_stream', (b'quack/', b''),
3467
 
            b'success', (b'ok',))
 
3335
            'Repository.insert_stream_1.19', ('quack/', ''),
 
3336
            'unknown', ('Repository.insert_stream_1.19',))
 
3337
        client.add_expected_call(
 
3338
            'Repository.insert_stream', ('quack/', ''),
 
3339
            'success', ('ok',))
 
3340
        client.add_expected_call(
 
3341
            'Repository.insert_stream', ('quack/', ''),
 
3342
            'success', ('ok',))
3468
3343
        # Create a fake real repository for insert_stream to fall back on, so
3469
3344
        # that we can directly see the records the RemoteSink passes to the
3470
3345
        # real sink.
3471
 
 
3472
3346
        class FakeRealSink:
3473
3347
            def __init__(self):
3474
3348
                self.records = []
3475
 
 
3476
3349
            def insert_stream(self, stream, src_format, resume_tokens):
3477
3350
                for substream_kind, substream in stream:
3478
3351
                    self.records.append(
3479
3352
                        (substream_kind, [record.key for record in substream]))
3480
 
                return [b'fake tokens'], [b'fake missing keys']
 
3353
                return ['fake tokens'], ['fake missing keys']
3481
3354
        fake_real_sink = FakeRealSink()
3482
 
 
3483
3355
        class FakeRealRepository:
3484
3356
            def _get_sink(self):
3485
3357
                return fake_real_sink
3486
 
 
3487
3358
            def is_in_write_group(self):
3488
3359
                return False
3489
 
 
3490
3360
            def refresh_data(self):
3491
3361
                return True
3492
3362
        repo._real_repository = FakeRealRepository()
3497
3367
        # Every record from the first inventory delta should have been sent to
3498
3368
        # the VFS sink.
3499
3369
        expected_records = [
3500
 
            ('inventory-deltas', [(b'rev2',), (b'rev3',)]),
3501
 
            ('texts', [(b'some-rev', b'some-file')])]
 
3370
            ('inventory-deltas', [('rev2',), ('rev3',)]),
 
3371
            ('texts', [('some-rev', 'some-file')])]
3502
3372
        self.assertEqual(expected_records, fake_real_sink.records)
3503
3373
        # The return values from the real sink's insert_stream are propagated
3504
3374
        # back to the original caller.
3505
 
        self.assertEqual([b'fake tokens'], resume_tokens)
3506
 
        self.assertEqual([b'fake missing keys'], missing_keys)
 
3375
        self.assertEqual(['fake tokens'], resume_tokens)
 
3376
        self.assertEqual(['fake missing keys'], missing_keys)
3507
3377
        self.assertFinished(client)
3508
3378
 
3509
3379
    def make_stream_with_inv_deltas(self, fmt):
3517
3387
           * texts substream: (some-rev, some-file)
3518
3388
        """
3519
3389
        # Define a stream using generators so that it isn't rewindable.
3520
 
        inv = inventory.Inventory(revision_id=b'rev1')
3521
 
        inv.root.revision = b'rev1'
3522
 
 
 
3390
        inv = inventory.Inventory(revision_id='rev1')
 
3391
        inv.root.revision = 'rev1'
3523
3392
        def stream_with_inv_delta():
3524
3393
            yield ('inventories', inventories_substream())
3525
3394
            yield ('inventory-deltas', inventory_delta_substream())
3526
3395
            yield ('texts', [
3527
3396
                versionedfile.FulltextContentFactory(
3528
 
                    (b'some-rev', b'some-file'), (), None, b'content')])
3529
 
 
 
3397
                    ('some-rev', 'some-file'), (), None, 'content')])
3530
3398
        def inventories_substream():
3531
3399
            # An empty inventory fulltext.  This will be streamed normally.
3532
 
            chunks = fmt._serializer.write_inventory_to_lines(inv)
3533
 
            yield versionedfile.ChunkedContentFactory(
3534
 
                (b'rev1',), (), None, chunks, chunks_are_lines=True)
3535
 
 
 
3400
            text = fmt._serializer.write_inventory_to_string(inv)
 
3401
            yield versionedfile.FulltextContentFactory(
 
3402
                ('rev1',), (), None, text)
3536
3403
        def inventory_delta_substream():
3537
3404
            # An inventory delta.  This can't be streamed via this verb, so it
3538
3405
            # will trigger a fallback to VFS insert_stream.
3539
3406
            entry = inv.make_entry(
3540
 
                'directory', 'newdir', inv.root.file_id, b'newdir-id')
3541
 
            entry.revision = b'ghost'
3542
 
            delta = [(None, 'newdir', b'newdir-id', entry)]
 
3407
                'directory', 'newdir', inv.root.file_id, 'newdir-id')
 
3408
            entry.revision = 'ghost'
 
3409
            delta = [(None, 'newdir', 'newdir-id', entry)]
3543
3410
            serializer = inventory_delta.InventoryDeltaSerializer(
3544
3411
                versioned_root=True, tree_references=False)
3545
 
            lines = serializer.delta_to_lines(b'rev1', b'rev2', delta)
 
3412
            lines = serializer.delta_to_lines('rev1', 'rev2', delta)
3546
3413
            yield versionedfile.ChunkedContentFactory(
3547
 
                (b'rev2',), ((b'rev1',)), None, lines)
 
3414
                ('rev2',), (('rev1',)), None, lines)
3548
3415
            # Another delta.
3549
 
            lines = serializer.delta_to_lines(b'rev1', b'rev3', delta)
 
3416
            lines = serializer.delta_to_lines('rev1', 'rev3', delta)
3550
3417
            yield versionedfile.ChunkedContentFactory(
3551
 
                (b'rev3',), ((b'rev1',)), None, lines)
 
3418
                ('rev3',), (('rev1',)), None, lines)
3552
3419
        return stream_with_inv_delta()
3553
3420
 
3554
3421
 
3558
3425
        transport_path = 'quack'
3559
3426
        repo, client = self.setup_fake_client_and_repository(transport_path)
3560
3427
        client.add_expected_call(
3561
 
            b'Repository.insert_stream_1.19', (b'quack/', b''),
3562
 
            b'success', (b'ok',))
 
3428
            'Repository.insert_stream_1.19', ('quack/', ''),
 
3429
            'success', ('ok',))
3563
3430
        client.add_expected_call(
3564
 
            b'Repository.insert_stream_1.19', (b'quack/', b''),
3565
 
            b'success', (b'ok',))
 
3431
            'Repository.insert_stream_1.19', ('quack/', ''),
 
3432
            'success', ('ok',))
3566
3433
        self.checkInsertEmptyStream(repo, client)
3567
3434
 
3568
3435
    def test_locked_repo_with_no_lock_token(self):
3569
3436
        transport_path = 'quack'
3570
3437
        repo, client = self.setup_fake_client_and_repository(transport_path)
3571
3438
        client.add_expected_call(
3572
 
            b'Repository.lock_write', (b'quack/', b''),
3573
 
            b'success', (b'ok', b''))
3574
 
        client.add_expected_call(
3575
 
            b'Repository.insert_stream_1.19', (b'quack/', b''),
3576
 
            b'success', (b'ok',))
3577
 
        client.add_expected_call(
3578
 
            b'Repository.insert_stream_1.19', (b'quack/', b''),
3579
 
            b'success', (b'ok',))
 
3439
            'Repository.lock_write', ('quack/', ''),
 
3440
            'success', ('ok', ''))
 
3441
        client.add_expected_call(
 
3442
            'Repository.insert_stream_1.19', ('quack/', ''),
 
3443
            'success', ('ok',))
 
3444
        client.add_expected_call(
 
3445
            'Repository.insert_stream_1.19', ('quack/', ''),
 
3446
            'success', ('ok',))
3580
3447
        repo.lock_write()
3581
3448
        self.checkInsertEmptyStream(repo, client)
3582
3449
 
3584
3451
        transport_path = 'quack'
3585
3452
        repo, client = self.setup_fake_client_and_repository(transport_path)
3586
3453
        client.add_expected_call(
3587
 
            b'Repository.lock_write', (b'quack/', b''),
3588
 
            b'success', (b'ok', b'a token'))
3589
 
        client.add_expected_call(
3590
 
            b'Repository.insert_stream_1.19', (b'quack/', b'', b'a token'),
3591
 
            b'success', (b'ok',))
3592
 
        client.add_expected_call(
3593
 
            b'Repository.insert_stream_1.19', (b'quack/', b'', b'a token'),
3594
 
            b'success', (b'ok',))
 
3454
            'Repository.lock_write', ('quack/', ''),
 
3455
            'success', ('ok', 'a token'))
 
3456
        client.add_expected_call(
 
3457
            'Repository.insert_stream_1.19', ('quack/', '', 'a token'),
 
3458
            'success', ('ok',))
 
3459
        client.add_expected_call(
 
3460
            'Repository.insert_stream_1.19', ('quack/', '', 'a token'),
 
3461
            'success', ('ok',))
3595
3462
        repo.lock_write()
3596
3463
        self.checkInsertEmptyStream(repo, client)
3597
3464
 
3599
3466
class TestRepositoryTarball(TestRemoteRepository):
3600
3467
 
3601
3468
    # This is a canned tarball reponse we can validate against
3602
 
    tarball_content = base64.b64decode(
 
3469
    tarball_content = (
3603
3470
        'QlpoOTFBWSZTWdGkj3wAAWF/k8aQACBIB//A9+8cIX/v33AACEAYABAECEACNz'
3604
3471
        'JqsgJJFPTSnk1A3qh6mTQAAAANPUHkagkSTEkaA09QaNAAAGgAAAcwCYCZGAEY'
3605
3472
        'mJhMJghpiaYBUkKammSHqNMZQ0NABkNAeo0AGneAevnlwQoGzEzNVzaYxp/1Uk'
3612
3479
        'QplPKp2nqBWAfwBGaOwVrz3y1T+UZZNismXHsb2Jq18T+VaD9k4P8DqE3g70qV'
3613
3480
        'JLurpnDI6VS5oqDDPVbtVjMxMxMg4rzQVipn2Bv1fVNK0iq3Gl0hhnnHKm/egy'
3614
3481
        'nWQ7QH/F3JFOFCQ0aSPfA='
3615
 
        )
 
3482
        ).decode('base64')
3616
3483
 
3617
3484
    def test_repository_tarball(self):
3618
3485
        # Test that Repository.tarball generates the right operations
3619
3486
        transport_path = 'repo'
3620
 
        expected_calls = [('call_expecting_body', b'Repository.tarball',
3621
 
                           (b'repo/', b'bz2',),),
3622
 
                          ]
 
3487
        expected_calls = [('call_expecting_body', 'Repository.tarball',
 
3488
                           ('repo/', 'bz2',),),
 
3489
            ]
3623
3490
        repo, client = self.setup_fake_client_and_repository(transport_path)
3624
 
        client.add_success_response_with_body(self.tarball_content, b'ok')
 
3491
        client.add_success_response_with_body(self.tarball_content, 'ok')
3625
3492
        # Now actually ask for the tarball
3626
3493
        tarball_file = repo._get_tarball('bz2')
3627
3494
        try:
3685
3552
        transport_path = 'quack'
3686
3553
        repo, client = self.setup_fake_client_and_repository(transport_path)
3687
3554
        client.add_expected_call(
3688
 
            b'PackRepository.autopack', (b'quack/',), b'success', (b'ok',))
 
3555
            'PackRepository.autopack', ('quack/',), 'success', ('ok',))
3689
3556
        repo.autopack()
3690
3557
        self.assertFinished(client)
3691
3558
 
3696
3563
        transport_path = 'quack'
3697
3564
        repo, client = self.setup_fake_client_and_repository(transport_path)
3698
3565
        client.add_expected_call(
3699
 
            b'PackRepository.autopack', (b'quack/',),
3700
 
            b'success', (b'ok',))
 
3566
            'PackRepository.autopack', ('quack/',),
 
3567
            'success', ('ok',))
3701
3568
        repo._real_repository = _StubRealPackRepository(client._calls)
3702
3569
        repo.autopack()
3703
3570
        self.assertEqual(
3704
 
            [('call', b'PackRepository.autopack', (b'quack/',)),
 
3571
            [('call', 'PackRepository.autopack', ('quack/',)),
3705
3572
             ('pack collection reload_pack_names',)],
3706
3573
            client._calls)
3707
3574
 
3711
3578
        """
3712
3579
        transport_path = 'quack'
3713
3580
        repo, client = self.setup_fake_client_and_repository(transport_path)
3714
 
        client.add_unknown_method_response(b'PackRepository.autopack')
3715
 
 
 
3581
        client.add_unknown_method_response('PackRepository.autopack')
3716
3582
        def stub_ensure_real():
3717
3583
            client._calls.append(('_ensure_real',))
3718
3584
            repo._real_repository = _StubRealPackRepository(client._calls)
3719
3585
        repo._ensure_real = stub_ensure_real
3720
3586
        repo.autopack()
3721
3587
        self.assertEqual(
3722
 
            [('call', b'PackRepository.autopack', (b'quack/',)),
 
3588
            [('call', 'PackRepository.autopack', ('quack/',)),
3723
3589
             ('_ensure_real',),
3724
3590
             ('pack collection autopack',)],
3725
3591
            client._calls)
3729
3595
        transport_path = 'quack'
3730
3596
        repo, client = self.setup_fake_client_and_repository(transport_path)
3731
3597
        client.add_expected_call(
3732
 
            b'PackRepository.autopack', (b'quack/',),
3733
 
            b'error', (b'MemoryError',))
 
3598
            'PackRepository.autopack', ('quack/',),
 
3599
            'error', ('MemoryError',))
3734
3600
        err = self.assertRaises(errors.BzrError, repo.autopack)
3735
3601
        self.assertContainsRe(str(err), "^remote server out of mem")
3736
3602
 
3737
3603
 
3738
3604
class TestErrorTranslationBase(tests.TestCaseWithMemoryTransport):
3739
 
    """Base class for unit tests for breezy.bzr.remote._translate_error."""
 
3605
    """Base class for unit tests for brzlib.remote._translate_error."""
3740
3606
 
3741
3607
    def translateTuple(self, error_tuple, **context):
3742
3608
        """Call _translate_error with an ErrorFromSmartServer built from the
3762
3628
        """
3763
3629
        try:
3764
3630
            raise error_object
3765
 
        except errors.ErrorFromSmartServer as server_error:
 
3631
        except errors.ErrorFromSmartServer, server_error:
3766
3632
            translated_error = self.assertRaises(
3767
3633
                errors.BzrError, remote._translate_error, server_error,
3768
3634
                **context)
3770
3636
 
3771
3637
 
3772
3638
class TestErrorTranslationSuccess(TestErrorTranslationBase):
3773
 
    """Unit tests for breezy.bzr.remote._translate_error.
 
3639
    """Unit tests for brzlib.remote._translate_error.
3774
3640
 
3775
3641
    Given an ErrorFromSmartServer (which has an error tuple from a smart
3776
3642
    server) and some context, _translate_error raises more specific errors from
3777
 
    breezy.errors.
 
3643
    brzlib.errors.
3778
3644
 
3779
3645
    This test case covers the cases where _translate_error succeeds in
3780
3646
    translating an ErrorFromSmartServer to something better.  See
3783
3649
 
3784
3650
    def test_NoSuchRevision(self):
3785
3651
        branch = self.make_branch('')
3786
 
        revid = b'revid'
 
3652
        revid = 'revid'
3787
3653
        translated_error = self.translateTuple(
3788
 
            (b'NoSuchRevision', revid), branch=branch)
 
3654
            ('NoSuchRevision', revid), branch=branch)
3789
3655
        expected_error = errors.NoSuchRevision(branch, revid)
3790
3656
        self.assertEqual(expected_error, translated_error)
3791
3657
 
3792
3658
    def test_nosuchrevision(self):
3793
3659
        repository = self.make_repository('')
3794
 
        revid = b'revid'
 
3660
        revid = 'revid'
3795
3661
        translated_error = self.translateTuple(
3796
 
            (b'nosuchrevision', revid), repository=repository)
 
3662
            ('nosuchrevision', revid), repository=repository)
3797
3663
        expected_error = errors.NoSuchRevision(repository, revid)
3798
3664
        self.assertEqual(expected_error, translated_error)
3799
3665
 
3800
3666
    def test_nobranch(self):
3801
 
        bzrdir = self.make_controldir('')
3802
 
        translated_error = self.translateTuple((b'nobranch',), bzrdir=bzrdir)
 
3667
        bzrdir = self.make_bzrdir('')
 
3668
        translated_error = self.translateTuple(('nobranch',), bzrdir=bzrdir)
3803
3669
        expected_error = errors.NotBranchError(path=bzrdir.root_transport.base)
3804
3670
        self.assertEqual(expected_error, translated_error)
3805
3671
 
3806
3672
    def test_nobranch_one_arg(self):
3807
 
        bzrdir = self.make_controldir('')
 
3673
        bzrdir = self.make_bzrdir('')
3808
3674
        translated_error = self.translateTuple(
3809
 
            (b'nobranch', b'extra detail'), bzrdir=bzrdir)
 
3675
            ('nobranch', 'extra detail'), bzrdir=bzrdir)
3810
3676
        expected_error = errors.NotBranchError(
3811
3677
            path=bzrdir.root_transport.base,
3812
3678
            detail='extra detail')
3813
3679
        self.assertEqual(expected_error, translated_error)
3814
3680
 
3815
3681
    def test_norepository(self):
3816
 
        bzrdir = self.make_controldir('')
3817
 
        translated_error = self.translateTuple((b'norepository',),
3818
 
                                               bzrdir=bzrdir)
 
3682
        bzrdir = self.make_bzrdir('')
 
3683
        translated_error = self.translateTuple(('norepository',),
 
3684
            bzrdir=bzrdir)
3819
3685
        expected_error = errors.NoRepositoryPresent(bzrdir)
3820
3686
        self.assertEqual(expected_error, translated_error)
3821
3687
 
3822
3688
    def test_LockContention(self):
3823
 
        translated_error = self.translateTuple((b'LockContention',))
 
3689
        translated_error = self.translateTuple(('LockContention',))
3824
3690
        expected_error = errors.LockContention('(remote lock)')
3825
3691
        self.assertEqual(expected_error, translated_error)
3826
3692
 
3827
3693
    def test_UnlockableTransport(self):
3828
 
        bzrdir = self.make_controldir('')
 
3694
        bzrdir = self.make_bzrdir('')
3829
3695
        translated_error = self.translateTuple(
3830
 
            (b'UnlockableTransport',), bzrdir=bzrdir)
 
3696
            ('UnlockableTransport',), bzrdir=bzrdir)
3831
3697
        expected_error = errors.UnlockableTransport(bzrdir.root_transport)
3832
3698
        self.assertEqual(expected_error, translated_error)
3833
3699
 
3834
3700
    def test_LockFailed(self):
3835
3701
        lock = 'str() of a server lock'
3836
3702
        why = 'str() of why'
3837
 
        translated_error = self.translateTuple(
3838
 
            (b'LockFailed', lock.encode('ascii'), why.encode('ascii')))
 
3703
        translated_error = self.translateTuple(('LockFailed', lock, why))
3839
3704
        expected_error = errors.LockFailed(lock, why)
3840
3705
        self.assertEqual(expected_error, translated_error)
3841
3706
 
3842
3707
    def test_TokenMismatch(self):
3843
3708
        token = 'a lock token'
3844
 
        translated_error = self.translateTuple(
3845
 
            (b'TokenMismatch',), token=token)
 
3709
        translated_error = self.translateTuple(('TokenMismatch',), token=token)
3846
3710
        expected_error = errors.TokenMismatch(token, '(remote token)')
3847
3711
        self.assertEqual(expected_error, translated_error)
3848
3712
 
3850
3714
        branch = self.make_branch('a')
3851
3715
        other_branch = self.make_branch('b')
3852
3716
        translated_error = self.translateTuple(
3853
 
            (b'Diverged',), branch=branch, other_branch=other_branch)
 
3717
            ('Diverged',), branch=branch, other_branch=other_branch)
3854
3718
        expected_error = errors.DivergedBranches(branch, other_branch)
3855
3719
        self.assertEqual(expected_error, translated_error)
3856
3720
 
3857
3721
    def test_NotStacked(self):
3858
3722
        branch = self.make_branch('')
3859
 
        translated_error = self.translateTuple((b'NotStacked',), branch=branch)
 
3723
        translated_error = self.translateTuple(('NotStacked',), branch=branch)
3860
3724
        expected_error = errors.NotStacked(branch)
3861
3725
        self.assertEqual(expected_error, translated_error)
3862
3726
 
3863
3727
    def test_ReadError_no_args(self):
3864
3728
        path = 'a path'
3865
 
        translated_error = self.translateTuple((b'ReadError',), path=path)
 
3729
        translated_error = self.translateTuple(('ReadError',), path=path)
3866
3730
        expected_error = errors.ReadError(path)
3867
3731
        self.assertEqual(expected_error, translated_error)
3868
3732
 
3869
3733
    def test_ReadError(self):
3870
3734
        path = 'a path'
3871
 
        translated_error = self.translateTuple(
3872
 
            (b'ReadError', path.encode('utf-8')))
 
3735
        translated_error = self.translateTuple(('ReadError', path))
3873
3736
        expected_error = errors.ReadError(path)
3874
3737
        self.assertEqual(expected_error, translated_error)
3875
3738
 
3876
3739
    def test_IncompatibleRepositories(self):
3877
 
        translated_error = self.translateTuple((b'IncompatibleRepositories',
3878
 
                                                b"repo1", b"repo2", b"details here"))
 
3740
        translated_error = self.translateTuple(('IncompatibleRepositories',
 
3741
            "repo1", "repo2", "details here"))
3879
3742
        expected_error = errors.IncompatibleRepositories("repo1", "repo2",
3880
 
                                                         "details here")
3881
 
        self.assertEqual(expected_error, translated_error)
3882
 
 
3883
 
    def test_GhostRevisionsHaveNoRevno(self):
3884
 
        translated_error = self.translateTuple((b'GhostRevisionsHaveNoRevno',
3885
 
                                                b"revid1", b"revid2"))
3886
 
        expected_error = errors.GhostRevisionsHaveNoRevno(b"revid1", b"revid2")
 
3743
            "details here")
3887
3744
        self.assertEqual(expected_error, translated_error)
3888
3745
 
3889
3746
    def test_PermissionDenied_no_args(self):
3890
3747
        path = 'a path'
3891
 
        translated_error = self.translateTuple((b'PermissionDenied',),
3892
 
                                               path=path)
 
3748
        translated_error = self.translateTuple(('PermissionDenied',),
 
3749
            path=path)
3893
3750
        expected_error = errors.PermissionDenied(path)
3894
3751
        self.assertEqual(expected_error, translated_error)
3895
3752
 
3896
3753
    def test_PermissionDenied_one_arg(self):
3897
3754
        path = 'a path'
3898
 
        translated_error = self.translateTuple(
3899
 
            (b'PermissionDenied', path.encode('utf-8')))
 
3755
        translated_error = self.translateTuple(('PermissionDenied', path))
3900
3756
        expected_error = errors.PermissionDenied(path)
3901
3757
        self.assertEqual(expected_error, translated_error)
3902
3758
 
3907
3763
        local_path = 'local path'
3908
3764
        remote_path = 'remote path'
3909
3765
        translated_error = self.translateTuple(
3910
 
            (b'PermissionDenied', remote_path.encode('utf-8')), path=local_path)
 
3766
            ('PermissionDenied', remote_path), path=local_path)
3911
3767
        expected_error = errors.PermissionDenied(local_path)
3912
3768
        self.assertEqual(expected_error, translated_error)
3913
3769
 
3915
3771
        path = 'a path'
3916
3772
        extra = 'a string with extra info'
3917
3773
        translated_error = self.translateTuple(
3918
 
            (b'PermissionDenied', path.encode('utf-8'), extra.encode('utf-8')))
 
3774
            ('PermissionDenied', path, extra))
3919
3775
        expected_error = errors.PermissionDenied(path, extra)
3920
3776
        self.assertEqual(expected_error, translated_error)
3921
3777
 
3923
3779
 
3924
3780
    def test_NoSuchFile_context_path(self):
3925
3781
        local_path = "local path"
3926
 
        translated_error = self.translateTuple((b'ReadError', b"remote path"),
3927
 
                                               path=local_path)
 
3782
        translated_error = self.translateTuple(('ReadError', "remote path"),
 
3783
            path=local_path)
3928
3784
        expected_error = errors.ReadError(local_path)
3929
3785
        self.assertEqual(expected_error, translated_error)
3930
3786
 
3931
3787
    def test_NoSuchFile_without_context(self):
3932
3788
        remote_path = "remote path"
3933
 
        translated_error = self.translateTuple(
3934
 
            (b'ReadError', remote_path.encode('utf-8')))
 
3789
        translated_error = self.translateTuple(('ReadError', remote_path))
3935
3790
        expected_error = errors.ReadError(remote_path)
3936
3791
        self.assertEqual(expected_error, translated_error)
3937
3792
 
3938
3793
    def test_ReadOnlyError(self):
3939
 
        translated_error = self.translateTuple((b'ReadOnlyError',))
 
3794
        translated_error = self.translateTuple(('ReadOnlyError',))
3940
3795
        expected_error = errors.TransportNotPossible("readonly transport")
3941
3796
        self.assertEqual(expected_error, translated_error)
3942
3797
 
3943
3798
    def test_MemoryError(self):
3944
 
        translated_error = self.translateTuple((b'MemoryError',))
 
3799
        translated_error = self.translateTuple(('MemoryError',))
3945
3800
        self.assertStartsWith(str(translated_error),
3946
 
                              "remote server out of memory")
 
3801
            "remote server out of memory")
3947
3802
 
3948
3803
    def test_generic_IndexError_no_classname(self):
3949
 
        err = errors.ErrorFromSmartServer(
3950
 
            (b'error', b"list index out of range"))
 
3804
        err = errors.ErrorFromSmartServer(('error', "list index out of range"))
3951
3805
        translated_error = self.translateErrorFromSmartServer(err)
3952
3806
        expected_error = errors.UnknownErrorFromSmartServer(err)
3953
3807
        self.assertEqual(expected_error, translated_error)
3955
3809
    # GZ 2011-03-02: TODO test generic non-ascii error string
3956
3810
 
3957
3811
    def test_generic_KeyError(self):
3958
 
        err = errors.ErrorFromSmartServer((b'error', b'KeyError', b"1"))
 
3812
        err = errors.ErrorFromSmartServer(('error', 'KeyError', "1"))
3959
3813
        translated_error = self.translateErrorFromSmartServer(err)
3960
3814
        expected_error = errors.UnknownErrorFromSmartServer(err)
3961
3815
        self.assertEqual(expected_error, translated_error)
3962
3816
 
3963
 
    def test_RevnoOutOfBounds(self):
3964
 
        translated_error = self.translateTuple(
3965
 
            ((b'revno-outofbounds', 5, 0, 3)), path=b'path')
3966
 
        expected_error = errors.RevnoOutOfBounds(5, (0, 3))
3967
 
        self.assertEqual(expected_error, translated_error)
3968
 
 
3969
3817
 
3970
3818
class TestErrorTranslationRobustness(TestErrorTranslationBase):
3971
 
    """Unit tests for breezy.bzr.remote._translate_error's robustness.
 
3819
    """Unit tests for brzlib.remote._translate_error's robustness.
3972
3820
 
3973
3821
    TestErrorTranslationSuccess is for cases where _translate_error can
3974
3822
    translate successfully.  This class about how _translate_err behaves when
3979
3827
        """If the error code from the server is not recognised, the original
3980
3828
        ErrorFromSmartServer is propagated unmodified.
3981
3829
        """
3982
 
        error_tuple = (b'An unknown error tuple',)
 
3830
        error_tuple = ('An unknown error tuple',)
3983
3831
        server_error = errors.ErrorFromSmartServer(error_tuple)
3984
3832
        translated_error = self.translateErrorFromSmartServer(server_error)
3985
3833
        expected_error = errors.UnknownErrorFromSmartServer(server_error)
3993
3841
        # To translate a NoSuchRevision error _translate_error needs a 'branch'
3994
3842
        # in the context dict.  So let's give it an empty context dict instead
3995
3843
        # to exercise its error recovery.
3996
 
        error_tuple = (b'NoSuchRevision', b'revid')
 
3844
        empty_context = {}
 
3845
        error_tuple = ('NoSuchRevision', 'revid')
3997
3846
        server_error = errors.ErrorFromSmartServer(error_tuple)
3998
3847
        translated_error = self.translateErrorFromSmartServer(server_error)
3999
3848
        self.assertEqual(server_error, translated_error)
4008
3857
        'path' variable from either the wire or the local context.  If neither
4009
3858
        has it, then an error is raised.
4010
3859
        """
4011
 
        error_tuple = (b'ReadError',)
 
3860
        error_tuple = ('ReadError',)
4012
3861
        server_error = errors.ErrorFromSmartServer(error_tuple)
4013
3862
        translated_error = self.translateErrorFromSmartServer(server_error)
4014
3863
        self.assertEqual(server_error, translated_error)
4028
3877
        # make a branch stacked on another repository containing an empty
4029
3878
        # revision, then open it over hpss - we should be able to see that
4030
3879
        # revision.
 
3880
        base_transport = self.get_transport()
4031
3881
        base_builder = self.make_branch_builder('base', format='1.9')
4032
3882
        base_builder.start_series()
4033
 
        base_revid = base_builder.build_snapshot(None,
4034
 
                                                 [('add', ('', None, 'directory', None))],
4035
 
                                                 'message', revision_id=b'rev-id')
 
3883
        base_revid = base_builder.build_snapshot('rev-id', None,
 
3884
            [('add', ('', None, 'directory', None))],
 
3885
            'message')
4036
3886
        base_builder.finish_series()
4037
3887
        stacked_branch = self.make_branch('stacked', format='1.9')
4038
3888
        stacked_branch.set_stacked_on_url('../base')
4049
3899
            # be a RemoteRepository
4050
3900
            self.assertLength(1, remote_repo._fallback_repositories)
4051
3901
            self.assertIsInstance(remote_repo._fallback_repositories[0],
4052
 
                                  RemoteRepository)
 
3902
                RemoteRepository)
4053
3903
            # and it has the revision committed to the underlying repository;
4054
3904
            # these have varying implementations so we try several of them
4055
3905
            self.assertTrue(remote_repo.has_revisions([base_revid]))
4056
3906
            self.assertTrue(remote_repo.has_revision(base_revid))
4057
3907
            self.assertEqual(remote_repo.get_revision(base_revid).message,
4058
 
                             'message')
 
3908
                'message')
4059
3909
        finally:
4060
3910
            remote_repo.unlock()
4061
3911
 
4063
3913
        """Get stacked_upon and stacked branches with content in each."""
4064
3914
        self.setup_smart_server_with_call_log()
4065
3915
        tree1 = self.make_branch_and_tree('tree1', format='1.9')
4066
 
        tree1.commit('rev1', rev_id=b'rev1')
4067
 
        tree2 = tree1.branch.controldir.sprout('tree2', stacked=True
4068
 
                                               ).open_workingtree()
 
3916
        tree1.commit('rev1', rev_id='rev1')
 
3917
        tree2 = tree1.branch.bzrdir.sprout('tree2', stacked=True
 
3918
            ).open_workingtree()
4069
3919
        local_tree = tree2.branch.create_checkout('local')
4070
3920
        local_tree.commit('local changes make me feel good.')
4071
3921
        branch2 = Branch.open(self.get_url('tree2'))
4077
3927
        # the public implementation of get_parent_map obeys stacking
4078
3928
        _, branch = self.prepare_stacked_remote_branch()
4079
3929
        repo = branch.repository
4080
 
        self.assertEqual({b'rev1'}, set(repo.get_parent_map([b'rev1'])))
 
3930
        self.assertEqual(['rev1'], repo.get_parent_map(['rev1']).keys())
4081
3931
 
4082
3932
    def test_unstacked_get_parent_map(self):
4083
3933
        # _unstacked_provider.get_parent_map ignores stacking
4084
3934
        _, branch = self.prepare_stacked_remote_branch()
4085
3935
        provider = branch.repository._unstacked_provider
4086
 
        self.assertEqual(set(), set(provider.get_parent_map([b'rev1'])))
 
3936
        self.assertEqual([], provider.get_parent_map(['rev1']).keys())
4087
3937
 
4088
3938
    def fetch_stream_to_rev_order(self, stream):
4089
3939
        result = []
4116
3966
        tip = stacked.last_revision()
4117
3967
        stacked.repository._ensure_real()
4118
3968
        graph = stacked.repository.get_graph()
4119
 
        revs = [r for (r, ps) in graph.iter_ancestry([tip])
 
3969
        revs = [r for (r,ps) in graph.iter_ancestry([tip])
4120
3970
                if r != NULL_REVISION]
4121
3971
        revs.reverse()
4122
3972
        search = vf_search.PendingAncestryResult([tip], stacked.repository)
4143
3993
        # is itself stacked yields the full data from all three sources.
4144
3994
        def make_stacked_stacked():
4145
3995
            _, stacked = self.prepare_stacked_remote_branch()
4146
 
            tree = stacked.controldir.sprout('tree3', stacked=True
4147
 
                                             ).open_workingtree()
 
3996
            tree = stacked.bzrdir.sprout('tree3', stacked=True
 
3997
                ).open_workingtree()
4148
3998
            local_tree = tree.branch.create_checkout('local-tree3')
4149
3999
            local_tree.commit('more local changes are better')
4150
4000
            branch = Branch.open(self.get_url('tree3'))
4151
4001
            branch.lock_read()
4152
4002
            self.addCleanup(branch.unlock)
4153
4003
            return None, branch
4154
 
        rev_ord, expected_revs = self.get_ordered_revs(
4155
 
            '1.9', 'unordered', branch_factory=make_stacked_stacked)
 
4004
        rev_ord, expected_revs = self.get_ordered_revs('1.9', 'unordered',
 
4005
            branch_factory=make_stacked_stacked)
4156
4006
        self.assertEqual(set(expected_revs), set(rev_ord))
4157
4007
        # Getting unordered results should have made a streaming data request
4158
4008
        # from the server, and one from each backing repo
4187
4037
        # branch pulling content from stacked and trunk.
4188
4038
        self.setup_smart_server_with_call_log()
4189
4039
        trunk = self.make_branch_and_tree('trunk', format="1.9-rich-root")
4190
 
        trunk.commit('start')
 
4040
        r1 = trunk.commit('start')
4191
4041
        stacked_branch = trunk.branch.create_clone_on_transport(
4192
4042
            self.get_transport('stacked'), stacked_on=trunk.branch.base)
4193
4043
        local = self.make_branch('local', format='1.9-rich-root')
4194
4044
        local.repository.fetch(stacked_branch.repository,
4195
 
                               stacked_branch.last_revision())
 
4045
            stacked_branch.last_revision())
4196
4046
 
4197
4047
 
4198
4048
class TestRemoteBranchEffort(tests.TestCaseWithTransport):
4220
4070
        local.repository.fetch(remote_branch.repository)
4221
4071
        self.hpss_calls = []
4222
4072
        remote_branch.copy_content_into(local)
4223
 
        self.assertFalse(b'Branch.revision_history' in self.hpss_calls)
 
4073
        self.assertFalse('Branch.revision_history' in self.hpss_calls)
4224
4074
 
4225
4075
    def test_fetch_everything_needs_just_one_call(self):
4226
4076
        local = self.make_branch('local')
4232
4082
        local.repository.fetch(
4233
4083
            remote_branch.repository,
4234
4084
            fetch_spec=vf_search.EverythingResult(remote_branch.repository))
4235
 
        self.assertEqual([b'Repository.get_stream_1.19'], self.hpss_calls)
 
4085
        self.assertEqual(['Repository.get_stream_1.19'], self.hpss_calls)
4236
4086
 
4237
4087
    def override_verb(self, verb_name, verb):
4238
4088
        request_handlers = request.request_handlers
4240
4090
        orig_info = request_handlers.get_info(verb_name)
4241
4091
        request_handlers.register(verb_name, verb, override_existing=True)
4242
4092
        self.addCleanup(request_handlers.register, verb_name, orig_verb,
4243
 
                        override_existing=True, info=orig_info)
 
4093
                override_existing=True, info=orig_info)
4244
4094
 
4245
4095
    def test_fetch_everything_backwards_compat(self):
4246
4096
        """Can fetch with EverythingResult even with pre 2.4 servers.
4247
 
 
 
4097
        
4248
4098
        Pre-2.4 do not support 'everything' searches with the
4249
4099
        Repository.get_stream_1.19 verb.
4250
4100
        """
4251
4101
        verb_log = []
4252
 
 
4253
4102
        class OldGetStreamVerb(SmartServerRepositoryGetStream_1_19):
4254
4103
            """A version of the Repository.get_stream_1.19 verb patched to
4255
4104
            reject 'everything' searches the way 2.3 and earlier do.
4256
4105
            """
4257
 
 
4258
4106
            def recreate_search(self, repository, search_bytes,
4259
4107
                                discard_excess=False):
4260
 
                verb_log.append(search_bytes.split(b'\n', 1)[0])
4261
 
                if search_bytes == b'everything':
 
4108
                verb_log.append(search_bytes.split('\n', 1)[0])
 
4109
                if search_bytes == 'everything':
4262
4110
                    return (None,
4263
 
                            request.FailedSmartServerResponse((b'BadSearch',)))
 
4111
                            request.FailedSmartServerResponse(('BadSearch',)))
4264
4112
                return super(OldGetStreamVerb,
4265
 
                             self).recreate_search(repository, search_bytes,
4266
 
                                                   discard_excess=discard_excess)
4267
 
        self.override_verb(b'Repository.get_stream_1.19', OldGetStreamVerb)
 
4113
                        self).recreate_search(repository, search_bytes,
 
4114
                            discard_excess=discard_excess)
 
4115
        self.override_verb('Repository.get_stream_1.19', OldGetStreamVerb)
4268
4116
        local = self.make_branch('local')
4269
4117
        builder = self.make_branch_builder('remote')
4270
4118
        builder.build_commit(message="Commit.")
4282
4130
 
4283
4131
 
4284
4132
class TestUpdateBoundBranchWithModifiedBoundLocation(
4285
 
        tests.TestCaseWithTransport):
 
4133
    tests.TestCaseWithTransport):
4286
4134
    """Ensure correct handling of bound_location modifications.
4287
4135
 
4288
4136
    This is tested against a smart server as http://pad.lv/786980 was about a
4334
4182
 
4335
4183
            def __init__(self, urgency):
4336
4184
                self.urgency = urgency
4337
 
        remote.no_context_error_translators.register(b"OutOfCoffee",
4338
 
                                                     lambda err: OutOfCoffee(err.error_args[0]))
 
4185
        remote.no_context_error_translators.register("OutOfCoffee",
 
4186
            lambda err: OutOfCoffee(err.error_args[0]))
4339
4187
        transport = MemoryTransport()
4340
4188
        client = FakeClient(transport.base)
4341
4189
        client.add_expected_call(
4342
 
            b'Branch.get_stacked_on_url', (b'quack/',),
4343
 
            b'error', (b'NotStacked',))
 
4190
            'Branch.get_stacked_on_url', ('quack/',),
 
4191
            'error', ('NotStacked',))
4344
4192
        client.add_expected_call(
4345
 
            b'Branch.last_revision_info',
4346
 
            (b'quack/',),
4347
 
            b'error', (b'OutOfCoffee', b'low'))
 
4193
            'Branch.last_revision_info',
 
4194
            ('quack/',),
 
4195
            'error', ('OutOfCoffee', 'low'))
4348
4196
        transport.mkdir('quack')
4349
4197
        transport = transport.clone('quack')
4350
4198
        branch = self.make_remote_branch(transport, client)
4356
4204
            def __init__(self, branch, urgency):
4357
4205
                self.branch = branch
4358
4206
                self.urgency = urgency
4359
 
        remote.error_translators.register(b"OutOfTea",
4360
 
                                          lambda err, find, path: OutOfTea(
4361
 
                                              err.error_args[0].decode(
4362
 
                                                  'utf-8'),
4363
 
                                              find("branch")))
 
4207
        remote.error_translators.register("OutOfTea",
 
4208
            lambda err, find, path: OutOfTea(err.error_args[0],
 
4209
                find("branch")))
4364
4210
        transport = MemoryTransport()
4365
4211
        client = FakeClient(transport.base)
4366
4212
        client.add_expected_call(
4367
 
            b'Branch.get_stacked_on_url', (b'quack/',),
4368
 
            b'error', (b'NotStacked',))
 
4213
            'Branch.get_stacked_on_url', ('quack/',),
 
4214
            'error', ('NotStacked',))
4369
4215
        client.add_expected_call(
4370
 
            b'Branch.last_revision_info',
4371
 
            (b'quack/',),
4372
 
            b'error', (b'OutOfTea', b'low'))
 
4216
            'Branch.last_revision_info',
 
4217
            ('quack/',),
 
4218
            'error', ('OutOfTea', 'low'))
4373
4219
        transport.mkdir('quack')
4374
4220
        transport = transport.clone('quack')
4375
4221
        branch = self.make_remote_branch(transport, client)
4383
4229
        transport_path = 'quack'
4384
4230
        repo, client = self.setup_fake_client_and_repository(transport_path)
4385
4231
        client.add_expected_call(
4386
 
            b'Repository.lock_write', (b'quack/', b''),
4387
 
            b'success', (b'ok', b'token'))
4388
 
        client.add_expected_call(
4389
 
            b'Repository.pack', (b'quack/', b'token', b'False'),
4390
 
            b'success', (b'ok',), )
4391
 
        client.add_expected_call(
4392
 
            b'Repository.unlock', (b'quack/', b'token'),
4393
 
            b'success', (b'ok', ))
 
4232
            'Repository.lock_write', ('quack/', ''),
 
4233
            'success', ('ok', 'token'))
 
4234
        client.add_expected_call(
 
4235
            'Repository.pack', ('quack/', 'token', 'False'),
 
4236
            'success', ('ok',), )
 
4237
        client.add_expected_call(
 
4238
            'Repository.unlock', ('quack/', 'token'),
 
4239
            'success', ('ok', ))
4394
4240
        repo.pack()
4395
4241
 
4396
4242
    def test_pack_with_hint(self):
4397
4243
        transport_path = 'quack'
4398
4244
        repo, client = self.setup_fake_client_and_repository(transport_path)
4399
4245
        client.add_expected_call(
4400
 
            b'Repository.lock_write', (b'quack/', b''),
4401
 
            b'success', (b'ok', b'token'))
4402
 
        client.add_expected_call(
4403
 
            b'Repository.pack', (b'quack/', b'token', b'False'),
4404
 
            b'success', (b'ok',), )
4405
 
        client.add_expected_call(
4406
 
            b'Repository.unlock', (b'quack/', b'token', b'False'),
4407
 
            b'success', (b'ok', ))
 
4246
            'Repository.lock_write', ('quack/', ''),
 
4247
            'success', ('ok', 'token'))
 
4248
        client.add_expected_call(
 
4249
            'Repository.pack', ('quack/', 'token', 'False'),
 
4250
            'success', ('ok',), )
 
4251
        client.add_expected_call(
 
4252
            'Repository.unlock', ('quack/', 'token', 'False'),
 
4253
            'success', ('ok', ))
4408
4254
        repo.pack(['hinta', 'hintb'])
4409
4255
 
4410
4256
 
4413
4259
 
4414
4260
    def _serialize_inv_delta(self, old_name, new_name, delta):
4415
4261
        serializer = inventory_delta.InventoryDeltaSerializer(True, False)
4416
 
        return b"".join(serializer.delta_to_lines(old_name, new_name, delta))
 
4262
        return "".join(serializer.delta_to_lines(old_name, new_name, delta))
4417
4263
 
4418
4264
    def test_single_empty(self):
4419
4265
        transport_path = 'quack'
4421
4267
        fmt = controldir.format_registry.get('2a')().repository_format
4422
4268
        repo._format = fmt
4423
4269
        stream = [('inventory-deltas', [
4424
 
            versionedfile.FulltextContentFactory(b'somerevid', None, None,
4425
 
                                                 self._serialize_inv_delta(b'null:', b'somerevid', []))])]
 
4270
            versionedfile.FulltextContentFactory('somerevid', None, None,
 
4271
                self._serialize_inv_delta('null:', 'somerevid', []))])]
4426
4272
        client.add_expected_call(
4427
 
            b'VersionedFileRepository.get_inventories', (
4428
 
                b'quack/', b'unordered'),
4429
 
            b'success', (b'ok', ),
 
4273
            'VersionedFileRepository.get_inventories', ('quack/', 'unordered'),
 
4274
            'success', ('ok', ),
4430
4275
            _stream_to_byte_stream(stream, fmt))
4431
 
        ret = list(repo.iter_inventories([b"somerevid"]))
 
4276
        ret = list(repo.iter_inventories(["somerevid"]))
4432
4277
        self.assertLength(1, ret)
4433
4278
        inv = ret[0]
4434
 
        self.assertEqual(b"somerevid", inv.revision_id)
 
4279
        self.assertEqual("somerevid", inv.revision_id)
4435
4280
 
4436
4281
    def test_empty(self):
4437
4282
        transport_path = 'quack'
4443
4288
        transport_path = 'quack'
4444
4289
        repo, client = self.setup_fake_client_and_repository(transport_path)
4445
4290
        client.add_expected_call(
4446
 
            b'VersionedFileRepository.get_inventories', (
4447
 
                b'quack/', b'unordered'),
4448
 
            b'success', (b'ok', ), iter([]))
 
4291
            'VersionedFileRepository.get_inventories', ('quack/', 'unordered'),
 
4292
            'success', ('ok', ), iter([]))
4449
4293
        self.assertRaises(errors.NoSuchRevision, list, repo.iter_inventories(
4450
 
            [b"somerevid"]))
4451
 
 
4452
 
 
4453
 
class TestRepositoryRevisionTreeArchive(TestRemoteRepository):
4454
 
    """Test Repository.iter_inventories."""
4455
 
 
4456
 
    def _serialize_inv_delta(self, old_name, new_name, delta):
4457
 
        serializer = inventory_delta.InventoryDeltaSerializer(True, False)
4458
 
        return b"".join(serializer.delta_to_lines(old_name, new_name, delta))
4459
 
 
4460
 
    def test_simple(self):
4461
 
        transport_path = 'quack'
4462
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
4463
 
        fmt = controldir.format_registry.get('2a')().repository_format
4464
 
        repo._format = fmt
4465
 
        stream = [('inventory-deltas', [
4466
 
            versionedfile.FulltextContentFactory(b'somerevid', None, None,
4467
 
                                                 self._serialize_inv_delta(b'null:', b'somerevid', []))])]
4468
 
        client.add_expected_call(
4469
 
            b'VersionedFileRepository.get_inventories', (
4470
 
                b'quack/', b'unordered'),
4471
 
            b'success', (b'ok', ),
4472
 
            _stream_to_byte_stream(stream, fmt))
4473
 
        f = BytesIO()
4474
 
        with tarfile.open(mode='w', fileobj=f) as tf:
4475
 
            info = tarfile.TarInfo('somefile')
4476
 
            info.mtime = 432432
4477
 
            contents = b'some data'
4478
 
            info.type = tarfile.REGTYPE
4479
 
            info.mode = 0o644
4480
 
            info.size = len(contents)
4481
 
            tf.addfile(info, BytesIO(contents))
4482
 
        client.add_expected_call(
4483
 
            b'Repository.revision_archive', (b'quack/',
4484
 
                                             b'somerevid', b'tar', b'foo.tar', b'', b'', None),
4485
 
            b'success', (b'ok', ),
4486
 
            f.getvalue())
4487
 
        tree = repo.revision_tree(b'somerevid')
4488
 
        self.assertEqual(f.getvalue(), b''.join(
4489
 
            tree.archive('tar', 'foo.tar')))
4490
 
 
4491
 
 
4492
 
class TestRepositoryAnnotate(TestRemoteRepository):
4493
 
    """Test RemoteRevisionTree.annotate.."""
4494
 
 
4495
 
    def _serialize_inv_delta(self, old_name, new_name, delta):
4496
 
        serializer = inventory_delta.InventoryDeltaSerializer(True, False)
4497
 
        return b"".join(serializer.delta_to_lines(old_name, new_name, delta))
4498
 
 
4499
 
    def test_simple(self):
4500
 
        transport_path = 'quack'
4501
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
4502
 
        fmt = controldir.format_registry.get('2a')().repository_format
4503
 
        repo._format = fmt
4504
 
        stream = [
4505
 
            ('inventory-deltas', [
4506
 
                versionedfile.FulltextContentFactory(
4507
 
                    b'somerevid', None, None,
4508
 
                    self._serialize_inv_delta(b'null:', b'somerevid', []))])]
4509
 
        client.add_expected_call(
4510
 
            b'VersionedFileRepository.get_inventories', (
4511
 
                b'quack/', b'unordered'),
4512
 
            b'success', (b'ok', ),
4513
 
            _stream_to_byte_stream(stream, fmt))
4514
 
        client.add_expected_call(
4515
 
            b'Repository.annotate_file_revision',
4516
 
            (b'quack/', b'somerevid', b'filename', b'', b'current:'),
4517
 
            b'success', (b'ok', ),
4518
 
            bencode.bencode([[b'baserevid', b'line 1\n'],
4519
 
                             [b'somerevid', b'line2\n']]))
4520
 
        tree = repo.revision_tree(b'somerevid')
4521
 
        self.assertEqual([
4522
 
            (b'baserevid', b'line 1\n'),
4523
 
            (b'somerevid', b'line2\n')],
4524
 
            list(tree.annotate_iter('filename')))
4525
 
 
4526
 
 
4527
 
class TestBranchGetAllReferenceInfo(RemoteBranchTestCase):
4528
 
 
4529
 
    def test_get_all_reference_info(self):
4530
 
        transport = MemoryTransport()
4531
 
        client = FakeClient(transport.base)
4532
 
        client.add_expected_call(
4533
 
            b'Branch.get_stacked_on_url', (b'quack/',),
4534
 
            b'error', (b'NotStacked',))
4535
 
        client.add_expected_call(
4536
 
            b'Branch.get_all_reference_info', (b'quack/',),
4537
 
            b'success', (b'ok',), bencode.bencode([
4538
 
                (b'file-id', b'https://www.example.com/', b'')]))
4539
 
        transport.mkdir('quack')
4540
 
        transport = transport.clone('quack')
4541
 
        branch = self.make_remote_branch(transport, client)
4542
 
        result = branch._get_all_reference_info()
4543
 
        self.assertFinished(client)
4544
 
        self.assertEqual({b'file-id': ('https://www.example.com/', None)}, result)
 
4294
            ["somerevid"]))