~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_remote.py

  • Committer: Jelmer Vernooij
  • Date: 2016-04-03 16:32:31 UTC
  • mto: This revision was merged to the branch mainline in revision 6617.
  • Revision ID: jelmer@jelmer.uk-20160403163231-h72bo0uyek2gikw0
Don't put French text in doc/en/user-reference when LANGUAGE=fr_CH.UTF_8.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2011 Canonical Ltd
 
1
# Copyright (C) 2006-2013, 2016 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
25
25
 
26
26
import bz2
27
27
from cStringIO import StringIO
 
28
import zlib
28
29
 
29
30
from bzrlib import (
 
31
    bencode,
30
32
    branch,
31
33
    bzrdir,
32
34
    config,
33
35
    controldir,
34
36
    errors,
35
 
    graph as _mod_graph,
36
37
    inventory,
37
38
    inventory_delta,
38
39
    remote,
41
42
    transport,
42
43
    treebuilder,
43
44
    versionedfile,
 
45
    vf_search,
44
46
    )
45
47
from bzrlib.branch import Branch
46
48
from bzrlib.bzrdir import (
48
50
    BzrDirFormat,
49
51
    RemoteBzrProber,
50
52
    )
 
53
from bzrlib.chk_serializer import chk_bencode_serializer
51
54
from bzrlib.remote import (
52
55
    RemoteBranch,
53
56
    RemoteBranchFormat,
57
60
    RemoteRepositoryFormat,
58
61
    )
59
62
from bzrlib.repofmt import groupcompress_repo, knitpack_repo
60
 
from bzrlib.revision import NULL_REVISION
 
63
from bzrlib.revision import (
 
64
    NULL_REVISION,
 
65
    Revision,
 
66
    )
61
67
from bzrlib.smart import medium, request
62
68
from bzrlib.smart.client import _SmartClient
63
69
from bzrlib.smart.repository import (
64
70
    SmartServerRepositoryGetParentMap,
65
71
    SmartServerRepositoryGetStream_1_19,
 
72
    _stream_to_byte_stream,
66
73
    )
 
74
from bzrlib.symbol_versioning import deprecated_in
67
75
from bzrlib.tests import (
68
76
    test_server,
69
77
    )
113
121
        self.local_wt.commit(message='test commit', rev_id=revid)
114
122
        self.assertTrue(repo.has_revision(revid))
115
123
 
116
 
    def test_remote_branch_revision_history(self):
117
 
        b = BzrDir.open_from_transport(self.transport).open_branch()
118
 
        self.assertEqual([], b.revision_history())
119
 
        r1 = self.local_wt.commit('1st commit')
120
 
        r2 = self.local_wt.commit('1st commit', rev_id=u'\xc8'.encode('utf8'))
121
 
        self.assertEqual([r1, r2], b.revision_history())
122
 
 
123
124
    def test_find_correct_format(self):
124
125
        """Should open a RemoteBzrDir over a RemoteTransport"""
125
126
        fmt = BzrDirFormat.find_format(self.transport)
165
166
    def test_remote_branch_set_append_revisions_only(self):
166
167
        # Make a format 1.9 branch, which supports append_revisions_only
167
168
        branch = self.make_branch('branch', format='1.9')
168
 
        config = branch.get_config()
169
169
        branch.set_append_revisions_only(True)
 
170
        config = branch.get_config_stack()
170
171
        self.assertEqual(
171
 
            'True', config.get_user_option('append_revisions_only'))
 
172
            True, config.get('append_revisions_only'))
172
173
        branch.set_append_revisions_only(False)
 
174
        config = branch.get_config_stack()
173
175
        self.assertEqual(
174
 
            'False', config.get_user_option('append_revisions_only'))
 
176
            False, config.get('append_revisions_only'))
175
177
 
176
178
    def test_remote_branch_set_append_revisions_only_upgrade_reqd(self):
177
179
        branch = self.make_branch('branch', format='knit')
178
 
        config = branch.get_config()
179
180
        self.assertRaises(
180
181
            errors.UpgradeRequired, branch.set_append_revisions_only, True)
181
182
 
339
340
class TestRemote(tests.TestCaseWithMemoryTransport):
340
341
 
341
342
    def get_branch_format(self):
342
 
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
 
343
        reference_bzrdir_format = controldir.format_registry.get('default')()
343
344
        return reference_bzrdir_format.get_branch_format()
344
345
 
345
346
    def get_repo_format(self):
346
 
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
 
347
        reference_bzrdir_format = controldir.format_registry.get('default')()
347
348
        return reference_bzrdir_format.repository_format
348
349
 
349
350
    def assertFinished(self, fake_client):
465
466
        transport = transport.clone('quack')
466
467
        self.make_bzrdir('quack')
467
468
        client = FakeClient(transport.base)
468
 
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
 
469
        reference_bzrdir_format = controldir.format_registry.get('default')()
469
470
        control_name = reference_bzrdir_format.network_name()
470
471
        client.add_expected_call(
471
472
            'BzrDir.cloning_metadir', ('quack/', 'False'),
481
482
        self.assertEqual(None, result._branch_format)
482
483
        self.assertFinished(client)
483
484
 
 
485
    def test_unknown(self):
 
486
        transport = self.get_transport('quack')
 
487
        referenced = self.make_branch('referenced')
 
488
        expected = referenced.bzrdir.cloning_metadir()
 
489
        client = FakeClient(transport.base)
 
490
        client.add_expected_call(
 
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)
 
496
 
 
497
 
 
498
class TestBzrDirCheckoutMetaDir(TestRemote):
 
499
 
 
500
    def test__get_checkout_format(self):
 
501
        transport = MemoryTransport()
 
502
        client = FakeClient(transport.base)
 
503
        reference_bzrdir_format = controldir.format_registry.get('default')()
 
504
        control_name = reference_bzrdir_format.network_name()
 
505
        client.add_expected_call(
 
506
            'BzrDir.checkout_metadir', ('quack/', ),
 
507
            'success', (control_name, '', ''))
 
508
        transport.mkdir('quack')
 
509
        transport = transport.clone('quack')
 
510
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
511
            _client=client)
 
512
        result = a_bzrdir.checkout_metadir()
 
513
        # We should have got a reference control dir with default branch and
 
514
        # repository formats.
 
515
        self.assertEqual(bzrdir.BzrDirMetaFormat1, type(result))
 
516
        self.assertEqual(None, result._repository_format)
 
517
        self.assertEqual(None, result._branch_format)
 
518
        self.assertFinished(client)
 
519
 
 
520
    def test_unknown_format(self):
 
521
        transport = MemoryTransport()
 
522
        client = FakeClient(transport.base)
 
523
        client.add_expected_call(
 
524
            'BzrDir.checkout_metadir', ('quack/',),
 
525
            'success', ('dontknow', '', ''))
 
526
        transport.mkdir('quack')
 
527
        transport = transport.clone('quack')
 
528
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
529
            _client=client)
 
