~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_remote.py

  • Committer: Jelmer Vernooij
  • Date: 2012-01-04 16:10:04 UTC
  • mto: This revision was merged to the branch mainline in revision 6424.
  • Revision ID: jelmer@samba.org-20120104161004-2gepg7c0famy3lq6
Fix config name.

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
 
26
26
import bz2
27
27
from cStringIO import StringIO
 
28
import zlib
28
29
 
29
30
from bzrlib import (
30
31
    branch,
32
33
    config,
33
34
    controldir,
34
35
    errors,
35
 
    graph,
 
36
    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
    )
115
123
 
116
124
    def test_remote_branch_revision_history(self):
117
125
        b = BzrDir.open_from_transport(self.transport).open_branch()
118
 
        self.assertEqual([], b.revision_history())
 
126
        self.assertEqual([],
 
127
            self.applyDeprecated(deprecated_in((2, 5, 0)), b.revision_history))
119
128
        r1 = self.local_wt.commit('1st commit')
120
129
        r2 = self.local_wt.commit('1st commit', rev_id=u'\xc8'.encode('utf8'))
121
 
        self.assertEqual([r1, r2], b.revision_history())
 
130
        self.assertEqual([r1, r2],
 
131
            self.applyDeprecated(deprecated_in((2, 5, 0)), b.revision_history))
122
132
 
123
133
    def test_find_correct_format(self):
124
134
        """Should open a RemoteBzrDir over a RemoteTransport"""
165
175
    def test_remote_branch_set_append_revisions_only(self):
166
176
        # Make a format 1.9 branch, which supports append_revisions_only
167
177
        branch = self.make_branch('branch', format='1.9')
168
 
        config = branch.get_config()
169
178
        branch.set_append_revisions_only(True)
 
179
        config = branch.get_config_stack()
170
180
        self.assertEqual(
171
 
            'True', config.get_user_option('append_revisions_only'))
 
181
            True, config.get('append_revisions_only'))
172
182
        branch.set_append_revisions_only(False)
 
183
        config = branch.get_config_stack()
173
184
        self.assertEqual(
174
 
            'False', config.get_user_option('append_revisions_only'))
 
185
            False, config.get('append_revisions_only'))
175
186
 
176
187
    def test_remote_branch_set_append_revisions_only_upgrade_reqd(self):
177
188
        branch = self.make_branch('branch', format='knit')
178
 
        config = branch.get_config()
179
189
        self.assertRaises(
180
190
            errors.UpgradeRequired, branch.set_append_revisions_only, True)
181
191
 
481
491
        self.assertEqual(None, result._branch_format)
482
492
        self.assertFinished(client)
483
493
 
 
494
    def test_unknown(self):
 
495
        transport = self.get_transport('quack')
 
496
        referenced = self.make_branch('referenced')
 
497
        expected = referenced.bzrdir.cloning_metadir()
 
498
        client = FakeClient(transport.base)
 
499
        client.add_expected_call(
 
500
            'BzrDir.cloning_metadir', ('quack/', 'False'),
 
501
            'success', ('unknown', 'unknown', ('branch', ''))),
 
502
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
503
            _client=client)
 
504
        self.assertRaises(errors.UnknownFormatError, a_bzrdir.cloning_metadir)
 
505
 
 
506
 
 
507
class TestBzrDirCheckoutMetaDir(TestRemote):
 
508
 
 
509
    def test__get_checkout_format(self):
 
510
        transport = MemoryTransport()
 
511
        client = FakeClient(transport.base)
 
512
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
 
513
        control_name = reference_bzrdir_format.network_name()
 
514
        client.add_expected_call(
 
515
            'BzrDir.checkout_metadir', ('quack/', ),
 
516
            'success', (control_name, '', ''))
 
517
        transport.mkdir('quack')
 
518
        transport = transport.clone('quack')
 
519
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
520
            _client=client)
 
521
        result = a_bzrdir.checkout_metadir()
 
522
        # We should have got a reference control dir with default branch and
 
523
        # repository formats.
 
524
        self.assertEqual(bzrdir.BzrDirMetaFormat1, type(result))
 
525
        self.assertEqual(None, result._repository_format)
 
526
        self.assertEqual(None, result._branch_format)
 
527
        self.assertFinished(client)
 
528
 
 
529
    def test_unknown_format(self):
 
530
        transport = MemoryTransport()
 
531
        client = FakeClient(transport.base)
 
532
        client.add_expected_call(
 
533
            'BzrDir.checkout_metadir', ('quack/',),
 
534
            'success', ('dontknow', '', ''))
 
535
        transport.mkdir('quack')
 
536
        transport = transport.clone('quack')
 
537
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
538
            _client=client)
 
539
        self.assertRaises(errors.UnknownFormatError,
 
540
            a_bzrdir.checkout_metadir)
 
541
        self.assertFinished(client)
 
542
 
 
543
 
 
544
class TestBzrDirDestroyBranch(TestRemote):
 
545
 
 
546
    def test_destroy_default(self):
 
547
        transport = self.get_transport('quack')
 
548
        referenced = self.make_branch('referenced')
 
549
        client = FakeClient(transport.base)
 
550
        client.add_expected_call(
 
551
            'BzrDir.destroy_branch', ('quack/', ),
 
552
            'success', ('ok',)),
 
553
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
554
            _client=client)
 
555
        a_bzrdir.destroy_branch()
 
556
        self.assertFinished(client)
 
557
 
 
558
    def test_destroy_named(self):
 
559
        transport = self.get_transport('quack')
 
560
        referenced = self.make_branch('referenced')
 
561
        client = FakeClient(transport.base)
 
562
        client.add_expected_call(
 
563
            'BzrDir.destroy_branch', ('quack/', "foo"),
 
564
            'success', ('ok',)),
 
565
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
566
            _client=client)
 
567
        a_bzrdir.destroy_branch("foo")
 
568
        self.assertFinished(client)
 
569
 
 
570
 
 
571
class TestBzrDirHasWorkingTree(TestRemote):
 
572
 
 
573
    def test_has_workingtree(self):
 
574
        transport = self.get_transport('quack')
 
575
        client = FakeClient(transport.base)
 
576
        client.add_expected_call(
 
577
            'BzrDir.has_workingtree', ('quack/',),
 
578
            'success', ('yes',)),
 
579
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
580
            _client=client)
 
581
        self.assertTrue(a_bzrdir.has_workingtree())
 
582
        self.assertFinished(client)
 
583
 
 
584
    def test_no_workingtree(self):
 
585
        transport = self.get_transport('quack')
 
586
        client = FakeClient(transport.base)
 
587
        client.add_expected_call(
 
588
            'BzrDir.has_workingtree', ('quack/',),
 
589
            'success', ('no',)),
 
590
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
591
            _client=client)
 
592
        self.assertFalse(a_bzrdir.has_workingtree())
 
593
        self.assertFinished(client)
 
594
 
 
595
 
 
596
class TestBzrDirDestroyRepository(TestRemote):
 
597
 
 
598
    def test_destroy_repository(self):
 
599
        transport = self.get_transport('quack')
 
600
        client = FakeClient(transport.base)
 
601
        client.add_expected_call(
 
602
            'BzrDir.destroy_repository', ('quack/',),
 
603
            'success', ('ok',)),
 
604
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
605
            _client=client)
 
606
        a_bzrdir.destroy_repository()
 
