~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_remote.py

(gz) Fix deprecations of win32utils path function unicode wrappers (Martin
 Packman)

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,
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()
996
1121
        return RemoteBranch(bzrdir, repo, _client=client, format=format)
997
1122
 
998
1123
 
 
1124
class TestBranchBreakLock(RemoteBranchTestCase):
 
1125
 
 
1126
    def test_break_lock(self):
 
1127
        transport_path = 'quack'
 
1128
        transport = MemoryTransport()
 
1129
        client = FakeClient(transport.base)
 
1130
        client.add_expected_call(
 
1131
            'Branch.get_stacked_on_url', ('quack/',),
 
1132
            'error', ('NotStacked',))
 
1133
        client.add_expected_call(
 
1134
            'Branch.break_lock', ('quack/',),
 
1135
            'success', ('ok',))
 
1136
        transport.mkdir('quack')
 
1137
        transport = transport.clone('quack')
 
1138
        branch = self.make_remote_branch(transport, client)
 
1139
        branch.break_lock()
 
1140
        self.assertFinished(client)
 
1141
 
 
1142
 
 
1143
class TestBranchGetPhysicalLockStatus(RemoteBranchTestCase):
 
1144
 
 
1145
    def test_get_physical_lock_status_yes(self):
 
1146
        transport = MemoryTransport()
 
1147
        client = FakeClient(transport.base)
 
1148
        client.add_expected_call(
 
1149
            'Branch.get_stacked_on_url', ('quack/',),
 
1150
            'error', ('NotStacked',))
 
1151
        client.add_expected_call(
 
1152
            'Branch.get_physical_lock_status', ('quack/',),
 
1153
            'success', ('yes',))
 
1154
        transport.mkdir('quack')
 
1155
        transport = transport.clone('quack')
 
1156
        branch = self.make_remote_branch(transport, client)
 
1157
        result = branch.get_physical_lock_status()
 
1158
        self.assertFinished(client)
 
1159
        self.assertEqual(True, result)
 
1160
 
 
1161
    def test_get_physical_lock_status_no(self):
 
1162
        transport = MemoryTransport()
 
1163
        client = FakeClient(transport.base)
 
1164
        client.add_expected_call(
 
1165
            'Branch.get_stacked_on_url', ('quack/',),
 
1166
            'error', ('NotStacked',))
 
1167
        client.add_expected_call(
 
1168
            'Branch.get_physical_lock_status', ('quack/',),
 
1169
            'success', ('no',))
 
1170
        transport.mkdir('quack')
 
1171
        transport = transport.clone('quack')
 
1172
        branch = self.make_remote_branch(transport, client)
 
1173
        result = branch.get_physical_lock_status()
 
1174
        self.assertFinished(client)
 
1175
        self.assertEqual(False, result)
 
1176
 
 
1177
 
999
1178
class TestBranchGetParent(RemoteBranchTestCase):
1000
1179
 
1001
1180
    def test_no_parent(self):
1183
1362
        client.add_expected_call(
1184
1363
            'Branch.last_revision_info', ('quack/',),
1185
1364
            'success', ('ok', '1', 'rev-tip'))
 
1365
        client.add_expected_call(
 
1366
            'Branch.get_config_file', ('quack/',),
 
1367
            'success', ('ok',), '')
 
1368
        transport.mkdir('quack')
 
1369
        transport = transport.clone('quack')
 
1370
        branch = self.make_remote_branch(transport, client)
 
1371
        result = branch.heads_to_fetch()
 
1372
        self.assertFinished(client)
 
1373
        self.assertEqual((set(['rev-tip']), set()), result)
 
1374
 
 
1375
    def test_uses_last_revision_info_and_tags_when_set(self):
 
1376
        transport = MemoryTransport()
 
1377
        client = FakeClient(transport.base)
 
1378
        client.add_expected_call(
 
1379
            'Branch.get_stacked_on_url', ('quack/',),
 
1380
            'error', ('NotStacked',))
 
1381
        client.add_expected_call(
 
1382
            'Branch.last_revision_info', ('quack/',),
 
1383
            'success', ('ok', '1', 'rev-tip'))
 
1384
        client.add_expected_call(
 
1385
            'Branch.get_config_file', ('quack/',),
 
1386
            'success', ('ok',), 'branch.fetch_tags = True')
1186
1387
        # XXX: this will break if the default format's serialization of tags
1187
1388
        # changes, or if the RPC for fetching tags changes from get_tags_bytes.
1188
1389
        client.add_expected_call(
1213
1414
        self.assertFinished(client)
1214
1415
        self.assertEqual((set(['tip']), set(['tagged-1', 'tagged-2'])), result)
1215
1416
 
1216
 
    def test_backwards_compatible(self):
 
1417
    def make_branch_with_tags(self):
1217
1418
        self.setup_smart_server_with_call_log()
1218
1419
        # Make a branch with a single revision.
1219
1420
        builder = self.make_branch_builder('foo')
1225
1426
        # Add two tags to that branch
1226
1427
        branch.tags.set_tag('tag-1', 'rev-1')
1227
1428
        branch.tags.set_tag('tag-2', 'rev-2')
 
1429
        return branch
 
1430
 
 
1431
    def test_backwards_compatible(self):
 
1432
        branch = self.make_branch_with_tags()
 
1433
        c = branch.get_config()
 
1434
        c.set_user_option('branch.fetch_tags', 'True')
1228
1435
        self.addCleanup(branch.lock_read().unlock)
1229
1436
        # Disable the heads_to_fetch verb
1230
1437
        verb = 'Branch.heads_to_fetch'
1233
1440
        result = branch.heads_to_fetch()
1234
1441
        self.assertEqual((set(['tip']), set(['rev-1', 'rev-2'])), result)
1235
1442
        self.assertEqual(
1236
 
            ['Branch.last_revision_info', 'Branch.get_tags_bytes'],
 
1443
            ['Branch.last_revision_info', 'Branch.get_config_file',
 
1444
             'Branch.get_tags_bytes'],
 
1445
            [call.call.method for call in self.hpss_calls])
 
1446
 
 
1447
    def test_backwards_compatible_no_tags(self):
 
1448
        branch = self.make_branch_with_tags()
 
1449
        c = branch.get_config()
 
1450
        c.set_user_option('branch.fetch_tags', 'False')
 
1451
        self.addCleanup(branch.lock_read().unlock)
 
1452
        # Disable the heads_to_fetch verb
 
1453
        verb = 'Branch.heads_to_fetch'
 
1454
        self.disable_verb(verb)
 
1455
        self.reset_smart_call_log()
 
1456
        result = branch.heads_to_fetch()
 
1457
        self.assertEqual((set(['tip']), set()), result)
 
1458
        self.assertEqual(
 
1459
            ['Branch.last_revision_info', 'Branch.get_config_file'],
1237
1460
            [call.call.method for call in self.hpss_calls])
1238
1461
 
1239
1462
 
1401
1624
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1402
1625
            'success', ('ok',))