530
        self.assertRaises(errors.UnknownFormatError,
 
531
            a_bzrdir.checkout_metadir)
 
532
        self.assertFinished(client)
 
533
 
 
534
 
 
535
class TestBzrDirGetBranches(TestRemote):
 
536
 
 
537
    def test_get_branches(self):
 
538
        transport = MemoryTransport()
 
539
        client = FakeClient(transport.base)
 
540
        reference_bzrdir_format = controldir.format_registry.get('default')()
 
541
        branch_name = reference_bzrdir_format.get_branch_format().network_name()
 
542
        client.add_success_response_with_body(
 
543
            bencode.bencode({
 
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')
 
554
        transport.mkdir('quack')
 
555
        transport = transport.clone('quack')
 
556
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
557
            _client=client)
 
558
        result = a_bzrdir.get_branches()
 
559
        self.assertEqual(set(["", "foo"]), set(result.keys()))
 
560
        self.assertEqual(
 
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/', ))],
 
566
            client._calls)
 
567
 
 
568
 
 
569
class TestBzrDirDestroyBranch(TestRemote):
 
570
 
 
571
    def test_destroy_default(self):
 
572
        transport = self.get_transport('quack')
 
573
        referenced = self.make_branch('referenced')
 
574
        client = FakeClient(transport.base)
 
575
        client.add_expected_call(
 
576
            'BzrDir.destroy_branch', ('quack/', ),
 
577
            'success', ('ok',)),
 
578
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
579
            _client=client)
 
580
        a_bzrdir.destroy_branch()
 
581
        self.assertFinished(client)
 
582
 
 
583
 
 
584
class TestBzrDirHasWorkingTree(TestRemote):
 
585
 
 
586
    def test_has_workingtree(self):
 
587
        transport = self.get_transport('quack')
 
588
        client = FakeClient(transport.base)
 
589
        client.add_expected_call(
 
590
            'BzrDir.has_workingtree', ('quack/',),
 
591
            'success', ('yes',)),
 
592
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
593
            _client=client)
 
594
        self.assertTrue(a_bzrdir.has_workingtree())
 
595
        self.assertFinished(client)
 
596
 
 
597
    def test_no_workingtree(self):
 
598
        transport = self.get_transport('quack')
 
599
        client = FakeClient(transport.base)
 
600
        client.add_expected_call(
 
601
            'BzrDir.has_workingtree', ('quack/',),
 
602
            'success', ('no',)),
 
603
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
604
            _client=client)
 
605
        self.assertFalse(a_bzrdir.has_workingtree())
 
606
        self.assertFinished(client)
 
607
 
 
608
 
 
609
class TestBzrDirDestroyRepository(TestRemote):
 
610
 
 
611
    def test_destroy_repository(self):
 
612
        transport = self.get_transport('quack')
 
613
        client = FakeClient(transport.base)
 
614
        client.add_expected_call(
 
615
            'BzrDir.destroy_repository', ('quack/',),
 
616
            'success', ('ok',)),
 
617
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
618
            _client=client)
 
619
        a_bzrdir.destroy_repository()
 
620
        self.assertFinished(client)
 
621
 
484
622
 
485
623
class TestBzrDirOpen(TestRemote):
486
624
 
610
748
        # _get_tree_branch is a form of open_branch, but it should only ask for
611
749
        # branch opening, not any other network requests.
612
750
        calls = []
613
 
        def open_branch(name=None):
 
751
        def open_branch(name=None, possible_transports=None):
614
752
            calls.append("Called")
615
753
            return "a-branch"
616
754
        transport = MemoryTransport()
707
845
        transport = transport.clone('quack')
708
846
        self.make_repository('quack')
709
847
        client = FakeClient(transport.base)
710
 
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
 
848
        reference_bzrdir_format = controldir.format_registry.get('default')()
711
849
        reference_format = reference_bzrdir_format.get_branch_format()
712
850
        network_name = reference_format.network_name()
713
851
        reference_repo_fmt = reference_bzrdir_format.repository_format
735
873
        # Client's medium rooted a transport root (not at the bzrdir)
736
874
        client = FakeClient(transport.base)
737
875
        transport = transport.clone('quack')
738
 
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
 
876
        reference_bzrdir_format = controldir.format_registry.get('default')()
739
877
        reference_format = reference_bzrdir_format.get_branch_format()
740
878
        network_name = reference_format.network_name()
741
879
        reference_repo_fmt = reference_bzrdir_format.repository_format
771
909
        transport = transport.clone('quack')
772
910
        self.make_bzrdir('quack')
773
911
        client = FakeClient(transport.base)
774
 
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
 
912
        reference_bzrdir_format = controldir.format_registry.get('default')()
775
913
        reference_format = reference_bzrdir_format.repository_format
776
914
        network_name = reference_format.network_name()
777
915
        client.add_expected_call(
808
946
        # name.
809
947
        client.add_success_response_with_body(
810
948
            "Bazaar-NG meta directory, format 1\n", 'ok')
 
949
        client.add_success_response('stat', '0', '65535')
811
950
        client.add_success_response_with_body(
812
951
            reference_format.get_format_string(), 'ok')
813
952
        # PackRepository wants to do a stat
822
961
             ('call', 'BzrDir.find_repositoryV2', ('quack/',)),
823
962
             ('call', 'BzrDir.find_repository', ('quack/',)),
824
963
             ('call_expecting_body', 'get', ('/quack/.bzr/branch-format',)),
 
964
             ('call', 'stat', ('/quack/.bzr',)),
825
965
             ('call_expecting_body', 'get', ('/quack/.bzr/repository/format',)),
826
966
             ('call', 'stat', ('/quack/.bzr/repository',)),
827
967
             ],
841
981
        # name.
842
982
        client.add_success_response_with_body(
843
983
            "Bazaar-NG meta directory, format 1\n", 'ok')
 
984
        client.add_success_response('stat', '0', '65535')
844
985
        client.add_success_response_with_body(
845
986
            reference_format.get_format_string(), 'ok')
846
987
        # PackRepository wants to do a stat
854
995
            [('call', 'BzrDir.find_repositoryV3', ('quack/',)),
855
996
             ('call', 'BzrDir.find_repositoryV2', ('quack/',)),
856
997
             ('call_expecting_body', 'get', ('/quack/.bzr/branch-format',)),
 
998
             ('call', 'stat', ('/quack/.bzr',)),
857
999
             ('call_expecting_body', 'get', ('/quack/.bzr/repository/format',)),
858
1000
             ('call', 'stat', ('/quack/.bzr/repository',)),
859
1001
             ],
996
1138
        return RemoteBranch(bzrdir, repo, _client=client, format=format)
997
1139
 
998
1140
 
 
1141
class TestBranchBreakLock(RemoteBranchTestCase):
 
1142
 
 
1143
    def test_break_lock(self):
 
1144
        transport_path = 'quack'
 
1145
        transport = MemoryTransport()
 
1146
        client = FakeClient(transport.base)
 