607
        self.assertFinished(client)
 
608
 
484
609
 
485
610
class TestBzrDirOpen(TestRemote):
486
611
 
610
735
        # _get_tree_branch is a form of open_branch, but it should only ask for
611
736
        # branch opening, not any other network requests.
612
737
        calls = []
613
 
        def open_branch(name=None):
 
738
        def open_branch(name=None, possible_transports=None):
614
739
            calls.append("Called")
615
740
            return "a-branch"
616
741
        transport = MemoryTransport()
808
933
        # name.
809
934
        client.add_success_response_with_body(
810
935
            "Bazaar-NG meta directory, format 1\n", 'ok')
 
936
        client.add_success_response('stat', '0', '65535')
811
937
        client.add_success_response_with_body(
812
938
            reference_format.get_format_string(), 'ok')
813
939
        # PackRepository wants to do a stat
822
948
             ('call', 'BzrDir.find_repositoryV2', ('quack/',)),
823
949
             ('call', 'BzrDir.find_repository', ('quack/',)),
824
950
             ('call_expecting_body', 'get', ('/quack/.bzr/branch-format',)),
 
951
             ('call', 'stat', ('/quack/.bzr',)),
825
952
             ('call_expecting_body', 'get', ('/quack/.bzr/repository/format',)),
826
953
             ('call', 'stat', ('/quack/.bzr/repository',)),
827
954
             ],
841
968
        # name.
842
969
        client.add_success_response_with_body(
843
970
            "Bazaar-NG meta directory, format 1\n", 'ok')
 
971
        client.add_success_response('stat', '0', '65535')
844
972
        client.add_success_response_with_body(
845
973
            reference_format.get_format_string(), 'ok')
846
974
        # PackRepository wants to do a stat
854
982
            [('call', 'BzrDir.find_repositoryV3', ('quack/',)),
855
983
             ('call', 'BzrDir.find_repositoryV2', ('quack/',)),
856
984
             ('call_expecting_body', 'get', ('/quack/.bzr/branch-format',)),
 
985
             ('call', 'stat', ('/quack/.bzr',)),
857
986
             ('call_expecting_body', 'get', ('/quack/.bzr/repository/format',)),
858
987
             ('call', 'stat', ('/quack/.bzr/repository',)),
859
988
             ],
996
1125
        return RemoteBranch(bzrdir, repo, _client=client, format=format)
997
1126
 
998
1127
 
 
1128
class TestBranchBreakLock(RemoteBranchTestCase):
 
1129
 
 
1130
    def test_break_lock(self):
 
1131
        transport_path = 'quack'
 
1132
        transport = MemoryTransport()
 
1133
        client = FakeClient(transport.base)
 
1134
        client.add_expected_call(
 
1135
            'Branch.get_stacked_on_url', ('quack/',),
 
1136
            'error', ('NotStacked',))
 
1137
        client.add_expected_call(
 
1138
            'Branch.break_lock', ('quack/',),
 
1139
            'success', ('ok',))
 
1140
        transport.mkdir('quack')
 
1141
        transport = transport.clone('quack')
 
1142
        branch = self.make_remote_branch(transport, client)
 
1143
        branch.break_lock()
 
1144
        self.assertFinished(client)
 
1145
 
 
1146
 
 
1147
class TestBranchGetPhysicalLockStatus(RemoteBranchTestCase):
 
1148
 
 
1149
    def test_get_physical_lock_status_yes(self):
 
1150
        transport = MemoryTransport()
 
1151
        client = FakeClient(transport.base)
 
1152
        client.add_expected_call(
 
1153
            'Branch.get_stacked_on_url', ('quack/',),
 
1154
            'error', ('NotStacked',))
 
1155
        client.add_expected_call(
 
1156
            'Branch.get_physical_lock_status', ('quack/',),
 
1157
            'success', ('yes',))
 
1158
        transport.mkdir('quack')
 
1159
        transport = transport.clone('quack')
 
1160
        branch = self.make_remote_branch(transport, client)
 
1161
        result = branch.get_physical_lock_status()
 
1162
        self.assertFinished(client)
 
1163
        self.assertEqual(True, result)
 
1164
 
 
1165
    def test_get_physical_lock_status_no(self):
 
1166
        transport = MemoryTransport()
 
1167
        client = FakeClient(transport.base)
 
1168
        client.add_expected_call(
 
1169
            'Branch.get_stacked_on_url', ('quack/',),
 
1170
            'error', ('NotStacked',))
 
1171
        client.add_expected_call(
 
1172
            'Branch.get_physical_lock_status', ('quack/',),
 
1173
            'success', ('no',))
 
1174
        transport.mkdir('quack')
 
1175
        transport = transport.clone('quack')
 
1176
        branch = self.make_remote_branch(transport, client)
 
1177
        result = branch.get_physical_lock_status()
 
1178
        self.assertFinished(client)
 
1179
        self.assertEqual(False, result)
 
1180
 
 
1181
 
999
1182
class TestBranchGetParent(RemoteBranchTestCase):
1000
1183
 
1001
1184
    def test_no_parent(self):
1091
1274
        verb = 'Branch.set_parent_location'
1092
1275
        self.disable_verb(verb)
1093
1276
        branch.set_parent('http://foo/')
1094
 
        self.assertLength(12, self.hpss_calls)
 
1277
        self.assertLength(13, self.hpss_calls)
1095
1278
 
1096
1279
 
1097
1280
class TestBranchGetTagsBytes(RemoteBranchTestCase):
1183
1366
        client.add_expected_call(
1184
1367
            'Branch.last_revision_info', ('quack/',),
1185
1368
            'success', ('ok', '1', 'rev-tip'))
 
1369
        client.add_expected_call(
 
1370
            'Branch.get_config_file', ('quack/',),
 
1371
            'success', ('ok',), '')
 
1372
        transport.mkdir('quack')
 
1373
        transport = transport.clone('quack')
 
1374
        branch = self.make_remote_branch(transport, client)
 
1375
        result = branch.heads_to_fetch()
 
1376
        self.assertFinished(client)
 
1377
        self.assertEqual((set(['rev-tip']), set()), result)
 
1378
 
 
1379
    def test_uses_last_revision_info_and_tags_when_set(self):
 
1380
        transport = MemoryTransport()
 
1381
        client = FakeClient(transport.base)
 
1382
        client.add_expected_call(
 
1383
            'Branch.get_stacked_on_url', ('quack/',),
 
1384
            'error', ('NotStacked',))
 
1385
        client.add_expected_call(
 
1386
            'Branch.last_revision_info', ('quack/',),
 
1387
            'success', ('ok', '1', 'rev-tip'))
 
1388
        client.add_expected_call(
 
1389
            'Branch.get_config_file', ('quack/',),
 
1390
            'success', ('ok',), 'branch.fetch_tags = True')
1186
1391
        # XXX: this will break if the default format's serialization of tags
1187
1392
        # changes, or if the RPC for fetching tags changes from get_tags_bytes.