1403
1626
        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
1627
        branch.lock_write()
1408
1628
        result = branch._set_last_revision(NULL_REVISION)
1409
1629
        branch.unlock()
1438
1658
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1439
1659
            'success', ('ok',))
1440
1660
        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
1661
        # Lock the branch, reset the record of remote calls.
1445
1662
        branch.lock_write()
1446
1663
        result = branch._set_last_revision('rev-id2')
1513
1730
            'Branch.unlock', ('branch/', 'branch token', 'repo token'),
1514
1731
            'success', ('ok',))
1515
1732
        branch = self.make_remote_branch(transport, client)
1516
 
        branch._ensure_real = lambda: None
1517
1733
        branch.lock_write()
1518
1734
        # The 'TipChangeRejected' error response triggered by calling
1519
1735
        # set_last_revision_info causes a TipChangeRejected exception.
1800
2016
        self.assertEqual(value_dict, branch._get_config().get_option('name'))
1801
2017
 
1802
2018
 
 
2019
class TestBranchGetPutConfigStore(RemoteBranchTestCase):
 
2020
 
 
2021
    def test_get_branch_conf(self):
 
2022
        # in an empty branch we decode the response properly
 
2023
        client = FakeClient()
 
2024
        client.add_expected_call(
 
2025
            'Branch.get_stacked_on_url', ('memory:///',),
 
2026
            'error', ('NotStacked',),)
 
2027
        client.add_success_response_with_body('# config file body', 'ok')
 
2028
        transport = MemoryTransport()
 
2029
        branch = self.make_remote_branch(transport, client)
 
2030
        config = branch.get_config_stack()
 
2031
        config.get("email")
 
2032
        config.get("log_format")
 
2033
        self.assertEqual(
 
2034
            [('call', 'Branch.get_stacked_on_url', ('memory:///',)),
 
2035
             ('call_expecting_body', 'Branch.get_config_file', ('memory:///',))],
 
2036
            client._calls)
 
2037
 
 
2038
    def test_set_branch_conf(self):
 
2039
        client = FakeClient()
 
2040
        client.add_expected_call(
 
2041
            'Branch.get_stacked_on_url', ('memory:///',),
 
2042
            'error', ('NotStacked',),)
 
2043
        client.add_expected_call(
 
2044
            'Branch.lock_write', ('memory:///', '', ''),
 
2045
            'success', ('ok', 'branch token', 'repo token'))
 
2046
        client.add_expected_call(
 
2047
            'Branch.get_config_file', ('memory:///', ),
 
2048
            'success', ('ok', ), "# line 1\n")
 
2049
        client.add_expected_call(
 
2050
            'Branch.put_config_file', ('memory:///', 'branch token',
 
2051
            'repo token'),
 
2052
            'success', ('ok',))
 
2053
        client.add_expected_call(
 
2054
            'Branch.unlock', ('memory:///', 'branch token', 'repo token'),
 
2055
            'success', ('ok',))
 
2056
        transport = MemoryTransport()
 
2057
        branch = self.make_remote_branch(transport, client)
 
2058
        branch.lock_write()
 
2059
        config = branch.get_config_stack()
 
2060
        config.set('email', 'The Dude <lebowski@example.com>')
 
2061
        branch.unlock()
 
2062
        self.assertFinished(client)
 
2063
        self.assertEqual(
 
2064
            [('call', 'Branch.get_stacked_on_url', ('memory:///',)),
 
2065
             ('call', 'Branch.lock_write', ('memory:///', '', '')),
 
2066
             ('call_expecting_body', 'Branch.get_config_file', ('memory:///',)),
 
2067
             ('call_with_body_bytes_expecting_body', 'Branch.put_config_file',
 
2068
                 ('memory:///', 'branch token', 'repo token'),
 
2069
                 '# line 1\nemail = The Dude <lebowski@example.com>\n'),
 
2070
             ('call', 'Branch.unlock', ('memory:///', 'branch token', 'repo token'))],
 
2071
            client._calls)
 
2072
 
 
2073
 
1803
2074
class TestBranchLockWrite(RemoteBranchTestCase):
1804
2075
 
1805
2076
    def test_lock_write_unlockable(self):
1818
2089
        self.assertFinished(client)
1819
2090
 
1820
2091
 
 
2092
class TestBranchRevisionIdToRevno(RemoteBranchTestCase):
 
2093
 
 
2094
    def test_simple(self):
 
2095
        transport = MemoryTransport()
 
2096
        client = FakeClient(transport.base)
 
2097
        client.add_expected_call(
 
2098
            'Branch.get_stacked_on_url', ('quack/',),
 
2099
            'error', ('NotStacked',),)
 