1147
        client.add_expected_call(
 
1148
            'Branch.get_stacked_on_url', ('quack/',),
 
1149
            'error', ('NotStacked',))
 
1150
        client.add_expected_call(
 
1151
            'Branch.break_lock', ('quack/',),
 
1152
            'success', ('ok',))
 
1153
        transport.mkdir('quack')
 
1154
        transport = transport.clone('quack')
 
1155
        branch = self.make_remote_branch(transport, client)
 
1156
        branch.break_lock()
 
1157
        self.assertFinished(client)
 
1158
 
 
1159
 
 
1160
class TestBranchGetPhysicalLockStatus(RemoteBranchTestCase):
 
1161
 
 
1162
    def test_get_physical_lock_status_yes(self):
 
1163
        transport = MemoryTransport()
 
1164
        client = FakeClient(transport.base)
 
1165
        client.add_expected_call(
 
1166
            'Branch.get_stacked_on_url', ('quack/',),
 
1167
            'error', ('NotStacked',))
 
1168
        client.add_expected_call(
 
1169
            'Branch.get_physical_lock_status', ('quack/',),
 
1170
            'success', ('yes',))
 
1171
        transport.mkdir('quack')
 
1172
        transport = transport.clone('quack')
 
1173
        branch = self.make_remote_branch(transport, client)
 
1174
        result = branch.get_physical_lock_status()
 
1175
        self.assertFinished(client)
 
1176
        self.assertEqual(True, result)
 
1177
 
 
1178
    def test_get_physical_lock_status_no(self):
 
1179
        transport = MemoryTransport()
 
1180
        client = FakeClient(transport.base)
 
1181
        client.add_expected_call(
 
1182
            'Branch.get_stacked_on_url', ('quack/',),
 
1183
            'error', ('NotStacked',))
 
1184
        client.add_expected_call(
 
1185
            'Branch.get_physical_lock_status', ('quack/',),
 
1186
            'success', ('no',))
 
1187
        transport.mkdir('quack')
 
1188
        transport = transport.clone('quack')
 
1189
        branch = self.make_remote_branch(transport, client)
 
1190
        result = branch.get_physical_lock_status()
 
1191
        self.assertFinished(client)
 
1192
        self.assertEqual(False, result)
 
1193
 
 
1194
 
999
1195
class TestBranchGetParent(RemoteBranchTestCase):
1000
1196
 
1001
1197
    def test_no_parent(self):
1091
1287
        verb = 'Branch.set_parent_location'
1092
1288
        self.disable_verb(verb)
1093
1289
        branch.set_parent('http://foo/')
1094
 
        self.assertLength(12, self.hpss_calls)
 
1290
        self.assertLength(14, self.hpss_calls)
1095
1291
 
1096
1292
 
1097
1293
class TestBranchGetTagsBytes(RemoteBranchTestCase):
1250
1446
        return branch
1251
1447
 
1252
1448
    def test_backwards_compatible(self):
1253
 
        branch = self.make_branch_with_tags()
1254
 
        c = branch.get_config()
1255
 
        c.set_user_option('branch.fetch_tags', 'True')
1256
 
        self.addCleanup(branch.lock_read().unlock)
 
1449
        br = self.make_branch_with_tags()
 
1450
        br.get_config_stack().set('branch.fetch_tags', True)
 
1451
        self.addCleanup(br.lock_read().unlock)
1257
1452
        # Disable the heads_to_fetch verb
1258
1453
        verb = 'Branch.heads_to_fetch'
1259
1454
        self.disable_verb(verb)
1260
1455
        self.reset_smart_call_log()
1261
 
        result = branch.heads_to_fetch()
 
1456
        result = br.heads_to_fetch()
1262
1457
        self.assertEqual((set(['tip']), set(['rev-1', 'rev-2'])), result)
1263
1458
        self.assertEqual(
1264
 
            ['Branch.last_revision_info', 'Branch.get_config_file',
1265
 
             'Branch.get_tags_bytes'],
 
1459
            ['Branch.last_revision_info', 'Branch.get_tags_bytes'],
1266
1460
            [call.call.method for call in self.hpss_calls])
1267
1461
 
1268
1462
    def test_backwards_compatible_no_tags(self):
1269
 
        branch = self.make_branch_with_tags()
1270
 
        c = branch.get_config()
1271
 
        c.set_user_option('branch.fetch_tags', 'False')
1272
 
        self.addCleanup(branch.lock_read().unlock)
 
1463
        br = self.make_branch_with_tags()
 
1464
        br.get_config_stack().set('branch.fetch_tags', False)
 
1465
        self.addCleanup(br.lock_read().unlock)
1273
1466
        # Disable the heads_to_fetch verb
1274
1467
        verb = 'Branch.heads_to_fetch'
1275
1468
        self.disable_verb(verb)
1276
1469
        self.reset_smart_call_log()
1277
 
        result = branch.heads_to_fetch()
 
1470
        result = br.heads_to_fetch()
1278
1471
        self.assertEqual((set(['tip']), set()), result)
1279
1472
        self.assertEqual(
1280
 
            ['Branch.last_revision_info', 'Branch.get_config_file'],
 
1473
            ['Branch.last_revision_info'],
1281
1474
            [call.call.method for call in self.hpss_calls])
1282
1475
 
1283
1476
 
1445
1638
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1446
1639
            'success', ('ok',))
1447
1640
        branch = self.make_remote_branch(transport, client)
1448
 
        # This is a hack to work around the problem that RemoteBranch currently
1449
 
        # unnecessarily invokes _ensure_real upon a call to lock_write.
1450
 
        branch._ensure_real = lambda: None
1451
1641
        branch.lock_write()
1452
1642
        result = branch._set_last_revision(NULL_REVISION)
1453
1643
        branch.unlock()
1482
1672
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1483
1673
            'success', ('ok',))
1484
1674
        branch = self.make_remote_branch(transport, client)
1485
 
        # This is a hack to work around the problem that RemoteBranch currently
1486
 
        # unnecessarily invokes _ensure_real upon a call to lock_write.
1487
 
        branch._ensure_real = lambda: None
1488
1675
        # Lock the branch, reset the record of remote calls.
1489
1676
        branch.lock_write()
1490
1677
        result = branch._set_last_revision('rev-id2')
1557
1744
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1558
1745
            'success', ('ok',))
1559
1746
        branch = self.make_remote_branch(transport, client)
1560
 
        branch._ensure_real = lambda: None
1561
1747
        branch.lock_write()
1562
1748
        # The 'TipChangeRejected' error response triggered by calling
1563
1749
        # set_last_revision_info causes a TipChangeRejected exception.
1826
2012
        self.addCleanup(branch.unlock)
1827
2013
        self.reset_smart_call_log()
1828
2014
        branch._get_config().set_option('value', 'name')
1829
 
        self.assertLength(10, self.hpss_calls)
 
2015
        self.assertLength(11, self.hpss_calls)
1830
2016
        self.assertEqual('value', branch._get_config().get_option('name'))
1831
2017
 