1188
1393
        client.add_expected_call(
1213
1418
        self.assertFinished(client)
1214
1419
        self.assertEqual((set(['tip']), set(['tagged-1', 'tagged-2'])), result)
1215
1420
 
1216
 
    def test_backwards_compatible(self):
 
1421
    def make_branch_with_tags(self):
1217
1422
        self.setup_smart_server_with_call_log()
1218
1423
        # Make a branch with a single revision.
1219
1424
        builder = self.make_branch_builder('foo')
1225
1430
        # Add two tags to that branch
1226
1431
        branch.tags.set_tag('tag-1', 'rev-1')
1227
1432
        branch.tags.set_tag('tag-2', 'rev-2')
 
1433
        return branch
 
1434
 
 
1435
    def test_backwards_compatible(self):
 
1436
        branch = self.make_branch_with_tags()
 
1437
        c = branch.get_config_stack()
 
1438
        c.set('branch.fetch_tags', True)
1228
1439
        self.addCleanup(branch.lock_read().unlock)
1229
1440
        # Disable the heads_to_fetch verb
1230
1441
        verb = 'Branch.heads_to_fetch'
1233
1444
        result = branch.heads_to_fetch()
1234
1445
        self.assertEqual((set(['tip']), set(['rev-1', 'rev-2'])), result)
1235
1446
        self.assertEqual(
1236
 
            ['Branch.last_revision_info', 'Branch.get_tags_bytes'],
 
1447
            ['Branch.last_revision_info', 'Branch.get_config_file',
 
1448
             'Branch.get_tags_bytes'],
 
1449
            [call.call.method for call in self.hpss_calls])
 
1450
 
 
1451
    def test_backwards_compatible_no_tags(self):
 
1452
        branch = self.make_branch_with_tags()
 
1453
        c = branch.get_config_stack()
 
1454
        c.set('branch.fetch_tags', False)
 
1455
        self.addCleanup(branch.lock_read().unlock)
 
1456
        # Disable the heads_to_fetch verb
 
1457
        verb = 'Branch.heads_to_fetch'
 
1458
        self.disable_verb(verb)
 
1459
        self.reset_smart_call_log()
 
1460
        result = branch.heads_to_fetch()
 
1461
        self.assertEqual((set(['tip']), set()), result)
 
1462
        self.assertEqual(
 
1463
            ['Branch.last_revision_info', 'Branch.get_config_file'],
1237
1464
            [call.call.method for call in self.hpss_calls])
1238
1465
 
1239
1466
 
1401
1628
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1402
1629
            'success', ('ok',))
1403
1630
        branch = self.make_remote_branch(transport, client)
1404
 
        # This is a hack to work around the problem that RemoteBranch currently
1405
 
        # unnecessarily invokes _ensure_real upon a call to lock_write.
1406
 
        branch._ensure_real = lambda: None
1407
1631
        branch.lock_write()
1408
1632
        result = branch._set_last_revision(NULL_REVISION)
1409
1633
        branch.unlock()
1438
1662
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1439
1663
            'success', ('ok',))
1440
1664
        branch = self.make_remote_branch(transport, client)
1441
 
        # This is a hack to work around the problem that RemoteBranch currently
1442
 
        # unnecessarily invokes _ensure_real upon a call to lock_write.
1443
 
        branch._ensure_real = lambda: None
1444
1665
        # Lock the branch, reset the record of remote calls.
1445
1666
        branch.lock_write()
1446
1667
        result = branch._set_last_revision('rev-id2')
1513
1734
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1514
1735
            'success', ('ok',))
1515
1736
        branch = self.make_remote_branch(transport, client)
1516
 
        branch._ensure_real = lambda: None
1517
1737
        branch.lock_write()
1518
1738
        # The 'TipChangeRejected' error response triggered by calling
1519
1739
        # set_last_revision_info causes a TipChangeRejected exception.
1782
2002
        self.addCleanup(branch.unlock)
1783
2003
        self.reset_smart_call_log()
1784
2004
        branch._get_config().set_option('value', 'name')
1785
 
        self.assertLength(10, self.hpss_calls)
 
2005
        self.assertLength(11, self.hpss_calls)
1786
2006
        self.assertEqual('value', branch._get_config().get_option('name'))
1787
2007
 
1788
2008
    def test_backwards_compat_set_option_with_dict(self):
1796
2016
        config = branch._get_config()
1797
2017
        value_dict = {'ascii': 'a', u'unicode \N{WATCH}': u'\N{INTERROBANG}'}
1798
2018
        config.set_option(value_dict, 'name')
1799
 
        self.assertLength(10, self.hpss_calls)
 
2019
        self.assertLength(11, self.hpss_calls)
1800
2020
        self.assertEqual(value_dict, branch._get_config().get_option('name'))
1801
2021
 
1802
2022
 
 
2023
class TestBranchGetPutConfigStore(RemoteBranchTestCase):
 
2024
 
 
2025
    def test_get_branch_conf(self):
 
2026
        # in an empty branch we decode the response properly
 
2027
        client = FakeClient()
 
2028
        client.add_expected_call(
 
2029
            'Branch.get_stacked_on_url', ('memory:///',),
 
2030
            'error', ('NotStacked',),)
 
2031
        client.add_success_response_with_body('# config file body', 'ok')
 
2032
        transport = MemoryTransport()
 
2033
        branch = self.make_remote_branch(transport, client)
 
2034
        config = branch.get_config_stack()
 
2035
        config.get("email")
 
2036
        config.get("log_format")
 
2037
        self.assertEqual(
 
2038
            [('call', 'Branch.get_stacked_on_url', ('memory:///',)),
 
2039
             ('call_expecting_body', 'Branch.get_config_file', ('memory:///',))],
 
2040
            client._calls)
 
2041
 
 
2042
    def test_set_branch_conf(self):
 
2043
        client = FakeClient()
 
2044
        client.add_expected_call(
 
2045
            'Branch.get_stacked_on_url', ('memory:///',),
 
2046
            'error', ('NotStacked',),)
 
2047
        client.add_expected_call(
 
2048
            'Branch.lock_write', ('memory:///', '', ''),
 
2049
            'success', ('ok', 'branch token', 'repo token'))
 
2050
        client.add_expected_call(
 
2051
            'Branch.get_config_file', ('memory:///', ),
 
2052
            'success', ('ok', ), "# line 1\n")
 
2053
        client.add_expected_call(
 
2054
            'Branch.put_config_file', ('memory:///', 'branch token',
 
2055
            'repo token'),
 
2056
            'success', ('ok',))
 
2057
        client.add_expected_call(
 
2058
            'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
 
2059
            'success', ('ok',))
 
2060
        transport = MemoryTransport()
 
2061
        branch = self.make_remote_branch(transport, client)
 
2062
        branch.lock_write()
 
2063
        config = branch.get_config_stack()
 
2064
        config.set('email', 'The Dude <lebowski@example.com>')
 
2065
        branch.unlock()
 
2066
        self.assertFinished(client)
 
2067
        self.assertEqual(
 
2068
            [('call', 'Branch.get_stacked_on_url', ('memory:///',)),
 
2069
             ('call', 'Branch.lock_write', ('memory:///', '', '')),
 
2070
             ('call_expecting_body', 'Branch.get_config_file', ('memory:///',)),
 
2071
             ('call_with_body_bytes_expecting_body', 'Branch.put_config_file',
 
2072
                 ('memory:///', 'branch token', 'repo token'),
 
2073
                 '# line 1\nemail = The Dude <lebowski@example.com>\n'),
 
2074
             ('call', 'Branch.unlock', ('memory:///', 'branch token', 'repo token'))],
 
2075
            client._calls)
 
2076
 
 
2077
 
1803
2078
class TestBranchLockWrite(RemoteBranchTestCase):
1804
2079
 