2100
        client.add_expected_call(
 
2101
            'Branch.revision_id_to_revno', ('quack/', 'null:'),
 
2102
            'success', ('ok', '0',),)
 
2103
        client.add_expected_call(
 
2104
            'Branch.revision_id_to_revno', ('quack/', 'unknown'),
 
2105
            'error', ('NoSuchRevision', 'unknown',),)
 
2106
        transport.mkdir('quack')
 
2107
        transport = transport.clone('quack')
 
2108
        branch = self.make_remote_branch(transport, client)
 
2109
        self.assertEquals(0, branch.revision_id_to_revno('null:'))
 
2110
        self.assertRaises(errors.NoSuchRevision,
 
2111
            branch.revision_id_to_revno, 'unknown')
 
2112
        self.assertFinished(client)
 
2113
 
 
2114
    def test_dotted(self):
 
2115
        transport = MemoryTransport()
 
2116
        client = FakeClient(transport.base)
 
2117
        client.add_expected_call(
 
2118
            'Branch.get_stacked_on_url', ('quack/',),
 
2119
            'error', ('NotStacked',),)
 
2120
        client.add_expected_call(
 
2121
            'Branch.revision_id_to_revno', ('quack/', 'null:'),
 
2122
            'success', ('ok', '0',),)
 
2123
        client.add_expected_call(
 
2124
            'Branch.revision_id_to_revno', ('quack/', 'unknown'),
 
2125
            'error', ('NoSuchRevision', 'unknown',),)
 
2126
        transport.mkdir('quack')
 
2127
        transport = transport.clone('quack')
 
2128
        branch = self.make_remote_branch(transport, client)
 
2129
        self.assertEquals((0, ), branch.revision_id_to_dotted_revno('null:'))
 
2130
        self.assertRaises(errors.NoSuchRevision,
 
2131
            branch.revision_id_to_dotted_revno, 'unknown')
 
2132
        self.assertFinished(client)
 
2133
 
 
2134
    def test_dotted_no_smart_verb(self):
 
2135
        self.setup_smart_server_with_call_log()
 
2136
        branch = self.make_branch('.')
 
2137
        self.disable_verb('Branch.revision_id_to_revno')
 
2138
        self.reset_smart_call_log()
 
2139
        self.assertEquals((0, ),
 
2140
            branch.revision_id_to_dotted_revno('null:'))
 
2141
        self.assertLength(7, self.hpss_calls)
 
2142
 
 
2143
 
1821
2144
class TestBzrDirGetSetConfig(RemoteBzrDirTestCase):
1822
2145
 
1823
2146
    def test__get_config(self):
1980
2303
            remote_repo_format.get_format_description())
1981
2304
 
1982
2305
 
 
2306
class TestRepositoryAllRevisionIds(TestRemoteRepository):
 
2307
 
 
2308
    def test_empty(self):
 
2309
        transport_path = 'quack'
 
2310
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2311
        client.add_success_response_with_body('', 'ok')
 
2312
        self.assertEquals([], repo.all_revision_ids())
 
2313
        self.assertEqual(
 
2314
            [('call_expecting_body', 'Repository.all_revision_ids',
 
2315
             ('quack/',))],
 
2316
            client._calls)
 
2317
 
 
2318
    def test_with_some_content(self):
 
2319
        transport_path = 'quack'
 
2320
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2321
        client.add_success_response_with_body(
 
2322
            'rev1\nrev2\nanotherrev\n', 'ok')
 
2323
        self.assertEquals(["rev1", "rev2", "anotherrev"],
 
2324
            repo.all_revision_ids())
 
2325
        self.assertEqual(
 
2326
            [('call_expecting_body', 'Repository.all_revision_ids',
 
2327
             ('quack/',))],
 
2328
            client._calls)
 
2329
 
 
2330
 
1983
2331
class TestRepositoryGatherStats(TestRemoteRepository):
1984
2332
 
1985
2333
    def test_revid_none(self):
2038
2386
                         result)
2039
2387
 
2040
2388
 
 
2389
class TestRepositoryBreakLock(TestRemoteRepository):
 
2390
 
 
2391
    def test_break_lock(self):
 
2392
        transport_path = 'quack'
 
2393
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2394
        client.add_success_response('ok')
 
2395
        repo.break_lock()
 
2396
        self.assertEqual(
 
2397
            [('call', 'Repository.break_lock', ('quack/',))],
 
2398
            client._calls)
 
2399
 
 
2400
 
 
2401
class TestRepositoryGetSerializerFormat(TestRemoteRepository):
 
2402
 
 
2403
    def test_get_serializer_format(self):
 
2404
        transport_path = 'hill'
 
2405
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2406
        client.add_success_response('ok', '7')
 
2407
        self.assertEquals('7', repo.get_serializer_format())
 
2408
        self.assertEqual(
 
2409
            [('call', 'VersionedFileRepository.get_serializer_format',
 
2410
              ('hill/', ))],
 
2411
            client._calls)
 
2412
 
 
2413
 
 
2414
class TestRepositoryReconcile(TestRemoteRepository):
 
2415
 
 
2416
    def test_reconcile(self):
 
2417
        transport_path = 'hill'
 
2418
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2419
        body = ("garbage_inventories: 2\n"
 
2420
                "inconsistent_parents: 3\n")
 
2421
        client.add_expected_call(
 
2422
            'Repository.lock_write', ('hill/', ''),
 
2423
            'success', ('ok', 'a token'))
 
2424
        client.add_success_response_with_body(body, 'ok')
 
2425
        reconciler = repo.reconcile()
 
2426
        self.assertEqual(
 
2427
            [('call', 'Repository.lock_write', ('hill/', '')),
 
2428
             ('call_expecting_body', 'Repository.reconcile',
 
2429
                ('hill/', 'a token'))],
 
2430
            client._calls)
 