1832
2018
    def test_backwards_compat_set_option_with_dict(self):
1840
2026
        config = branch._get_config()
1841
2027
        value_dict = {'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'}
1842
2028
        config.set_option(value_dict, 'name')
1843
 
        self.assertLength(10, self.hpss_calls)
 
2029
        self.assertLength(11, self.hpss_calls)
1844
2030
        self.assertEqual(value_dict, branch._get_config().get_option('name'))
1845
2031
 
1846
2032
 
 
2033
class TestBranchGetPutConfigStore(RemoteBranchTestCase):
 
2034
 
 
2035
    def test_get_branch_conf(self):
 
2036
        # in an empty branch we decode the response properly
 
2037
        client = FakeClient()
 
2038
        client.add_expected_call(
 
2039
            'Branch.get_stacked_on_url', ('memory:///',),
 
2040
            'error', ('NotStacked',),)
 
2041
        client.add_success_response_with_body('# config file body', 'ok')
 
2042
        transport = MemoryTransport()
 
2043
        branch = self.make_remote_branch(transport, client)
 
2044
        config = branch.get_config_stack()
 
2045
        config.get("email")
 
2046
        config.get("log_format")
 
2047
        self.assertEqual(
 
2048
            [('call', 'Branch.get_stacked_on_url', ('memory:///',)),
 
2049
             ('call_expecting_body', 'Branch.get_config_file', ('memory:///',))],
 
2050
            client._calls)
 
2051
 
 
2052
    def test_set_branch_conf(self):
 
2053
        client = FakeClient()
 