1805
2080
    def test_lock_write_unlockable(self):
1818
2093
        self.assertFinished(client)
1819
2094
 
1820
2095
 
 
2096
class TestBranchRevisionIdToRevno(RemoteBranchTestCase):
 
2097
 
 
2098
    def test_simple(self):
 
2099
        transport = MemoryTransport()
 
2100
        client = FakeClient(transport.base)
 
2101
        client.add_expected_call(
 
2102
            'Branch.get_stacked_on_url', ('quack/',),
 
2103
            'error', ('NotStacked',),)
 
2104
        client.add_expected_call(
 
2105
            'Branch.revision_id_to_revno', ('quack/', 'null:'),
 
2106
            'success', ('ok', '0',),)
 
2107
        client.add_expected_call(
 
2108
            'Branch.revision_id_to_revno', ('quack/', 'unknown'),
 
2109
            'error', ('NoSuchRevision', 'unknown',),)
 
2110
        transport.mkdir('quack')
 
2111
        transport = transport.clone('quack')
 
2112
        branch = self.make_remote_branch(transport, client)
 
2113
        self.assertEquals(0, branch.revision_id_to_revno('null:'))
 
2114
        self.assertRaises(errors.NoSuchRevision,
 
2115
            branch.revision_id_to_revno, 'unknown')
 
2116
        self.assertFinished(client)
 
2117
 
 
2118
    def test_dotted(self):
 
2119
        transport = MemoryTransport()
 
2120
        client = FakeClient(transport.base)
 
2121
        client.add_expected_call(
 
2122
            'Branch.get_stacked_on_url', ('quack/',),
 
2123
            'error', ('NotStacked',),)
 
2124
        client.add_expected_call(
 
2125
            'Branch.revision_id_to_revno', ('quack/', 'null:'),
 
2126
            'success', ('ok', '0',),)
 
2127
        client.add_expected_call(
 
2128
            'Branch.revision_id_to_revno', ('quack/', 'unknown'),
 
2129
            'error', ('NoSuchRevision', 'unknown',),)
 
2130
        transport.mkdir('quack')
 
2131
        transport = transport.clone('quack')
 
2132
        branch = self.make_remote_branch(transport, client)
 
2133
        self.assertEquals((0, ), branch.revision_id_to_dotted_revno('null:'))
 
2134
        self.assertRaises(errors.NoSuchRevision,
 
2135
            branch.revision_id_to_dotted_revno, 'unknown')
 
2136
        self.assertFinished(client)
 
2137
 
 
2138
    def test_dotted_no_smart_verb(self):
 
2139
        self.setup_smart_server_with_call_log()
 
2140
        branch = self.make_branch('.')
 
2141
        self.disable_verb('Branch.revision_id_to_revno')
 
2142
        self.reset_smart_call_log()
 
2143
        self.assertEquals((0, ),
 
2144
            branch.revision_id_to_dotted_revno('null:'))
 
2145
        self.assertLength(8, self.hpss_calls)
 
2146
 
 
2147
 
1821
2148
class TestBzrDirGetSetConfig(RemoteBzrDirTestCase):
1822
2149
 
1823
2150
    def test__get_config(self):
1837
2164
        self.reset_smart_call_log()
1838
2165
        config = bzrdir.get_config()
1839
2166
        config.set_default_stack_on('/')
1840
 
        self.assertLength(3, self.hpss_calls)
 
2167
        self.assertLength(4, self.hpss_calls)
1841
2168
 
1842
2169
    def test_backwards_compat_get_option(self):
1843
2170
        self.setup_smart_server_with_call_log()
1847
2174
        self.reset_smart_call_log()
1848
2175
        self.assertEqual(None,
1849
2176
            bzrdir._get_config().get_option('default_stack_on'))
1850
 
        self.assertLength(3, self.hpss_calls)
 
2177
        self.assertLength(4, self.hpss_calls)
1851
2178
 
1852
2179
 
1853
2180
class TestTransportIsReadonly(tests.TestCase):
1980
2307
            remote_repo_format.get_format_description())
1981
2308
 
1982
2309
 
 
2310
class TestRepositoryAllRevisionIds(TestRemoteRepository):
 
2311
 
 
2312
    def test_empty(self):
 
2313
        transport_path = 'quack'
 
2314
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2315
        client.add_success_response_with_body('', 'ok')
 
2316
        self.assertEquals([], repo.all_revision_ids())
 
2317
        self.assertEqual(
 
2318
            [('call_expecting_body', 'Repository.all_revision_ids',
 
2319
             ('quack/',))],
 
2320
            client._calls)
 
2321
 
 
2322
    def test_with_some_content(self):
 
2323
        transport_path = 'quack'
 
2324
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2325
        client.add_success_response_with_body(
 
2326
            'rev1\nrev2\nanotherrev\n', 'ok')
 
2327
        self.assertEquals(["rev1", "rev2", "anotherrev"],
 
2328
            repo.all_revision_ids())
 
2329
        self.assertEqual(
 
2330
            [('call_expecting_body', 'Repository.all_revision_ids',
 
2331
             ('quack/',))],
 
2332
            client._calls)
 
2333
 
 
2334
 
1983
2335
class TestRepositoryGatherStats(TestRemoteRepository):
1984
2336
 
1985
2337
    def test_revid_none(self):
2038
2390
                         result)
2039
2391
 
2040
2392
 
 
2393
class TestRepositoryBreakLock(TestRemoteRepository):
 
2394
 
 
2395
    def test_break_lock(self):
 
2396
        transport_path = 'quack'
 
2397
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2398
        client.add_success_response('ok')
 
2399
        repo.break_lock()
 
2400
        self.assertEqual(
 
2401
            [('call', 'Repository.break_lock', ('quack/',))],
 
2402
            client._calls)
 
2403
 
 
2404
 
 
2405
class TestRepositoryGetSerializerFormat(TestRemoteRepository):
 
2406
 
 
2407
    def test_get_serializer_format(self):
 
2408
        transport_path = 'hill'
 
2409
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2410
        client.add_success_response('ok', '7')
 
2411
        self.assertEquals('7', repo.get_serializer_format())
 
2412
        self.assertEqual(
 
2413
            [('call', 'VersionedFileRepository.get_serializer_format',
 
2414
              ('hill/', ))],
 
2415
            client._calls)
 
2416
 
 
2417
 
 
2418
class TestRepositoryReconcile(TestRemoteRepository):
 
2419
 
 
2420
    def test_reconcile(self):
 
2421
        transport_path = 'hill'
 
2422
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2423
        body = ("garbage_inventories: 2\n"
 
2424
                "inconsistent_parents: 3\n")
 
2425
        client.add_expected_call(
 
2426
            'Repository.lock_write', ('hill/', ''),
 
2427
            'success', ('ok', 'a token'))
 
2428
        client.add_success_response_with_body(body, 'ok')
 
2429
        reconciler = repo.reconcile()
 
2430
        self.assertEqual(
 
2431
            [('call', 'Repository.lock_write', ('hill/', '')),
 
2432
             ('call_expecting_body', 'Repository.reconcile',
 
2433
                ('hill/', 'a token'))],
 
2434
            client._calls)
 
2435
        self.assertEquals(2, reconciler.garbage_inventories)
 
2436
        self.assertEquals(3, reconciler.inconsistent_parents)
 