2431
        self.assertEquals(2, reconciler.garbage_inventories)
 
2432
        self.assertEquals(3, reconciler.inconsistent_parents)
 
2433
 
 
2434
 
 
2435
class TestRepositoryGetRevisionSignatureText(TestRemoteRepository):
 
2436
 
 
2437
    def test_text(self):
 
2438
        # ('ok',), body with signature text
 
2439
        transport_path = 'quack'
 
2440
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2441
        client.add_success_response_with_body(
 
2442
            'THETEXT', 'ok')
 
2443
        self.assertEquals("THETEXT", repo.get_signature_text("revid"))
 
2444
        self.assertEqual(
 
2445
            [('call_expecting_body', 'Repository.get_revision_signature_text',
 
2446
             ('quack/', 'revid'))],
 
2447
            client._calls)
 
2448
 
 
2449
    def test_no_signature(self):
 
2450
        transport_path = 'quick'
 
2451
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2452
        client.add_error_response('nosuchrevision', 'unknown')
 
2453
        self.assertRaises(errors.NoSuchRevision, repo.get_signature_text,
 
2454
                "unknown")
 
2455
        self.assertEqual(
 
2456
            [('call_expecting_body', 'Repository.get_revision_signature_text',
 
2457
              ('quick/', 'unknown'))],
 
2458
            client._calls)
 
2459
 
 
2460
 
2041
2461
class TestRepositoryGetGraph(TestRemoteRepository):
2042
2462
 
2043
2463
    def test_get_graph(self):
2048
2468
        self.assertNotEqual(graph._parents_provider, repo)
2049
2469
 
2050
2470
 
 
2471
class TestRepositoryAddSignatureText(TestRemoteRepository):
 
2472
 
 
2473
    def test_add_signature_text(self):
 
2474
        transport_path = 'quack'
 
2475
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2476
        client.add_expected_call(
 
2477
            'Repository.lock_write', ('quack/', ''),
 
2478
            'success', ('ok', 'a token'))
 
2479
        client.add_expected_call(
 
2480
            'Repository.start_write_group', ('quack/', 'a token'),
 
2481
            'success', ('ok', ('token1', )))
 
2482
        client.add_expected_call(
 
2483
            'Repository.add_signature_text', ('quack/', 'a token', 'rev1',
 
2484
                'token1'),
 
2485
            'success', ('ok', ), None)
 
2486
        repo.lock_write()
 
2487
        repo.start_write_group()
 
2488
        self.assertIs(None,
 
2489
            repo.add_signature_text("rev1", "every bloody emperor"))
 
2490
        self.assertEqual(
 
2491
            ('call_with_body_bytes_expecting_body',
 
2492
              'Repository.add_signature_text',
 
2493
                ('quack/', 'a token', 'rev1', 'token1'),
 
2494
              'every bloody emperor'),
 
2495
            client._calls[-1])
 
2496
 
 
2497
 
2051
2498
class TestRepositoryGetParentMap(TestRemoteRepository):
2052
2499
 
2053
2500
    def test_get_parent_map_caching(self):
2103
2550
        parents = repo.get_parent_map([rev_id])
2104
2551
        self.assertEqual(
2105
2552
            [('call_with_body_bytes_expecting_body',
2106
 
              'Repository.get_parent_map', ('quack/', 'include-missing:',
2107
 
              rev_id), '\n\n0'),
 
2553
              'Repository.get_parent_map',
 
2554
              ('quack/', 'include-missing:', rev_id), '\n\n0'),
2108
2555
             ('disconnect medium',),
2109
2556
             ('call_expecting_body', 'Repository.get_revision_graph',
2110
2557
              ('quack/', ''))],
2230
2677
        self.assertEqual({}, repo.get_parent_map(['non-existant']))
2231
2678
        self.assertLength(0, self.hpss_calls)
2232
2679
 
 
2680
    def test_exposes_get_cached_parent_map(self):
 
2681
        """RemoteRepository exposes get_cached_parent_map from
 
2682
        _unstacked_provider
 
2683
        """
 
2684
        r1 = u'\u0e33'.encode('utf8')
 
2685
        r2 = u'\u0dab'.encode('utf8')
 
2686
        lines = [' '.join([r2, r1]), r1]
 
2687
        encoded_body = bz2.compress('\n'.join(lines))
 
2688
 
 
2689
        transport_path = 'quack'
 
2690
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2691
        client.add_success_response_with_body(encoded_body, 'ok')
 
2692
        repo.lock_read()
 
2693
        # get_cached_parent_map should *not* trigger an RPC
 
2694
        self.assertEqual({}, repo.get_cached_parent_map([r1]))
 
2695
        self.assertEqual([], client._calls)
 
2696
        self.assertEqual({r2: (r1,)}, repo.get_parent_map([r2]))
 
2697
        self.assertEqual({r1: (NULL_REVISION,)},
 
2698
            repo.get_cached_parent_map([r1]))
 
2699
        self.assertEqual(
 
2700
            [('call_with_body_bytes_expecting_body',
 
2701
              'Repository.get_parent_map', ('quack/', 'include-missing:', r2),
 
2702
              '\n\n0')],
 
2703
            client._calls)
 
2704
        repo.unlock()
 
2705
 
2233
2706
 
2234
2707
class TestGetParentMapAllowsNew(tests.TestCaseWithTransport):
2235
2708
 
2250
2723
        self.assertEqual({'rev1': ('null:',)}, graph.get_parent_map(['rev1']))
2251
2724
 
2252
2725
 
 
2726
class TestRepositoryGetRevisions(TestRemoteRepository):
 
2727
 
 
2728
    def test_hpss_missing_revision(self):
 
2729
        transport_path = 'quack'
 
2730
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2731
        client.add_success_response_with_body(
 
2732
            '', 'ok', '10')
 