2054
        client.add_expected_call(
 
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',))
 
2073
        transport = MemoryTransport()
 
2074
        branch = self.make_remote_branch(transport, client)
 
2075
        branch.lock_write()
 
2076
        config = branch.get_config_stack()
 
2077
        config.set('email', 'The Dude <lebowski@example.com>')
 
2078
        branch.unlock()
 
2079
        self.assertFinished(client)
 
2080
        self.assertEqual(
 
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'))],
 
2089
            client._calls)
 
2090
 
 
2091
 
1847
2092
class TestBranchLockWrite(RemoteBranchTestCase):
1848
2093
 
1849
2094
    def test_lock_write_unlockable(self):
1862
2107
        self.assertFinished(client)
1863
2108
 
1864
2109
 
 
2110
class TestBranchRevisionIdToRevno(RemoteBranchTestCase):
 
2111
 
 
2112
    def test_simple(self):
 
2113
        transport = MemoryTransport()
 
2114
        client = FakeClient(transport.base)
 
2115
        client.add_expected_call(
 
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',),)
 
2124
        transport.mkdir('quack')
 
2125
        transport = transport.clone('quack')
 
2126
        branch = self.make_remote_branch(transport, client)
 
2127
        self.assertEqual(0, branch.revision_id_to_revno('null:'))
 
2128
        self.assertRaises(errors.NoSuchRevision,
 
2129
            branch.revision_id_to_revno, 'unknown')
 
2130
        self.assertFinished(client)
 
2131
 
 
2132
    def test_dotted(self):
 
2133
        transport = MemoryTransport()
 
2134
        client = FakeClient(transport.base)
 
2135
        client.add_expected_call(
 
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',),)
 
2144
        transport.mkdir('quack')
 
2145
        transport = transport.clone('quack')
 
2146
        branch = self.make_remote_branch(transport, client)
 
2147
        self.assertEqual((0, ), branch.revision_id_to_dotted_revno('null:'))
 
2148
        self.assertRaises(errors.NoSuchRevision,
 
2149
            branch.revision_id_to_dotted_revno, 'unknown')
 
2150
        self.assertFinished(client)
 
2151
 
 
2152
    def test_dotted_no_smart_verb(self):
 
2153
        self.setup_smart_server_with_call_log()
 
2154
        branch = self.make_branch('.')
 
2155
        self.disable_verb('Branch.revision_id_to_revno')
 
2156
        self.reset_smart_call_log()
 
2157
        self.assertEqual((0, ),
 
2158
            branch.revision_id_to_dotted_revno('null:'))
 
2159
        self.assertLength(8, self.hpss_calls)
 
2160
 
 
2161
 
1865
2162
class TestBzrDirGetSetConfig(RemoteBzrDirTestCase):
1866
2163
 
1867
2164
    def test__get_config(self):
1881
2178
        self.reset_smart_call_log()
1882
2179
        config = bzrdir.get_config()
1883
2180
        config.set_default_stack_on('/')
1884
 
        self.assertLength(3, self.hpss_calls)
 
2181
        self.assertLength(4, self.hpss_calls)
1885
2182
 
1886
2183
    def test_backwards_compat_get_option(self):
1887
2184
        self.setup_smart_server_with_call_log()
1891
2188
        self.reset_smart_call_log()
1892
2189
        self.assertEqual(None,
1893
2190
            bzrdir._get_config().get_option('default_stack_on'))
1894
 
        self.assertLength(3, self.hpss_calls)
 
2191
        self.assertLength(4, self.hpss_calls)
1895
2192
 
1896
2193
 
1897
2194
class TestTransportIsReadonly(tests.TestCase):
2024
2321
            remote_repo_format.get_format_description())
2025
2322
 
2026
2323
 
 
2324
class TestRepositoryAllRevisionIds(TestRemoteRepository):
 
2325
 
 
2326
    def test_empty(self):
 
2327
        transport_path = 'quack'
 
2328
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2329
        client.add_success_response_with_body('', 'ok')
 
2330
        self.assertEqual([], repo.all_revision_ids())
 
2331
        self.assertEqual(
 
2332
            [('call_expecting_body', 'Repository.all_revision_ids',
 
2333
             ('quack/',))],
 
2334
            client._calls)
 
2335
 
 
2336
    def test_with_some_content(self):
 
2337
        transport_path = 'quack'
 
2338
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2339
        client.add_success_response_with_body(
 
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/',))],
 
2346
            client._calls)
 
2347
 
 
2348
 
2027
2349
class TestRepositoryGatherStats(TestRemoteRepository):
2028
2350
 
2029
2351
    def test_revid_none(self):
2082
2404
                         result)
2083
2405
 
2084
2406
 
 
2407
class TestRepositoryBreakLock(TestRemoteRepository):
 
2408
 
 
2409
    def test_break_lock(self):
 
2410
        transport_path = 'quack'
 
2411
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2412
        client.add_success_response('ok')
 
2413
        repo.break_lock()
 
2414
        self.assertEqual(
 
2415
            [('call', 'Repository.break_lock', ('quack/',))],
 
2416
            client._calls)
 
2417
 
 
2418
 
 
2419
class TestRepositoryGetSerializerFormat(TestRemoteRepository):
 
2420
 
 
2421
    def test_get_serializer_format(self):
 
2422
        transport_path = 'hill'
 
2423
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2424
        client.add_success_response('ok', '7')
 
2425
        self.assertEqual('7', repo.get_serializer_format())
 
2426
        self.assertEqual(
 
2427
            [('call', 'VersionedFileRepository.get_serializer_format',
 
2428
              ('hill/', ))],
 
2429
            client._calls)
 
2430
 
 
2431
 
 
2432
class TestRepositoryReconcile(TestRemoteRepository):
 
2433
 
 
2434
    def test_reconcile(self):
 
2435
        transport_path = 'hill'
 
2436
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2437
        body = ("garbage_inventories: 2\n"
 
2438
                "inconsistent_parents: 3\n")
 
2439
        client.add_expected_call(
 
2440
            'Repository.lock_write', ('hill/', ''),
 
2441
            'success', ('ok', 'a token'))
 
2442
        client.add_success_response_with_body(body, 'ok')
 
2443
        reconciler = repo.reconcile()
 
2444
        self.assertEqual(
 
2445
            [('call', 'Repository.lock_write', ('hill/', '')),
 
2446
             ('call_expecting_body', 'Repository.reconcile',
 
2447
                ('hill/', 'a token'))],
 
2448
            client._calls)
 
2449
        self.assertEqual(2, reconciler.garbage_inventories)
 
2450
        self.assertEqual(3, reconciler.inconsistent_parents)
 
2451
 
 
2452
 
 
2453
class TestRepositoryGetRevisionSignatureText(TestRemoteRepository):
 
2454
 
 
2455
    def test_text(self):
 
2456
        # ('ok',), body with signature text
 
2457
        transport_path = 'quack'
 
2458
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2459
        client.add_success_response_with_body(
 
2460
            'THETEXT', 'ok')
 
2461
        self.assertEqual("THETEXT", repo.get_signature_text("revid"))
 
2462
        self.assertEqual(
 
2463
            [('call_expecting_body', 'Repository.get_revision_signature_text',
 
2464
             ('quack/', 'revid'))],
 
2465
            client._calls)
 
2466
 
 
2467
    def test_no_signature(self):
 
2468
        transport_path = 'quick'
 
2469
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2470
        client.add_error_response('nosuchrevision', 'unknown')
 
2471
        self.assertRaises(errors.NoSuchRevision, repo.get_signature_text,
 
2472
                "unknown")
 
2473
        self.assertEqual(
 
2474
            [('call_expecting_body', 'Repository.get_revision_signature_text',
 
2475
              ('quick/', 'unknown'))],
 
2476
            client._calls)
 
2477
 
 
2478
 
2085
2479
class TestRepositoryGetGraph(TestRemoteRepository):
2086
2480
 
2087
2481
    def test_get_graph(self):
2092
2486
        self.assertNotEqual(graph._parents_provider, repo)
2093
2487
 
2094
2488
 
 
2489
class TestRepositoryAddSignatureText(TestRemoteRepository):
 
2490
 
 
2491
    def test_add_signature_text(self):
 
2492
        transport_path = 'quack'
 
2493
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2494
        client.add_expected_call(
 
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)
 
2504
        repo.lock_write()
 
2505
        repo.start_write_group()
 
2506
        self.assertIs(None,
 
2507
            repo.add_signature_text("rev1", "every bloody emperor"))
 
2508
        self.assertEqual(
 
2509
            ('call_with_body_bytes_expecting_body',
 
2510
              'Repository.add_signature_text',
 
2511
                ('quack/', 'a token', 'rev1', 'token1'),
 
2512
              'every bloody emperor'),
 
2513
            client._calls[-1])
 
2514
 
 
2515
 
2095
2516
class TestRepositoryGetParentMap(TestRemoteRepository):
2096
2517
 
2097
2518
    def test_get_parent_map_caching(self):
2147
2568
        parents = repo.get_parent_map([rev_id])
2148
2569
        self.assertEqual(
2149
2570
            [('call_with_body_bytes_expecting_body',
2150
 
              'Repository.get_parent_map', ('quack/', 'include-missing:',
2151
 
              rev_id), '\n\n0'),
 
2571
              'Repository.get_parent_map',
 
2572
              ('quack/', 'include-missing:', rev_id), '\n\n0'),
2152
2573
             ('disconnect medium',),
2153
2574
             ('call_expecting_body', 'Repository.get_revision_graph',
2154
2575
              ('quack/', ''))],
2274
2695
        self.assertEqual({}, repo.get_parent_map(['non-existant']))
2275
2696
        self.assertLength(0, self.hpss_calls)
2276
2697
 
 
2698
    def test_exposes_get_cached_parent_map(self):
 
2699
        """RemoteRepository exposes get_cached_parent_map from
 
2700
        _unstacked_provider
 
2701
        """
 
2702
        r1 = u'\u0e33'.encode('utf8')
 
2703
        r2 = u'\u0dab'.encode('utf8')
 
2704
        lines = [' '.join([r2, r1]), r1]
 
2705
        encoded_body = bz2.compress('\n'.join(lines))
 
2706
 
 
2707
        transport_path = 'quack'
 
2708
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2709
        client.add_success_response_with_body(encoded_body, 'ok')
 
2710
        repo.lock_read()
 
2711
        # get_cached_parent_map should *not* trigger an RPC
 
2712
        self.assertEqual({}, repo.get_cached_parent_map([r1]))
 
2713
        self.assertEqual([], client._calls)
 
2714
        self.assertEqual({r2: (r1,)}, repo.get_parent_map([r2]))
 
2715
        self.assertEqual({r1: (NULL_REVISION,)},
 
2716
            repo.get_cached_parent_map([r1]))
 
2717
        self.assertEqual(
 
2718
            [('call_with_body_bytes_expecting_body',
 
2719
              'Repository.get_parent_map', ('quack/', 'include-missing:', r2),
 
2720
              '\n\n0')],
 
2721
            client._calls)
 
2722
        repo.unlock()
 
2723
 
2277
2724
 
2278
2725
class TestGetParentMapAllowsNew(tests.TestCaseWithTransport):
2279
2726
 
2294
2741
        self.assertEqual({'rev1': ('null:',)}, graph.get_parent_map(['rev1']))
2295
2742
 
2296
2743
 
 
2744
class TestRepositoryGetRevisions(TestRemoteRepository):
 
2745
 
 
2746
    def test_hpss_missing_revision(self):
 
2747
        transport_path = 'quack'
 
2748
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2749
        client.add_success_response_with_body(
 
2750
            '', 'ok', '10')
 
2751
        self.assertRaises(errors.NoSuchRevision, repo.get_revisions,
 
2752
            ['somerev1', 'anotherrev2'])
 
2753
        self.assertEqual(
 
2754
            [('call_with_body_bytes_expecting_body', 'Repository.iter_revisions',
 
2755
             ('quack/', ), "somerev1\nanotherrev2")],
 
2756
            client._calls)
 
2757
 
 
2758
    def test_hpss_get_single_revision(self):
 
2759
        transport_path = 'quack'
 
2760
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2761
        somerev1 = Revision("somerev1")
 
2762
        somerev1.committer = "Joe Committer <joe@example.com>"
 
2763
        somerev1.timestamp = 1321828927
 
2764
        somerev1.timezone = -60
 
2765
        somerev1.inventory_sha1 = "691b39be74c67b1212a75fcb19c433aaed903c2b"
 
2766
        somerev1.message = "Message"
 
2767
        body = zlib.compress(chk_bencode_serializer.write_revision_to_string(
 
2768
            somerev1))
 
2769
        # Split up body into two bits to make sure the zlib compression object
 
2770
        # gets data fed twice.
 
2771
        client.add_success_response_with_body(
 
2772
                [body[:10], body[10:]], 'ok', '10')
 
2773
        revs = repo.get_revisions(['somerev1'])
 
2774
        self.assertEqual(revs, [somerev1])
 
2775
        self.assertEqual(
 
2776
            [('call_with_body_bytes_expecting_body', 'Repository.iter_revisions',
 
2777
             ('quack/', ), "somerev1")],
 
2778
            client._calls)
 
2779
 
 
2780
 
2297
2781
class TestRepositoryGetRevisionGraph(TestRemoteRepository):
2298
2782
 
2299
2783
    def test_null_revision(self):
2450
2934
                              call.call.method == verb])