2437
 
 
2438
 
 
2439
class TestRepositoryGetRevisionSignatureText(TestRemoteRepository):
 
2440
 
 
2441
    def test_text(self):
 
2442
        # ('ok',), body with signature text
 
2443
        transport_path = 'quack'
 
2444
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2445
        client.add_success_response_with_body(
 
2446
            'THETEXT', 'ok')
 
2447
        self.assertEquals("THETEXT", repo.get_signature_text("revid"))
 
2448
        self.assertEqual(
 
2449
            [('call_expecting_body', 'Repository.get_revision_signature_text',
 
2450
             ('quack/', 'revid'))],
 
2451
            client._calls)
 
2452
 
 
2453
    def test_no_signature(self):
 
2454
        transport_path = 'quick'
 
2455
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2456
        client.add_error_response('nosuchrevision', 'unknown')
 
2457
        self.assertRaises(errors.NoSuchRevision, repo.get_signature_text,
 
2458
                "unknown")
 
2459
        self.assertEqual(
 
2460
            [('call_expecting_body', 'Repository.get_revision_signature_text',
 
2461
              ('quick/', 'unknown'))],
 
2462
            client._calls)
 
2463
 
 
2464
 
2041
2465
class TestRepositoryGetGraph(TestRemoteRepository):
2042
2466
 
2043
2467
    def test_get_graph(self):
2048
2472
        self.assertNotEqual(graph._parents_provider, repo)
2049
2473
 
2050
2474
 
 
2475
class TestRepositoryAddSignatureText(TestRemoteRepository):
 
2476
 
 
2477
    def test_add_signature_text(self):
 
2478
        transport_path = 'quack'
 
2479
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2480
        client.add_expected_call(
 
2481
            'Repository.lock_write', ('quack/', ''),
 
2482
            'success', ('ok', 'a token'))
 
2483
        client.add_expected_call(
 
2484
            'Repository.start_write_group', ('quack/', 'a token'),
 
2485
            'success', ('ok', ('token1', )))
 
2486
        client.add_expected_call(
 
2487
            'Repository.add_signature_text', ('quack/', 'a token', 'rev1',
 
2488
                'token1'),
 
2489
            'success', ('ok', ), None)
 
2490
        repo.lock_write()
 
2491
        repo.start_write_group()
 
2492
        self.assertIs(None,
 
2493
            repo.add_signature_text("rev1", "every bloody emperor"))
 
2494
        self.assertEqual(
 
2495
            ('call_with_body_bytes_expecting_body',
 
2496
              'Repository.add_signature_text',
 
2497
                ('quack/', 'a token', 'rev1', 'token1'),
 
2498
              'every bloody emperor'),
 
2499
            client._calls[-1])
 
2500
 
 
2501
 
2051
2502
class TestRepositoryGetParentMap(TestRemoteRepository):
2052
2503
 
2053
2504
    def test_get_parent_map_caching(self):
2103
2554
        parents = repo.get_parent_map([rev_id])
2104
2555
        self.assertEqual(
2105
2556
            [('call_with_body_bytes_expecting_body',
2106
 
              'Repository.get_parent_map', ('quack/', 'include-missing:',
2107
 
              rev_id), '\n\n0'),
 
2557
              'Repository.get_parent_map',
 
2558
              ('quack/', 'include-missing:', rev_id), '\n\n0'),
2108
2559
             ('disconnect medium',),
2109
2560
             ('call_expecting_body', 'Repository.get_revision_graph',
2110
2561
              ('quack/', ''))],
2230
2681
        self.assertEqual({}, repo.get_parent_map(['non-existant']))
2231
2682
        self.assertLength(0, self.hpss_calls)
2232
2683
 
 
2684
    def test_exposes_get_cached_parent_map(self):
 
2685
        """RemoteRepository exposes get_cached_parent_map from
 
2686
        _unstacked_provider
 
2687
        """
 
2688
        r1 = u'\u0e33'.encode('utf8')
 
2689
        r2 = u'\u0dab'.encode('utf8')
 
2690
        lines = [' '.join([r2, r1]), r1]
 
2691
        encoded_body = bz2.compress('\n'.join(lines))
 
2692
 
 
2693
        transport_path = 'quack'
 
2694
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2695
        client.add_success_response_with_body(encoded_body, 'ok')
 
2696
        repo.lock_read()
 
2697
        # get_cached_parent_map should *not* trigger an RPC
 
2698
        self.assertEqual({}, repo.get_cached_parent_map([r1]))
 
2699
        self.assertEqual([], client._calls)
 
2700
        self.assertEqual({r2: (r1,)}, repo.get_parent_map([r2]))
 
2701
        self.assertEqual({r1: (NULL_REVISION,)},
 
2702
            repo.get_cached_parent_map([r1]))
 
2703
        self.assertEqual(
 
2704
            [('call_with_body_bytes_expecting_body',
 
2705
              'Repository.get_parent_map', ('quack/', 'include-missing:', r2),
 
2706
              '\n\n0')],
 
2707
            client._calls)
 
2708
        repo.unlock()
 
2709
 
2233
2710
 
2234
2711
class TestGetParentMapAllowsNew(tests.TestCaseWithTransport):
2235
2712
 
2250
2727
        self.assertEqual({'rev1': ('null:',)}, graph.get_parent_map(['rev1']))
2251
2728
 
2252
2729
 
 
2730
class TestRepositoryGetRevisions(TestRemoteRepository):
 
2731
 
 
2732
    def test_hpss_missing_revision(self):
 
2733
        transport_path = 'quack'
 
2734
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2735
        client.add_success_response_with_body(
 
2736
            '', 'ok', '10')
 
2737
        self.assertRaises(errors.NoSuchRevision, repo.get_revisions,
 
2738
            ['somerev1', 'anotherrev2'])
 
2739
        self.assertEqual(
 
2740
            [('call_with_body_bytes_expecting_body', 'Repository.iter_revisions',
 
2741
             ('quack/', ), "somerev1\nanotherrev2")],
 
2742
            client._calls)
 
2743
 
 
2744
    def test_hpss_get_single_revision(self):
 
2745
        transport_path = 'quack'
 
2746
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2747
        somerev1 = Revision("somerev1")
 
2748
        somerev1.committer = "Joe Committer <joe@example.com>"
 
2749
        somerev1.timestamp = 1321828927
 
2750
        somerev1.timezone = -60
 
2751
        somerev1.inventory_sha1 = "691b39be74c67b1212a75fcb19c433aaed903c2b"
 
2752
        somerev1.message = "Message"
 
2753
        body = zlib.compress(chk_bencode_serializer.write_revision_to_string(
 
2754
            somerev1))
 
2755
        # Split up body into two bits to make sure the zlib compression object
 
2756
        # gets data fed twice.
 
2757
        client.add_success_response_with_body(
 
2758
                [body[:10], body[10:]], 'ok', '10')
 
2759
        revs = repo.get_revisions(['somerev1'])
 
2760
        self.assertEquals(revs, [somerev1])
 
2761
        self.assertEqual(
 
2762
            [('call_with_body_bytes_expecting_body', 'Repository.iter_revisions',
 
2763
             ('quack/', ), "somerev1")],
 
2764
            client._calls)
 
2765
 
 
2766
 
2253
2767
class TestRepositoryGetRevisionGraph(TestRemoteRepository):
2254
2768
 