2733
        self.assertRaises(errors.NoSuchRevision, repo.get_revisions,
 
2734
            ['somerev1', 'anotherrev2'])
 
2735
        self.assertEqual(
 
2736
            [('call_with_body_bytes_expecting_body', 'Repository.iter_revisions',
 
2737
             ('quack/', ), "somerev1\nanotherrev2")],
 
2738
            client._calls)
 
2739
 
 
2740
    def test_hpss_get_single_revision(self):
 
2741
        transport_path = 'quack'
 
2742
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2743
        somerev1 = Revision("somerev1")
 
2744
        somerev1.committer = "Joe Committer <joe@example.com>"
 
2745
        somerev1.timestamp = 1321828927
 
2746
        somerev1.timezone = -60
 
2747
        somerev1.inventory_sha1 = "691b39be74c67b1212a75fcb19c433aaed903c2b"
 
2748
        somerev1.message = "Message"
 
2749
        body = zlib.compress(chk_bencode_serializer.write_revision_to_string(
 
2750
            somerev1))
 
2751
        # Split up body into two bits to make sure the zlib compression object
 
2752
        # gets data fed twice.
 
2753
        client.add_success_response_with_body(
 
2754
                [body[:10], body[10:]], 'ok', '10')
 
2755
        revs = repo.get_revisions(['somerev1'])
 
2756
        self.assertEquals(revs, [somerev1])
 
2757
        self.assertEqual(
 
2758
            [('call_with_body_bytes_expecting_body', 'Repository.iter_revisions',
 
2759
             ('quack/', ), "somerev1")],
 
2760
            client._calls)
 
2761
 
 
2762
 
2253
2763
class TestRepositoryGetRevisionGraph(TestRemoteRepository):
2254
2764
 
2255
2765
    def test_null_revision(self):
2406
2916
                              call.call.method == verb])
2407
2917
 
2408
2918
 
 
2919
class TestRepositoryHasSignatureForRevisionId(TestRemoteRepository):
 
2920
 
 
2921
    def test_has_signature_for_revision_id(self):
 
2922
        # ('yes', ) for Repository.has_signature_for_revision_id -> 'True'.
 
2923
        transport_path = 'quack'
 
2924
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2925
        client.add_success_response('yes')
 
2926
        result = repo.has_signature_for_revision_id('A')
 
2927
        self.assertEqual(
 
2928
            [('call', 'Repository.has_signature_for_revision_id',
 
2929
              ('quack/', 'A'))],
 
2930
            client._calls)
 
2931
        self.assertEqual(True, result)
 
2932
 
 
2933
    def test_is_not_shared(self):
 
2934
        # ('no', ) for Repository.has_signature_for_revision_id -> 'False'.
 
2935
        transport_path = 'qwack'
 
2936
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2937
        client.add_success_response('no')
 
2938
        result = repo.has_signature_for_revision_id('A')
 
2939
        self.assertEqual(
 
2940
            [('call', 'Repository.has_signature_for_revision_id',
 
2941
              ('qwack/', 'A'))],
 
2942
            client._calls)
 
2943
        self.assertEqual(False, result)
 
2944
 
 
2945
 
 
2946
class TestRepositoryPhysicalLockStatus(TestRemoteRepository):
 
2947
 
 
2948
    def test_get_physical_lock_status_yes(self):
 
2949
        transport_path = 'qwack'
 
2950
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2951
        client.add_success_response('yes')
 
2952
        result = repo.get_physical_lock_status()
 
2953
        self.assertEqual(
 
2954
            [('call', 'Repository.get_physical_lock_status',
 
2955
              ('qwack/', ))],
 
2956
            client._calls)
 
2957
        self.assertEqual(True, result)
 
2958
 
 
2959
    def test_get_physical_lock_status_no(self):
 
2960
        transport_path = 'qwack'
 
2961
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
2962
        client.add_success_response('no')
 
2963
        result = repo.get_physical_lock_status()
 
2964
        self.assertEqual(
 
2965
            [('call', 'Repository.get_physical_lock_status',
 
2966
              ('qwack/', ))],
 
2967
            client._calls)
 
2968
        self.assertEqual(False, result)
 
2969
 
 
2970
 
2409
2971
class TestRepositoryIsShared(TestRemoteRepository):
2410
2972
 
2411
2973
    def test_is_shared(self):
2431
2993
        self.assertEqual(False, result)
2432
2994
 
2433
2995
 
 
2996
class TestRepositoryMakeWorkingTrees(TestRemoteRepository):
 
2997
 
 
2998
    def test_make_working_trees(self):
 
2999
        # ('yes', ) for Repository.make_working_trees -> 'True'.
 
3000
        transport_path = 'quack'
 
3001
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3002
        client.add_success_response('yes')
 
3003
        result = repo.make_working_trees()
 
3004
        self.assertEqual(
 
3005
            [('call', 'Repository.make_working_trees', ('quack/',))],
 
3006
            client._calls)
 
3007
        self.assertEqual(True, result)
 
3008
 
 
3009
    def test_no_working_trees(self):
 
3010
        # ('no', ) for Repository.make_working_trees -> 'False'.
 
3011
        transport_path = 'qwack'
 
3012
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3013
        client.add_success_response('no')
 
3014
        result = repo.make_working_trees()
 
3015
        self.assertEqual(
 
3016
            [('call', 'Repository.make_working_trees', ('qwack/',))],
 
3017
            client._calls)
 
3018
        self.assertEqual(False, result)
 
3019
 
 
3020
 
2434
3021
class TestRepositoryLockWrite(TestRemoteRepository):
2435
3022
 
2436
3023
    def test_lock_write(self):
2462
3049
            client._calls)
2463
3050
 
2464
3051
 
 
3052
class TestRepositoryWriteGroups(TestRemoteRepository):
 