2451
2935
 
2452
2936
 
 
2937
class TestRepositoryHasSignatureForRevisionId(TestRemoteRepository):
 
2938
 
 
2939
    def test_has_signature_for_revision_id(self):
 
2940
        # ('yes', ) for Repository.has_signature_for_revision_id -> 'True'.
 
2941
        transport_path = 'quack'
 
2942
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2943
        client.add_success_response('yes')
 
2944
        result = repo.has_signature_for_revision_id('A')
 
2945
        self.assertEqual(
 
2946
            [('call', 'Repository.has_signature_for_revision_id',
 
2947
              ('quack/', 'A'))],
 
2948
            client._calls)
 
2949
        self.assertEqual(True, result)
 
2950
 
 
2951
    def test_is_not_shared(self):
 
2952
        # ('no', ) for Repository.has_signature_for_revision_id -> 'False'.
 
2953
        transport_path = 'qwack'
 
2954
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2955
        client.add_success_response('no')
 
2956
        result = repo.has_signature_for_revision_id('A')
 
2957
        self.assertEqual(
 
2958
            [('call', 'Repository.has_signature_for_revision_id',
 
2959
              ('qwack/', 'A'))],
 
2960
            client._calls)
 
2961
        self.assertEqual(False, result)
 
2962
 
 
2963
 
 
2964
class TestRepositoryPhysicalLockStatus(TestRemoteRepository):
 
2965
 
 
2966
    def test_get_physical_lock_status_yes(self):
 
2967
        transport_path = 'qwack'
 
2968
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2969
        client.add_success_response('yes')
 
2970
        result = repo.get_physical_lock_status()
 
2971
        self.assertEqual(
 
2972
            [('call', 'Repository.get_physical_lock_status',
 
2973
              ('qwack/', ))],
 
2974
            client._calls)
 
2975
        self.assertEqual(True, result)
 
2976
 
 
2977
    def test_get_physical_lock_status_no(self):
 
2978
        transport_path = 'qwack'
 
2979
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2980
        client.add_success_response('no')
 
2981
        result = repo.get_physical_lock_status()
 
2982
        self.assertEqual(
 
2983
            [('call', 'Repository.get_physical_lock_status',
 
2984
              ('qwack/', ))],
 
2985
            client._calls)
 
2986
        self.assertEqual(False, result)
 
2987
 
 
2988
 
2453
2989
class TestRepositoryIsShared(TestRemoteRepository):
2454
2990
 
2455
2991
    def test_is_shared(self):
2475
3011
        self.assertEqual(False, result)
2476
3012
 
2477
3013
 
 
3014
class TestRepositoryMakeWorkingTrees(TestRemoteRepository):
 
3015
 
 
3016
    def test_make_working_trees(self):
 
3017
        # ('yes', ) for Repository.make_working_trees -> 'True'.
 
3018
        transport_path = 'quack'
 
3019
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3020
        client.add_success_response('yes')
 
3021
        result = repo.make_working_trees()
 
3022
        self.assertEqual(
 
3023
            [('call', 'Repository.make_working_trees', ('quack/',))],
 
3024
            client._calls)
 
3025
        self.assertEqual(True, result)
 
3026
 
 
3027
    def test_no_working_trees(self):
 
3028
        # ('no', ) for Repository.make_working_trees -> 'False'.
 
3029
        transport_path = 'qwack'
 
3030
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3031
        client.add_success_response('no')
 
3032
        result = repo.make_working_trees()
 
3033
        self.assertEqual(
 
3034
            [('call', 'Repository.make_working_trees', ('qwack/',))],
 
3035
            client._calls)
 
3036
        self.assertEqual(False, result)
 
3037
 
 
3038
 
2478
3039
class TestRepositoryLockWrite(TestRemoteRepository):
2479
3040
 
2480
3041
    def test_lock_write(self):
2506
3067
            client._calls)
2507
3068
 
2508
3069
 
 
3070
class TestRepositoryWriteGroups(TestRemoteRepository):
 
3071
 
 
3072
    def test_start_write_group(self):
 
3073
        transport_path = 'quack'
 
3074
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3075
        client.add_expected_call(
 
3076
            'Repository.lock_write', ('quack/', ''),
 
3077
            'success', ('ok', 'a token'))
 
3078
        client.add_expected_call(
 
3079
            'Repository.start_write_group', ('quack/', 'a token'),
 
3080
            'success', ('ok', ('token1', )))
 
3081
        repo.lock_write()
 
3082
        repo.start_write_group()
 
3083
 
 
3084
    def test_start_write_group_unsuspendable(self):
 
3085
        # Some repositories do not support suspending write
 
3086
        # groups. For those, fall back to the "real" repository.
 
3087
        transport_path = 'quack'
 
3088
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3089
        def stub_ensure_real():
 
3090
            client._calls.append(('_ensure_real',))
 
3091
            repo._real_repository = _StubRealPackRepository(client._calls)
 
3092
        repo._ensure_real = stub_ensure_real
 
3093
        client.add_expected_call(
 
3094
            'Repository.lock_write', ('quack/', ''),
 
3095
            'success', ('ok', 'a token'))
 
3096
        client.add_expected_call(
 
3097
            'Repository.start_write_group', ('quack/', 'a token'),
 
3098
            'error', ('UnsuspendableWriteGroup',))
 
3099
        repo.lock_write()
 
3100
        repo.start_write_group()
 
3101
        self.assertEqual(client._calls[-2:], [ 
 
3102
            ('_ensure_real',),
 
3103
            ('start_write_group',)])
 
3104
 
 
3105
    def test_commit_write_group(self):
 
3106
        transport_path = 'quack'
 