2255
2769
    def test_null_revision(self):
2406
2920
                              call.call.method == verb])
2407
2921
 
2408
2922
 
 
2923
class TestRepositoryHasSignatureForRevisionId(TestRemoteRepository):
 
2924
 
 
2925
    def test_has_signature_for_revision_id(self):
 
2926
        # ('yes', ) for Repository.has_signature_for_revision_id -> 'True'.
 
2927
        transport_path = 'quack'
 
2928
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2929
        client.add_success_response('yes')
 
2930
        result = repo.has_signature_for_revision_id('A')
 
2931
        self.assertEqual(
 
2932
            [('call', 'Repository.has_signature_for_revision_id',
 
2933
              ('quack/', 'A'))],
 
2934
            client._calls)
 
2935
        self.assertEqual(True, result)
 
2936
 
 
2937
    def test_is_not_shared(self):
 
2938
        # ('no', ) for Repository.has_signature_for_revision_id -> 'False'.
 
2939
        transport_path = 'qwack'
 
2940
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2941
        client.add_success_response('no')
 
2942
        result = repo.has_signature_for_revision_id('A')
 
2943
        self.assertEqual(
 
2944
            [('call', 'Repository.has_signature_for_revision_id',
 
2945
              ('qwack/', 'A'))],
 
2946
            client._calls)
 
2947
        self.assertEqual(False, result)
 
2948
 
 
2949
 
 
2950
class TestRepositoryPhysicalLockStatus(TestRemoteRepository):
 
2951
 
 
2952
    def test_get_physical_lock_status_yes(self):
 
2953
        transport_path = 'qwack'
 
2954
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2955
        client.add_success_response('yes')
 
2956
        result = repo.get_physical_lock_status()
 
2957
        self.assertEqual(
 
2958
            [('call', 'Repository.get_physical_lock_status',
 
2959
              ('qwack/', ))],
 
2960
            client._calls)
 
2961
        self.assertEqual(True, result)
 
2962
 
 
2963
    def test_get_physical_lock_status_no(self):
 
2964
        transport_path = 'qwack'
 
2965
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2966
        client.add_success_response('no')
 
2967
        result = repo.get_physical_lock_status()
 
2968
        self.assertEqual(
 
2969
            [('call', 'Repository.get_physical_lock_status',
 
2970
              ('qwack/', ))],
 
2971
            client._calls)
 
2972
        self.assertEqual(False, result)
 
2973
 
 
2974
 
2409
2975
class TestRepositoryIsShared(TestRemoteRepository):
2410
2976
 
2411
2977
    def test_is_shared(self):
2431
2997
        self.assertEqual(False, result)
2432
2998
 
2433
2999
 
 
3000
class TestRepositoryMakeWorkingTrees(TestRemoteRepository):
 
3001
 
 
3002
    def test_make_working_trees(self):
 
3003
        # ('yes', ) for Repository.make_working_trees -> 'True'.
 
3004
        transport_path = 'quack'
 
3005
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3006
        client.add_success_response('yes')
 
3007
        result = repo.make_working_trees()
 
3008
        self.assertEqual(
 
3009
            [('call', 'Repository.make_working_trees', ('quack/',))],
 
3010
            client._calls)
 
3011
        self.assertEqual(True, result)
 
3012
 
 
3013
    def test_no_working_trees(self):
 
3014
        # ('no', ) for Repository.make_working_trees -> 'False'.
 
3015
        transport_path = 'qwack'
 
3016
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3017
        client.add_success_response('no')
 
3018
        result = repo.make_working_trees()
 
3019
        self.assertEqual(
 
3020
            [('call', 'Repository.make_working_trees', ('qwack/',))],
 
3021
            client._calls)
 
3022
        self.assertEqual(False, result)
 
3023
 
 
3024
 
2434
3025
class TestRepositoryLockWrite(TestRemoteRepository):
2435
3026
 
2436
3027
    def test_lock_write(self):
2462
3053
            client._calls)
2463
3054
 
2464
3055
 
 
3056
class TestRepositoryWriteGroups(TestRemoteRepository):
 
3057
 
 
3058
    def test_start_write_group(self):
 
3059
        transport_path = 'quack'
 
3060
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3061
        client.add_expected_call(
 
3062
            'Repository.lock_write', ('quack/', ''),
 
3063
            'success', ('ok', 'a token'))
 
3064
        client.add_expected_call(
 
3065
            'Repository.start_write_group', ('quack/', 'a token'),
 
3066
            'success', ('ok', ('token1', )))
 
3067
        repo.lock_write()
 
3068
        repo.start_write_group()
 
3069
 
 
3070
    def test_start_write_group_unsuspendable(self):
 
3071
        # Some repositories do not support suspending write
 
3072
        # groups. For those, fall back to the "real" repository.
 
3073
        transport_path = 'quack'
 
3074
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3075
        def stub_ensure_real():
 
3076
            client._calls.append(('_ensure_real',))
 
3077
            repo._real_repository = _StubRealPackRepository(client._calls)
 
3078
        repo._ensure_real = stub_ensure_real
 
3079
        client.add_expected_call(
 
3080
            'Repository.lock_write', ('quack/', ''),
 
3081
            'success', ('ok', 'a token'))
 
3082
        client.add_expected_call(
 
3083
            'Repository.start_write_group', ('quack/', 'a token'),
 
3084
            'error', ('UnsuspendableWriteGroup',))
 
3085
        repo.lock_write()
 
3086
        repo.start_write_group()
 
3087
        self.assertEquals(client._calls[-2:], [ 
 
3088
            ('_ensure_real',),
 
3089
            ('start_write_group',)])
 
3090
 
 
3091
    def test_commit_write_group(self):
 
3092
        transport_path = 'quack'
 
3093
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3094
        client.add_expected_call(
 
3095
            'Repository.lock_write', ('quack/', ''),
 
3096
            'success', ('ok', 'a token'))
 
3097
        client.add_expected_call(
 
3098
            'Repository.start_write_group', ('quack/', 'a token'),
 
3099
            'success', ('ok', ['token1']))
 
3100
        client.add_expected_call(
 
3101
            'Repository.commit_write_group', ('quack/', 'a token', ['token1']),
 
3102
            'success', ('ok',))
 
3103
        repo.lock_write()
 
3104
        repo.start_write_group()
 
3105
        repo.commit_write_group()
 
3106
 
 
3107
    def test_abort_write_group(self):
 
3108
        transport_path = 'quack'
 
3109
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3110
        client.add_expected_call(
 
3111
            'Repository.lock_write', ('quack/', ''),
 
3112
            'success', ('ok', 'a token'))
 
3113
        client.add_expected_call(
 
3114
            'Repository.start_write_group', ('quack/', 'a token'),
 
3115
            'success', ('ok', ['token1']))
 
3116
        client.add_expected_call(
 
3117
            'Repository.abort_write_group', ('quack/', 'a token', ['token1']),
 
3118
            'success', ('ok',))
 
3119
        repo.lock_write()
 
3120
        repo.start_write_group()
 
3121
        repo.abort_write_group(False)
 
3122
 
 
3123
    def test_suspend_write_group(self):
 
3124
        transport_path = 'quack'
 
3125
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3126
        self.assertEquals([], repo.suspend_write_group())
 
3127
 
 
3128
    def test_resume_write_group(self):
 
3129
        transport_path = 'quack'
 