3053
 
 
3054
    def test_start_write_group(self):
 
3055
        transport_path = 'quack'
 
3056
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3057
        client.add_expected_call(
 
3058
            'Repository.lock_write', ('quack/', ''),
 
3059
            'success', ('ok', 'a token'))
 
3060
        client.add_expected_call(
 
3061
            'Repository.start_write_group', ('quack/', 'a token'),
 
3062
            'success', ('ok', ('token1', )))
 
3063
        repo.lock_write()
 
3064
        repo.start_write_group()
 
3065
 
 
3066
    def test_start_write_group_unsuspendable(self):
 
3067
        # Some repositories do not support suspending write
 
3068
        # groups. For those, fall back to the "real" repository.
 
3069
        transport_path = 'quack'
 
3070
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3071
        def stub_ensure_real():
 
3072
            client._calls.append(('_ensure_real',))
 
3073
            repo._real_repository = _StubRealPackRepository(client._calls)
 
3074
        repo._ensure_real = stub_ensure_real
 
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
            'error', ('UnsuspendableWriteGroup',))
 
3081
        repo.lock_write()
 
3082
        repo.start_write_group()
 
3083
        self.assertEquals(client._calls[-2:], [ 
 
3084
            ('_ensure_real',),
 
3085
            ('start_write_group',)])
 
3086
 
 
3087
    def test_commit_write_group(self):
 
3088
        transport_path = 'quack'
 
3089
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3090
        client.add_expected_call(
 
3091
            'Repository.lock_write', ('quack/', ''),
 
3092
            'success', ('ok', 'a token'))
 
3093
        client.add_expected_call(
 
3094
            'Repository.start_write_group', ('quack/', 'a token'),
 
3095
            'success', ('ok', ['token1']))
 
3096
        client.add_expected_call(
 
3097
            'Repository.commit_write_group', ('quack/', 'a token', ['token1']),
 
3098
            'success', ('ok',))
 
3099
        repo.lock_write()
 
3100
        repo.start_write_group()
 
3101
        repo.commit_write_group()
 
3102
 
 
3103
    def test_abort_write_group(self):
 
3104
        transport_path = 'quack'
 
3105
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3106
        client.add_expected_call(
 
3107
            'Repository.lock_write', ('quack/', ''),
 
3108
            'success', ('ok', 'a token'))
 
3109
        client.add_expected_call(
 
3110
            'Repository.start_write_group', ('quack/', 'a token'),
 
3111
            'success', ('ok', ['token1']))
 
3112
        client.add_expected_call(
 
3113
            'Repository.abort_write_group', ('quack/', 'a token', ['token1']),
 
3114
            'success', ('ok',))
 
3115
        repo.lock_write()
 
3116
        repo.start_write_group()
 
3117
        repo.abort_write_group(False)
 
3118
 
 
3119
    def test_suspend_write_group(self):
 
3120
        transport_path = 'quack'
 
3121
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3122
        self.assertEquals([], repo.suspend_write_group())
 
3123
 
 
3124
    def test_resume_write_group(self):
 
3125
        transport_path = 'quack'
 
3126
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3127
        client.add_expected_call(
 
3128
            'Repository.lock_write', ('quack/', ''),
 
3129
            'success', ('ok', 'a token'))
 
3130
        client.add_expected_call(
 
3131
            'Repository.check_write_group', ('quack/', 'a token', ['token1']),
 
3132
            'success', ('ok',))
 
3133
        repo.lock_write()
 
3134
        repo.resume_write_group(['token1'])
 
3135
 
 
3136
 
2465
3137
class TestRepositorySetMakeWorkingTrees(TestRemoteRepository):
2466
3138
 
2467
3139
    def test_backwards_compat(self):
2526
3198
        self.assertEqual([], client._calls)
2527
3199
 
2528
3200
 
 
3201
class TestRepositoryIterFilesBytes(TestRemoteRepository):
 
3202
    """Test Repository.iter_file_bytes."""
 
3203
 
 
3204
    def test_single(self):
 
3205
        transport_path = 'quack'
 
3206
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3207
        client.add_expected_call(
 
3208
            'Repository.iter_files_bytes', ('quack/', ),
 
3209
            'success', ('ok',), iter(["ok\x000", "\n", zlib.compress("mydata" * 10)]))
 
3210
        for (identifier, byte_stream) in repo.iter_files_bytes([("somefile",
 
3211
                "somerev", "myid")]):
 
3212
            self.assertEquals("myid", identifier)
 
3213
            self.assertEquals("".join(byte_stream), "mydata" * 10)
 
3214
 
 
3215
    def test_missing(self):
 
3216
        transport_path = 'quack'
 
3217
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
3218
        client.add_expected_call(
 
3219
            'Repository.iter_files_bytes',
 
3220
                ('quack/', ),
 
3221
            'error', ('RevisionNotPresent', 'somefile', 'somerev'),
 
3222
            iter(["absent\0somefile\0somerev\n"]))
 
3223
        self.assertRaises(errors.RevisionNotPresent, list,
 
3224
                repo.iter_files_bytes(
 
3225
                [("somefile", "somerev", "myid")]))
 
3226
 
 
3227
 