3107
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3108
        client.add_expected_call(
 
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',))
 
3117
        repo.lock_write()
 
3118
        repo.start_write_group()
 
3119
        repo.commit_write_group()
 
3120
 
 
3121
    def test_abort_write_group(self):
 
3122
        transport_path = 'quack'
 
3123
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3124
        client.add_expected_call(
 
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',))
 
3133
        repo.lock_write()
 
3134
        repo.start_write_group()
 
3135
        repo.abort_write_group(False)
 
3136
 
 
3137
    def test_suspend_write_group(self):
 
3138
        transport_path = 'quack'
 
3139
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3140
        self.assertEqual([], repo.suspend_write_group())
 
3141
 
 
3142
    def test_resume_write_group(self):
 
3143
        transport_path = 'quack'
 
3144
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3145
        client.add_expected_call(
 
3146
            'Repository.lock_write', ('quack/', ''),
 
3147
            'success', ('ok', 'a token'))
 
3148
        client.add_expected_call(
 
3149
            'Repository.check_write_group', ('quack/', 'a token', ['token1']),
 
3150
            'success', ('ok',))
 
3151
        repo.lock_write()
 
3152
        repo.resume_write_group(['token1'])
 
3153
 
 
3154
 
2509
3155
class TestRepositorySetMakeWorkingTrees(TestRemoteRepository):
2510
3156
 
2511
3157
    def test_backwards_compat(self):
2570
3216
        self.assertEqual([], client._calls)
2571
3217
 
2572
3218
 
 
3219
class TestRepositoryIterFilesBytes(TestRemoteRepository):
 
3220
    """Test Repository.iter_file_bytes."""
 
3221
 
 
3222
    def test_single(self):
 
3223
        transport_path = 'quack'
 
3224
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3225
        client.add_expected_call(
 
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)
 
3232
 
 
3233
    def test_missing(self):
 
3234
        transport_path = 'quack'
 
3235
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3236
        client.add_expected_call(
 
3237
            'Repository.iter_files_bytes',
 
3238
                ('quack/', ),
 
3239
            'error', ('RevisionNotPresent', 'somefile', 'somerev'),
 
3240
            iter(["absent\0somefile\0somerev\n"]))
 
3241
        self.assertRaises(errors.RevisionNotPresent, list,
 
3242
                repo.iter_files_bytes(
 
3243
                [("somefile", "somerev", "myid")]))
 
3244
 
 
3245
 
2573
3246
class TestRepositoryInsertStreamBase(TestRemoteRepository):
2574
3247
    """Base class for Repository.insert_stream and .insert_stream_1.19
2575
3248
    tests.
2597
3270
    """
2598
3271
 
2599
3272
    def setUp(self):
2600
 
        TestRemoteRepository.setUp(self)
 
3273
        super(TestRepositoryInsertStream, self).setUp()
2601
3274
        self.disable_verb('Repository.insert_stream_1.19')
2602
3275
 
2603
3276
    def test_unlocked_repo(self):
2850
3523
        self.calls = calls
2851
3524
        self._pack_collection = _StubPackCollection(calls)
2852
3525
 
 
3526
    def start_write_group(self):
 
3527
        self.calls.append(('start_write_group',))
 
3528
 
2853
3529
    def is_in_write_group(self):
2854
3530
        return False
2855
3531
 
3279
3955
        :result: The revision ids in the stream, in the order seen,
3280
3956
            the topological order of revisions in the source.
3281
3957
        """
3282
 
        unordered_format = bzrdir.format_registry.get(format)()
 
3958
        unordered_format = controldir.format_registry.get(format)()
3283
3959
        target_repository_format = unordered_format.repository_format
3284
3960
        # Cross check
3285
3961
        self.assertEqual(order, target_repository_format._fetch_order)
3293
3969
        revs = [r for (r,ps) in graph.iter_ancestry([tip])
3294
3970
                if r != NULL_REVISION]
3295
3971
        revs.reverse()
3296
 
        search = _mod_graph.PendingAncestryResult([tip], stacked.repository)
 
3972
        search = vf_search.PendingAncestryResult([tip], stacked.repository)
3297
3973
        self.reset_smart_call_log()
3298
3974
        stream = source.get_stream(search)
3299
3975
        # We trust that if a revision is in the stream the rest of the new
3405
4081
        self.hpss_calls = []
3406
4082
        local.repository.fetch(
3407
4083
            remote_branch.repository,
3408
 
            fetch_spec=_mod_graph.EverythingResult(remote_branch.repository))
 
4084
            fetch_spec=vf_search.EverythingResult(remote_branch.repository))
3409
4085
        self.assertEqual(['Repository.get_stream_1.19'], self.hpss_calls)
3410
4086
 
3411
4087
    def override_verb(self, verb_name, verb):
3412
4088
        request_handlers = request.request_handlers
3413
4089
        orig_verb = request_handlers.get(verb_name)
 
4090
        orig_info = request_handlers.get_info(verb_name)
3414
4091
        request_handlers.register(verb_name, verb, override_existing=True)
3415
4092
        self.addCleanup(request_handlers.register, verb_name, orig_verb,
3416
 
                override_existing=True)
 
4093
                override_existing=True, info=orig_info)
3417
4094
 
3418
4095
    def test_fetch_everything_backwards_compat(self):
3419
4096
        """Can fetch with EverythingResult even with pre 2.4 servers.
3444
4121
        self.hpss_calls = []
3445
4122
        local.repository.fetch(
3446
4123
            remote_branch.repository,
3447
 
            fetch_spec=_mod_graph.EverythingResult(remote_branch.repository))
 
4124
            fetch_spec=vf_search.EverythingResult(remote_branch.repository))
3448
4125
        # make sure the overridden verb was used
3449
4126
        self.assertLength(1, verb_log)
3450
4127
        # more than one HPSS call is needed, but because it's a VFS callback
3452
4129
        self.assertTrue(len(self.hpss_calls) > 1)
3453
4130
 
3454
4131
 
3455
 
class TestUpdateBoundBranch(tests.TestCaseWithTransport):
3456
 
 
3457
 
    def test_bug_786980(self):
 
4132
class TestUpdateBoundBranchWithModifiedBoundLocation(
 
4133
    tests.TestCaseWithTransport):
 
4134
    """Ensure correct handling of bound_location modifications.
 
4135
 
 
4136
    This is tested against a smart server as http://pad.lv/786980 was about a
 
4137
    ReadOnlyError (write attempt during a read-only transaction) which can only
 
4138
    happen in this context.
 
4139
    """
 
4140
 
 
4141
    def setUp(self):
 
4142
        super(TestUpdateBoundBranchWithModifiedBoundLocation, self).setUp()
3458
4143
        self.transport_server = test_server.SmartTCPServer_for_testing
3459
 
        wt = self.make_branch_and_tree('master')
3460
 
        checkout = wt.branch.create_checkout('checkout')
3461
 
        wt.commit('add stuff')
3462
 
        last_revid = wt.commit('even more stuff')
3463
 
        bound_location = checkout.branch.get_bound_location()
 
4144
 
 
4145
    def make_master_and_checkout(self, master_name, checkout_name):
 
4146
        # Create the master branch and its associated checkout
 
4147
        self.master = self.make_branch_and_tree(master_name)
 
4148
        self.checkout = self.master.branch.create_checkout(checkout_name)
 
4149
        # Modify the master branch so there is something to update
 
4150
        self.master.commit('add stuff')
 
4151
        self.last_revid = self.master.commit('even more stuff')
 
4152
        self.bound_location = self.checkout.branch.get_bound_location()
 
4153
 
 
4154
    def assertUpdateSucceeds(self, new_location):
 
4155
        self.checkout.branch.set_bound_location(new_location)
 
4156
        self.checkout.update()
 
4157
        self.assertEqual(self.last_revid, self.checkout.last_revision())
 
4158
 
 
4159
    def test_without_final_slash(self):
 
4160
        self.make_master_and_checkout('master', 'checkout')
3464
4161
        # For unclear reasons some users have a bound_location without a final
3465
4162
        # '/', simulate that by forcing such a value
3466
 
        self.assertEndsWith(bound_location, '/')
3467
 
        new_location = bound_location.rstrip('/')
3468
 
        checkout.branch.set_bound_location(new_location)
3469
 
        # bug 786980 was raising ReadOnlyError: A write attempt was made in a
3470
 
        # read only transaction during the update()
3471
 
        checkout.update()
3472
 
        self.assertEquals(last_revid, checkout.last_revision())
 
4163
        self.assertEndsWith(self.bound_location, '/')
 
4164
        self.assertUpdateSucceeds(self.bound_location.rstrip('/'))
 
4165
 
 
4166
    def test_plus_sign(self):
 
4167
        self.make_master_and_checkout('+master', 'checkout')
 
4168
        self.assertUpdateSucceeds(self.bound_location.replace('%2B', '+', 1))
 
4169
 
 
4170
    def test_tilda(self):
 
4171
        # Embed ~ in the middle of the path just to avoid any $HOME
 
4172
        # interpretation
 
4173
        self.make_master_and_checkout('mas~ter', 'checkout')
 
4174
        self.assertUpdateSucceeds(self.bound_location.replace('%2E', '~', 1))
 
4175
 
 
4176
 
 
4177
class TestWithCustomErrorHandler(RemoteBranchTestCase):
 
4178
 
 
4179
    def test_no_context(self):
 
4180
        class OutOfCoffee(errors.BzrError):
 
4181
            """A dummy exception for testing."""
 
4182
 
 
4183
            def __init__(self, urgency):
 
4184
                self.urgency = urgency
 
4185
        remote.no_context_error_translators.register("OutOfCoffee",
 
4186
            lambda err: OutOfCoffee(err.error_args[0]))
 
4187
        transport = MemoryTransport()
 
4188
        client = FakeClient(transport.base)
 
4189
        client.add_expected_call(
 
4190
            'Branch.get_stacked_on_url', ('quack/',),
 
4191
            'error', ('NotStacked',))
 
4192
        client.add_expected_call(
 
4193
            'Branch.last_revision_info',
 
4194
            ('quack/',),
 
4195
            'error', ('OutOfCoffee', 'low'))
 
4196
        transport.mkdir('quack')
 
4197
        transport = transport.clone('quack')
 
4198
        branch = self.make_remote_branch(transport, client)
 
4199
        self.assertRaises(OutOfCoffee, branch.last_revision_info)
 
4200
        self.assertFinished(client)
 
4201
 
 
4202
    def test_with_context(self):
 
4203
        class OutOfTea(errors.BzrError):
 
4204
            def __init__(self, branch, urgency):
 
4205
                self.branch = branch
 
4206
                self.urgency = urgency
 
4207
        remote.error_translators.register("OutOfTea",
 
4208
            lambda err, find, path: OutOfTea(err.error_args[0],
 
4209
                find("branch")))
 
4210
        transport = MemoryTransport()
 
4211
        client = FakeClient(transport.base)
 
4212
        client.add_expected_call(
 
4213
            'Branch.get_stacked_on_url', ('quack/',),
 
4214
            'error', ('NotStacked',))
 
4215
        client.add_expected_call(
 
4216
            'Branch.last_revision_info',
 
4217
            ('quack/',),
 
4218
            'error', ('OutOfTea', 'low'))
 
4219
        transport.mkdir('quack')
 
4220
        transport = transport.clone('quack')
 
4221
        branch = self.make_remote_branch(transport, client)
 
4222
        self.assertRaises(OutOfTea, branch.last_revision_info)
 
4223
        self.assertFinished(client)
 
4224
 
 
4225
 
 
4226
class TestRepositoryPack(TestRemoteRepository):
 
4227
 
 
4228
    def test_pack(self):
 
4229
        transport_path = 'quack'
 
4230
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4231
        client.add_expected_call(
 
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', ))
 
4240
        repo.pack()
 
4241
 
 
4242
    def test_pack_with_hint(self):
 
4243
        transport_path = 'quack'
 
4244
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4245
        client.add_expected_call(
 
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', ))
 
4254
        repo.pack(['hinta', 'hintb'])
 
4255
 
 
4256
 
 
4257
class TestRepositoryIterInventories(TestRemoteRepository):
 
4258
    """Test Repository.iter_inventories."""
 
4259
 
 
4260
    def _serialize_inv_delta(self, old_name, new_name, delta):
 
4261
        serializer = inventory_delta.InventoryDeltaSerializer(True, False)
 
4262
        return "".join(serializer.delta_to_lines(old_name, new_name, delta))
 
4263
 
 
4264
    def test_single_empty(self):
 
4265
        transport_path = 'quack'
 
4266
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4267
        fmt = controldir.format_registry.get('2a')().repository_format
 
4268
        repo._format = fmt
 
4269
        stream = [('inventory-deltas', [
 
4270
            versionedfile.FulltextContentFactory('somerevid', None, None,
 
4271
                self._serialize_inv_delta('null:', 'somerevid', []))])]
 
4272
        client.add_expected_call(
 
4273
            'VersionedFileRepository.get_inventories', ('quack/', 'unordered'),
 
4274
            'success', ('ok', ),
 
4275
            _stream_to_byte_stream(stream, fmt))
 
4276
        ret = list(repo.iter_inventories(["somerevid"]))
 
4277
        self.assertLength(1, ret)
 
4278
        inv = ret[0]
 
4279
        self.assertEqual("somerevid", inv.revision_id)
 
4280
 
 
4281
    def test_empty(self):
 
4282
        transport_path = 'quack'
 
4283
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4284
        ret = list(repo.iter_inventories([]))
 
4285
        self.assertEqual(ret, [])
 
4286
 
 
4287
    def test_missing(self):
 
4288
        transport_path = 'quack'
 
4289
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4290
        client.add_expected_call(
 
4291
            'VersionedFileRepository.get_inventories', ('quack/', 'unordered'),
 
4292
            'success', ('ok', ), iter([]))
 
4293
        self.assertRaises(errors.NoSuchRevision, list, repo.iter_inventories(
 
4294
            ["somerevid"]))