3130
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3131
        client.add_expected_call(
 
3132
            'Repository.lock_write', ('quack/', ''),
 
3133
            'success', ('ok', 'a token'))
 
3134
        client.add_expected_call(
 
3135
            'Repository.check_write_group', ('quack/', 'a token', ['token1']),
 
3136
            'success', ('ok',))
 
3137
        repo.lock_write()
 
3138
        repo.resume_write_group(['token1'])
 
3139
 
 
3140
 
2465
3141
class TestRepositorySetMakeWorkingTrees(TestRemoteRepository):
2466
3142
 
2467
3143
    def test_backwards_compat(self):
2526
3202
        self.assertEqual([], client._calls)
2527
3203
 
2528
3204
 
 
3205
class TestRepositoryIterFilesBytes(TestRemoteRepository):
 
3206
    """Test Repository.iter_file_bytes."""
 
3207
 
 
3208
    def test_single(self):
 
3209
        transport_path = 'quack'
 
3210
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3211
        client.add_expected_call(
 
3212
            'Repository.iter_files_bytes', ('quack/', ),
 
3213
            'success', ('ok',), iter(["ok\x000", "\n", zlib.compress("mydata" * 10)]))
 
3214
        for (identifier, byte_stream) in repo.iter_files_bytes([("somefile",
 
3215
                "somerev", "myid")]):
 
3216
            self.assertEquals("myid", identifier)
 
3217
            self.assertEquals("".join(byte_stream), "mydata" * 10)
 
3218
 
 
3219
    def test_missing(self):
 
3220
        transport_path = 'quack'
 
3221
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3222
        client.add_expected_call(
 
3223
            'Repository.iter_files_bytes',
 
3224
                ('quack/', ),
 
3225
            'error', ('RevisionNotPresent', 'somefile', 'somerev'),
 
3226
            iter(["absent\0somefile\0somerev\n"]))
 
3227
        self.assertRaises(errors.RevisionNotPresent, list,
 
3228
                repo.iter_files_bytes(
 
3229
                [("somefile", "somerev", "myid")]))
 
3230
 
 
3231
 
2529
3232
class TestRepositoryInsertStreamBase(TestRemoteRepository):
2530
3233
    """Base class for Repository.insert_stream and .insert_stream_1.19
2531
3234
    tests.
2806
3509
        self.calls = calls
2807
3510
        self._pack_collection = _StubPackCollection(calls)
2808
3511
 
 
3512
    def start_write_group(self):
 
3513
        self.calls.append(('start_write_group',))
 
3514
 
2809
3515
    def is_in_write_group(self):
2810
3516
        return False
2811
3517
 
3244
3950
        _, stacked = branch_factory()
3245
3951
        source = stacked.repository._get_source(target_repository_format)
3246
3952
        tip = stacked.last_revision()
3247
 
        revs = stacked.repository.get_ancestry(tip)
3248
 
        search = graph.PendingAncestryResult([tip], stacked.repository)
 
3953
        stacked.repository._ensure_real()
 
3954
        graph = stacked.repository.get_graph()
 
3955
        revs = [r for (r,ps) in graph.iter_ancestry([tip])
 
3956
                if r != NULL_REVISION]
 
3957
        revs.reverse()
 
3958
        search = vf_search.PendingAncestryResult([tip], stacked.repository)
3249
3959
        self.reset_smart_call_log()
3250
3960
        stream = source.get_stream(search)
3251
 
        if None in revs:
3252
 
            revs.remove(None)
3253
3961
        # We trust that if a revision is in the stream the rest of the new
3254
3962
        # content for it is too, as per our main fetch tests; here we are
3255
3963
        # checking that the revisions are actually included at all, and their
3294
4002
        self.assertEqual(expected_revs, rev_ord)
3295
4003
        # Getting topological sort requires VFS calls still - one of which is
3296
4004
        # pushing up from the bound branch.
3297
 
        self.assertLength(13, self.hpss_calls)
 
4005
        self.assertLength(14, self.hpss_calls)
3298
4006
 
3299
4007
    def test_stacked_get_stream_groupcompress(self):
3300
4008
        # Repository._get_source.get_stream() from a stacked repository with
3357
4065
        remote_branch_url = self.smart_server.get_url() + 'remote'
3358
4066
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
3359
4067
        self.hpss_calls = []
3360
 
        local.repository.fetch(remote_branch.repository,
3361
 
                fetch_spec=graph.EverythingResult(remote_branch.repository))
 
4068
        local.repository.fetch(
 
4069
            remote_branch.repository,
 
4070
            fetch_spec=vf_search.EverythingResult(remote_branch.repository))
3362
4071
        self.assertEqual(['Repository.get_stream_1.19'], self.hpss_calls)
3363
4072
 
3364
4073
    def override_verb(self, verb_name, verb):
3365
4074
        request_handlers = request.request_handlers
3366
4075
        orig_verb = request_handlers.get(verb_name)
 
4076
        orig_info = request_handlers.get_info(verb_name)
3367
4077
        request_handlers.register(verb_name, verb, override_existing=True)
3368
4078
        self.addCleanup(request_handlers.register, verb_name, orig_verb,
3369
 
                override_existing=True)
 
4079
                override_existing=True, info=orig_info)
3370
4080
 
3371
4081
    def test_fetch_everything_backwards_compat(self):
3372
4082
        """Can fetch with EverythingResult even with pre 2.4 servers.
3379
4089
            """A version of the Repository.get_stream_1.19 verb patched to
3380
4090
            reject 'everything' searches the way 2.3 and earlier do.
3381
4091
            """
3382
 
            def recreate_search(self, repository, search_bytes, discard_excess=False):
 
4092
            def recreate_search(self, repository, search_bytes,
 
4093
                                discard_excess=False):
3383
4094
                verb_log.append(search_bytes.split('\n', 1)[0])
3384
4095
                if search_bytes == 'everything':
3385
 
                    return (None, request.FailedSmartServerResponse(('BadSearch',)))
 
4096
                    return (None,
 
4097
                            request.FailedSmartServerResponse(('BadSearch',)))
3386
4098
                return super(OldGetStreamVerb,
3387
4099
                        self).recreate_search(repository, search_bytes,
3388
4100
                            discard_excess=discard_excess)
3393
4105
        remote_branch_url = self.smart_server.get_url() + 'remote'
3394
4106
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
3395
4107
        self.hpss_calls = []
3396
 
        local.repository.fetch(remote_branch.repository,
3397
 
                fetch_spec=graph.EverythingResult(remote_branch.repository))
 
4108
        local.repository.fetch(
 
4109
            remote_branch.repository,
 
4110
            fetch_spec=vf_search.EverythingResult(remote_branch.repository))
3398
4111
        # make sure the overridden verb was used
3399
4112
        self.assertLength(1, verb_log)
3400
4113
        # more than one HPSS call is needed, but because it's a VFS callback
3401
4114
        # its hard to predict exactly how many.
3402
4115
        self.assertTrue(len(self.hpss_calls) > 1)
3403
4116
 
 
4117
 
 
4118
class TestUpdateBoundBranchWithModifiedBoundLocation(
 
4119
    tests.TestCaseWithTransport):
 
4120
    """Ensure correct handling of bound_location modifications.
 
4121
 
 
4122
    This is tested against a smart server as http://pad.lv/786980 was about a
 
4123
    ReadOnlyError (write attempt during a read-only transaction) which can only
 
4124
    happen in this context.
 
4125
    """
 