2529
3228
class TestRepositoryInsertStreamBase(TestRemoteRepository):
2530
3229
    """Base class for Repository.insert_stream and .insert_stream_1.19
2531
3230
    tests.
2806
3505
        self.calls = calls
2807
3506
        self._pack_collection = _StubPackCollection(calls)
2808
3507
 
 
3508
    def start_write_group(self):
 
3509
        self.calls.append(('start_write_group',))
 
3510
 
2809
3511
    def is_in_write_group(self):
2810
3512
        return False
2811
3513
 
3249
3951
        revs = [r for (r,ps) in graph.iter_ancestry([tip])
3250
3952
                if r != NULL_REVISION]
3251
3953
        revs.reverse()
3252
 
        search = _mod_graph.PendingAncestryResult([tip], stacked.repository)
 
3954
        search = vf_search.PendingAncestryResult([tip], stacked.repository)
3253
3955
        self.reset_smart_call_log()
3254
3956
        stream = source.get_stream(search)
3255
3957
        # We trust that if a revision is in the stream the rest of the new
3359
4061
        remote_branch_url = self.smart_server.get_url() + 'remote'
3360
4062
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
3361
4063
        self.hpss_calls = []
3362
 
        local.repository.fetch(remote_branch.repository,
3363
 
                fetch_spec=_mod_graph.EverythingResult(remote_branch.repository))
 
4064
        local.repository.fetch(
 
4065
            remote_branch.repository,
 
4066
            fetch_spec=vf_search.EverythingResult(remote_branch.repository))
3364
4067
        self.assertEqual(['Repository.get_stream_1.19'], self.hpss_calls)
3365
4068
 
3366
4069
    def override_verb(self, verb_name, verb):
3367
4070
        request_handlers = request.request_handlers
3368
4071
        orig_verb = request_handlers.get(verb_name)
 
4072
        orig_info = request_handlers.get_info(verb_name)
3369
4073
        request_handlers.register(verb_name, verb, override_existing=True)
3370
4074
        self.addCleanup(request_handlers.register, verb_name, orig_verb,
3371
 
                override_existing=True)
 
4075
                override_existing=True, info=orig_info)
3372
4076
 
3373
4077
    def test_fetch_everything_backwards_compat(self):
3374
4078
        """Can fetch with EverythingResult even with pre 2.4 servers.
3381
4085
            """A version of the Repository.get_stream_1.19 verb patched to
3382
4086
            reject 'everything' searches the way 2.3 and earlier do.
3383
4087
            """
3384
 
            def recreate_search(self, repository, search_bytes, discard_excess=False):
 
4088
            def recreate_search(self, repository, search_bytes,
 
4089
                                discard_excess=False):
3385
4090
                verb_log.append(search_bytes.split('\n', 1)[0])
3386
4091
                if search_bytes == 'everything':
3387
 
                    return (None, request.FailedSmartServerResponse(('BadSearch',)))
 
4092
                    return (None,
 
4093
                            request.FailedSmartServerResponse(('BadSearch',)))
3388
4094
                return super(OldGetStreamVerb,
3389
4095
                        self).recreate_search(repository, search_bytes,
3390
4096
                            discard_excess=discard_excess)
3395
4101
        remote_branch_url = self.smart_server.get_url() + 'remote'
3396
4102
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
3397
4103
        self.hpss_calls = []
3398
 
        local.repository.fetch(remote_branch.repository,
3399
 
                fetch_spec=_mod_graph.EverythingResult(remote_branch.repository))
 
4104
        local.repository.fetch(
 
4105
            remote_branch.repository,
 
4106
            fetch_spec=vf_search.EverythingResult(remote_branch.repository))
3400
4107
        # make sure the overridden verb was used
3401
4108
        self.assertLength(1, verb_log)
3402
4109
        # more than one HPSS call is needed, but because it's a VFS callback
3403
4110
        # its hard to predict exactly how many.
3404
4111
        self.assertTrue(len(self.hpss_calls) > 1)
3405
4112
 
 
4113
 
 
4114
class TestUpdateBoundBranchWithModifiedBoundLocation(
 
4115
    tests.TestCaseWithTransport):
 
4116
    """Ensure correct handling of bound_location modifications.
 
4117
 
 
4118
    This is tested against a smart server as http://pad.lv/786980 was about a
 
4119
    ReadOnlyError (write attempt during a read-only transaction) which can only
 
4120
    happen in this context.
 
4121
    """
 
4122
 
 
4123
    def setUp(self):
 
4124
        super(TestUpdateBoundBranchWithModifiedBoundLocation, self).setUp()
 
4125
        self.transport_server = test_server.SmartTCPServer_for_testing
 
4126
 
 
4127
    def make_master_and_checkout(self, master_name, checkout_name):
 
4128
        # Create the master branch and its associated checkout
 
4129
        self.master = self.make_branch_and_tree(master_name)
 
4130
        self.checkout = self.master.branch.create_checkout(checkout_name)
 
4131
        # Modify the master branch so there is something to update
 
4132
        self.master.commit('add stuff')
 
4133
        self.last_revid = self.master.commit('even more stuff')
 
4134
        self.bound_location = self.checkout.branch.get_bound_location()
 
4135
 
 
4136
    def assertUpdateSucceeds(self, new_location):
 
4137
        self.checkout.branch.set_bound_location(new_location)
 
4138
        self.checkout.update()
 
4139
        self.assertEquals(self.last_revid, self.checkout.last_revision())
 
4140
 
 
4141
    def test_without_final_slash(self):
 
4142
        self.make_master_and_checkout('master', 'checkout')
 
4143
        # For unclear reasons some users have a bound_location without a final
 
4144
        # '/', simulate that by forcing such a value
 
4145
        self.assertEndsWith(self.bound_location, '/')
 
4146
        self.assertUpdateSucceeds(self.bound_location.rstrip('/'))
 
4147
 
 
4148
    def test_plus_sign(self):
 
4149
        self.make_master_and_checkout('+master', 'checkout')
 
4150
        self.assertUpdateSucceeds(self.bound_location.replace('%2B', '+', 1))
 
4151
 
 
4152
    def test_tilda(self):
 
4153
        # Embed ~ in the middle of the path just to avoid any $HOME
 
4154
        # interpretation
 
4155
        self.make_master_and_checkout('mas~ter', 'checkout')
 
4156
        self.assertUpdateSucceeds(self.bound_location.replace('%2E', '~', 1))
 
4157
 
 
4158
 
 
4159
class TestWithCustomErrorHandler(RemoteBranchTestCase):
 
4160
 
 
4161
    def test_no_context(self):
 
4162
        class OutOfCoffee(errors.BzrError):
 
4163
            """A dummy exception for testing."""
 
4164
 
 
4165
            def __init__(self, urgency):
 
4166
                self.urgency = urgency
 
4167
        remote.no_context_error_translators.register("OutOfCoffee",
 
4168
            lambda err: OutOfCoffee(err.error_args[0]))
 
4169
        transport = MemoryTransport()
 
4170
        client = FakeClient(transport.base)
 
4171
        client.add_expected_call(
 
4172
            'Branch.get_stacked_on_url', ('quack/',),
 
4173
            'error', ('NotStacked',))
 
4174
        client.add_expected_call(
 
4175
            'Branch.last_revision_info',
 
4176
            ('quack/',),
 
4177
            'error', ('OutOfCoffee', 'low'))
 
4178
        transport.mkdir('quack')
 
4179
        transport = transport.clone('quack')
 
4180
        branch = self.make_remote_branch(transport, client)
 
4181
        self.assertRaises(OutOfCoffee, branch.last_revision_info)
 
4182
        self.assertFinished(client)
 
4183
 
 
4184
    def test_with_context(self):
 
4185
        class OutOfTea(errors.BzrError):
 
4186
            def __init__(self, branch, urgency):
 
4187
                self.branch = branch
 
4188
                self.urgency = urgency
 
4189
        remote.error_translators.register("OutOfTea",
 
4190
            lambda err, find, path: OutOfTea(err.error_args[0],
 
4191
                find("branch")))
 
4192
        transport = MemoryTransport()
 
4193
        client = FakeClient(transport.base)
 
4194
        client.add_expected_call(
 
4195
            'Branch.get_stacked_on_url', ('quack/',),
 
4196
            'error', ('NotStacked',))
 
4197
        client.add_expected_call(
 
4198
            'Branch.last_revision_info',
 
4199
            ('quack/',),
 
4200
            'error', ('OutOfTea', 'low'))
 
4201
        transport.mkdir('quack')
 
4202
        transport = transport.clone('quack')
 
4203
        branch = self.make_remote_branch(transport, client)
 
4204
        self.assertRaises(OutOfTea, branch.last_revision_info)
 
4205
        self.assertFinished(client)
 
4206
 
 
4207
 
 
4208
class TestRepositoryPack(TestRemoteRepository):
 
4209
 
 
4210
    def test_pack(self):
 
4211
        transport_path = 'quack'
 
4212
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4213
        client.add_expected_call(
 
4214
            'Repository.lock_write', ('quack/', ''),
 
4215
            'success', ('ok', 'token'))
 
4216
        client.add_expected_call(
 
4217
            'Repository.pack', ('quack/', 'token', 'False'),
 
4218
            'success', ('ok',), )
 
4219
        client.add_expected_call(
 
4220
            'Repository.unlock', ('quack/', 'token'),
 
4221
            'success', ('ok', ))
 
4222
        repo.pack()
 
4223
 
 
4224
    def test_pack_with_hint(self):
 
4225
        transport_path = 'quack'
 
4226
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4227
        client.add_expected_call(
 
4228
            'Repository.lock_write', ('quack/', ''),
 
4229
            'success', ('ok', 'token'))
 
4230
        client.add_expected_call(
 
4231
            'Repository.pack', ('quack/', 'token', 'False'),
 
4232
            'success', ('ok',), )
 
4233
        client.add_expected_call(
 
4234
            'Repository.unlock', ('quack/', 'token', 'False'),
 
4235
            'success', ('ok', ))
 
4236
        repo.pack(['hinta', 'hintb'])
 
4237
 
 
4238
 
 
4239
class TestRepositoryIterInventories(TestRemoteRepository):
 
4240
    """Test Repository.iter_inventories."""
 
4241
 
 
4242
    def _serialize_inv_delta(self, old_name, new_name, delta):
 
4243
        serializer = inventory_delta.InventoryDeltaSerializer(True, False)
 
4244
        return "".join(serializer.delta_to_lines(old_name, new_name, delta))
 
4245
 
 
4246
    def test_single_empty(self):
 
4247
        transport_path = 'quack'
 
4248
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4249
        fmt = bzrdir.format_registry.get('2a')().repository_format
 
4250
        repo._format = fmt
 
4251
        stream = [('inventory-deltas', [
 
4252
            versionedfile.FulltextContentFactory('somerevid', None, None,
 
4253
                self._serialize_inv_delta('null:', 'somerevid', []))])]
 
4254
        client.add_expected_call(
 
4255
            'VersionedFileRepository.get_inventories', ('quack/', 'unordered'),
 
4256
            'success', ('ok', ),
 
4257
            _stream_to_byte_stream(stream, fmt))
 
4258
        ret = list(repo.iter_inventories(["somerevid"]))
 
4259
        self.assertLength(1, ret)
 
4260
        inv = ret[0]
 
4261
        self.assertEquals("somerevid", inv.revision_id)
 
4262
 
 
4263
    def test_empty(self):
 
4264
        transport_path = 'quack'
 
4265
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4266
        ret = list(repo.iter_inventories([]))
 
4267
        self.assertEquals(ret, [])
 
4268
 
 
4269
    def test_missing(self):
 
4270
        transport_path = 'quack'
 
4271
        repo, client = self.setup_fake_client_and_repository(transport_path)
 
4272
        client.add_expected_call(
 
4273
            'VersionedFileRepository.get_inventories', ('quack/', 'unordered'),
 
4274
            'success', ('ok', ), iter([]))
 
4275
        self.assertRaises(errors.NoSuchRevision, list, repo.iter_inventories(
 
4276
            ["somerevid"]))