4126
 
 
4127
    def setUp(self):
 
4128
        super(TestUpdateBoundBranchWithModifiedBoundLocation, self).setUp()
 
4129
        self.transport_server = test_server.SmartTCPServer_for_testing
 
4130
 
 
4131
    def make_master_and_checkout(self, master_name, checkout_name):
 
4132
        # Create the master branch and its associated checkout
 
4133
        self.master = self.make_branch_and_tree(master_name)
 
4134
        self.checkout = self.master.branch.create_checkout(checkout_name)
 
4135
        # Modify the master branch so there is something to update
 
4136
        self.master.commit('add stuff')
 
4137
        self.last_revid = self.master.commit('even more stuff')
 
4138
        self.bound_location = self.checkout.branch.get_bound_location()
 
4139
 
 
4140
    def assertUpdateSucceeds(self, new_location):
 
4141
        self.checkout.branch.set_bound_location(new_location)
 
4142
        self.checkout.update()
 
4143
        self.assertEquals(self.last_revid, self.checkout.last_revision())
 
4144
 
 
4145
    def test_without_final_slash(self):
 
4146
        self.make_master_and_checkout('master', 'checkout')
 
4147
        # For unclear reasons some users have a bound_location without a final
 
4148
        # '/', simulate that by forcing such a value
 
4149
        self.assertEndsWith(self.bound_location, '/')
 
4150
        self.assertUpdateSucceeds(self.bound_location.rstrip('/'))
 
4151
 
 
4152
    def test_plus_sign(self):
 
4153
        self.make_master_and_checkout('+master', 'checkout')
 
4154
        self.assertUpdateSucceeds(self.bound_location.replace('%2B', '+', 1))
 
4155
 
 
4156
    def test_tilda(self):
 
4157
        # Embed ~ in the middle of the path just to avoid any $HOME
 
4158
        # interpretation
 
4159
        self.make_master_and_checkout('mas~ter', 'checkout')
 
4160
        self.assertUpdateSucceeds(self.bound_location.replace('%2E', '~', 1))
 
4161
 
 
4162
 
 
4163
class TestWithCustomErrorHandler(RemoteBranchTestCase):
 
4164
 
 
4165
    def test_no_context(self):
 
4166
        class OutOfCoffee(errors.BzrError):
 
4167
            """A dummy exception for testing."""
 
4168
 
 
4169
            def __init__(self, urgency):
 
4170
                self.urgency = urgency
 
4171
        remote.no_context_error_translators.register("OutOfCoffee",
 
4172
            lambda err: OutOfCoffee(err.error_args[0]))
 
4173
        transport = MemoryTransport()
 
4174
        client = FakeClient(transport.base)
 
4175
        client.add_expected_call(
 
4176
            'Branch.get_stacked_on_url', ('quack/',),
 
4177
            'error', ('NotStacked',))
 
4178
        client.add_expected_call(
 
4179
            'Branch.last_revision_info',
 
4180
            ('quack/',),
 
4181
            'error', ('OutOfCoffee', 'low'))
 
4182
        transport.mkdir('quack')
 
4183
        transport = transport.clone('quack')
 
4184
        branch = self.make_remote_branch(transport, client)
 
4185
        self.assertRaises(OutOfCoffee, branch.last_revision_info)
 
4186
        self.assertFinished(client)
 
4187
 
 
4188
    def test_with_context(self):
 
4189
        class OutOfTea(errors.BzrError):
 
4190
            def __init__(self, branch, urgency):
 
4191
                self.branch = branch
 
4192
                self.urgency = urgency
 
4193
        remote.error_translators.register("OutOfTea",
 
4194
            lambda err, find, path: OutOfTea(err.error_args[0],
 
4195
                find("branch")))
 
4196
        transport = MemoryTransport()
 
4197
        client = FakeClient(transport.base)
 
4198
        client.add_expected_call(
 
4199
            'Branch.get_stacked_on_url', ('quack/',),
 
4200
            'error', ('NotStacked',))
 
4201
        client.add_expected_call(
 
4202
            'Branch.last_revision_info',
 
4203
            ('quack/',),
 
4204
            'error', ('OutOfTea', 'low'))
 
4205
        transport.mkdir('quack')
 
4206
        transport = transport.clone('quack')
 
4207
        branch = self.make_remote_branch(transport, client)
 
4208
        self.assertRaises(OutOfTea, branch.last_revision_info)
 
4209
        self.assertFinished(client)
 
4210
 
 
4211
 
 
4212
class TestRepositoryPack(TestRemoteRepository):
 
4213
 
 
4214
    def test_pack(self):
 
4215
        transport_path = 'quack'
 
4216
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4217
        client.add_expected_call(
 
4218
            'Repository.lock_write', ('quack/', ''),
 
4219
            'success', ('ok', 'token'))
 
4220
        client.add_expected_call(
 
4221
            'Repository.pack', ('quack/', 'token', 'False'),
 
4222
            'success', ('ok',), )
 
4223
        client.add_expected_call(
 
4224
            'Repository.unlock', ('quack/', 'token'),
 
4225
            'success', ('ok', ))
 
4226
        repo.pack()
 
4227
 
 
4228
    def test_pack_with_hint(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', 'False'),
 
4239
            'success', ('ok', ))
 
4240
        repo.pack(['hinta', 'hintb'])
 
4241
 
 
4242
 
 
4243
class TestRepositoryIterInventories(TestRemoteRepository):
 
4244
    """Test Repository.iter_inventories."""
 
4245
 
 
4246
    def _serialize_inv_delta(self, old_name, new_name, delta):
 
4247
        serializer = inventory_delta.InventoryDeltaSerializer(True, False)
 
4248
        return "".join(serializer.delta_to_lines(old_name, new_name, delta))
 
4249
 
 
4250
    def test_single_empty(self):
 
4251
        transport_path = 'quack'
 
4252
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4253
        fmt = bzrdir.format_registry.get('2a')().repository_format
 
4254
        repo._format = fmt
 
4255
        stream = [('inventory-deltas', [
 
4256
            versionedfile.FulltextContentFactory('somerevid', None, None,
 
4257
                self._serialize_inv_delta('null:', 'somerevid', []))])]
 
4258
        client.add_expected_call(
 
4259
            'VersionedFileRepository.get_inventories', ('quack/', 'unordered'),
 
4260
            'success', ('ok', ),
 
4261
            _stream_to_byte_stream(stream, fmt))
 
4262
        ret = list(repo.iter_inventories(["somerevid"]))
 
4263
        self.assertLength(1, ret)
 
4264
        inv = ret[0]
 
4265
        self.assertEquals("somerevid", inv.revision_id)
 
4266
 
 
4267
    def test_empty(self):
 
4268
        transport_path = 'quack'
 
4269
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4270
        ret = list(repo.iter_inventories([]))
 
4271
        self.assertEquals(ret, [])
 
4272
 
 
4273
    def test_missing(self):
 
4274
        transport_path = 'quack'
 
4275
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4276
        client.add_expected_call(
 
4277
            'VersionedFileRepository.get_inventories', ('quack/', 'unordered'),
 
4278
            'success', ('ok', ), iter([]))
 
4279
        self.assertRaises(errors.NoSuchRevision, list, repo.iter_inventories(
 
4280
            ["somerevid"]))