~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_remote.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2011-01-13 02:43:21 UTC
  • mfrom: (5582.9.2 funky-chars)
  • Revision ID: pqm@pqm.ubuntu.com-20110113024321-d1ssmy4knbv806zp
(jelmer) Avoid hardcoded list of repository formats that do not support
 funky characters in filenames. (Jelmer Vernooij)

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
    config,
33
33
    controldir,
34
34
    errors,
35
 
    graph as _mod_graph,
 
35
    graph,
36
36
    inventory,
37
37
    inventory_delta,
38
38
    remote,
52
52
    RemoteBranch,
53
53
    RemoteBranchFormat,
54
54
    RemoteBzrDir,
55
 
    RemoteBzrDirFormat,
56
55
    RemoteRepository,
57
56
    RemoteRepositoryFormat,
58
57
    )
59
 
from bzrlib.repofmt import groupcompress_repo, knitpack_repo
 
58
from bzrlib.repofmt import groupcompress_repo, pack_repo
60
59
from bzrlib.revision import NULL_REVISION
61
 
from bzrlib.smart import medium, request
 
60
from bzrlib.smart import medium
62
61
from bzrlib.smart.client import _SmartClient
63
 
from bzrlib.smart.repository import (
64
 
    SmartServerRepositoryGetParentMap,
65
 
    SmartServerRepositoryGetStream_1_19,
66
 
    )
 
62
from bzrlib.smart.repository import SmartServerRepositoryGetParentMap
67
63
from bzrlib.tests import (
68
64
    test_server,
69
65
    )
96
92
        self.addCleanup(self.transport.disconnect)
97
93
 
98
94
    def test_create_remote_bzrdir(self):
99
 
        b = remote.RemoteBzrDir(self.transport, RemoteBzrDirFormat())
 
95
        b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
100
96
        self.assertIsInstance(b, BzrDir)
101
97
 
102
98
    def test_open_remote_branch(self):
103
99
        # open a standalone branch in the working directory
104
 
        b = remote.RemoteBzrDir(self.transport, RemoteBzrDirFormat())
 
100
        b = remote.RemoteBzrDir(self.transport, remote.RemoteBzrDirFormat())
105
101
        branch = b.open_branch()
106
102
        self.assertIsInstance(branch, Branch)
107
103
 
125
121
        fmt = BzrDirFormat.find_format(self.transport)
126
122
        self.assertTrue(bzrdir.RemoteBzrProber
127
123
                        in controldir.ControlDirFormat._server_probers)
128
 
        self.assertIsInstance(fmt, RemoteBzrDirFormat)
 
124
        self.assertIsInstance(fmt, remote.RemoteBzrDirFormat)
129
125
 
130
126
    def test_open_detected_smart_format(self):
131
127
        fmt = BzrDirFormat.find_format(self.transport)
451
447
        client.add_expected_call(
452
448
            'BzrDir.open_branchV3', ('quack/',),
453
449
            'success', ('ref', self.get_url('referenced'))),
454
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
450
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
455
451
            _client=client)
456
452
        result = a_bzrdir.cloning_metadir()
457
453
        # We should have got a control dir matching the referenced branch.
470
466
        client.add_expected_call(
471
467
            'BzrDir.cloning_metadir', ('quack/', 'False'),
472
468
            'success', (control_name, '', ('branch', ''))),
473
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
469
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
474
470
            _client=client)
475
471
        result = a_bzrdir.cloning_metadir()
476
472
        # We should have got a reference control dir with default branch and
496
492
        client.add_expected_call(
497
493
            'BzrDir.open_2.1', ('quack/',), 'success', ('no',))
498
494
        self.assertRaises(errors.NotBranchError, RemoteBzrDir, transport,
499
 
                RemoteBzrDirFormat(), _client=client, _force_probe=True)
 
495
                remote.RemoteBzrDirFormat(), _client=client, _force_probe=True)
500
496
        self.assertFinished(client)
501
497
 
502
498
    def test_present_without_workingtree(self):
503
499
        client, transport = self.make_fake_client_and_transport()
504
500
        client.add_expected_call(
505
501
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'no'))
506
 
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
502
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
507
503
            _client=client, _force_probe=True)
508
504
        self.assertIsInstance(bd, RemoteBzrDir)
509
505
        self.assertFalse(bd.has_workingtree())
514
510
        client, transport = self.make_fake_client_and_transport()
515
511
        client.add_expected_call(
516
512
            'BzrDir.open_2.1', ('quack/',), 'success', ('yes', 'yes'))
517
 
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
513
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
518
514
            _client=client, _force_probe=True)
519
515
        self.assertIsInstance(bd, RemoteBzrDir)
520
516
        self.assertTrue(bd.has_workingtree())
527
523
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
528
524
        client.add_expected_call(
529
525
            'BzrDir.open', ('quack/',), 'success', ('yes',))
530
 
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
526
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
531
527
            _client=client, _force_probe=True)
532
528
        self.assertIsInstance(bd, RemoteBzrDir)
533
529
        self.assertFinished(client)
549
545
            'BzrDir.open_2.1', ('quack/',), 'unknown', ('BzrDir.open_2.1',))
550
546
        client.add_expected_call(
551
547
            'BzrDir.open', ('quack/',), 'success', ('yes',))
552
 
        bd = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
548
        bd = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
553
549
            _client=client, _force_probe=True)
554
550
        self.assertIsInstance(bd, RemoteBzrDir)
555
551
        self.assertFinished(client)
586
582
        client.add_expected_call(
587
583
            'Branch.get_stacked_on_url', ('quack/',),
588
584
            'error', ('NotStacked',))
589
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
585
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
590
586
            _client=client)
591
587
        result = bzrdir.open_branch()
592
588
        self.assertIsInstance(result, RemoteBranch)
599
595
        transport = transport.clone('quack')
600
596
        client = FakeClient(transport.base)
601
597
        client.add_error_response('nobranch')
602
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
598
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
603
599
            _client=client)
604
600
        self.assertRaises(errors.NotBranchError, bzrdir.open_branch)
605
601
        self.assertEqual(
616
612
        transport = MemoryTransport()
617
613
        # no requests on the network - catches other api calls being made.
618
614
        client = FakeClient(transport.base)
619
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
615
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
620
616
            _client=client)
621
617
        # patch the open_branch call to record that it was called.
622
618
        bzrdir.open_branch = open_branch
641
637
        client.add_expected_call(
642
638
            'Branch.get_stacked_on_url', ('~hello/',),
643
639
            'error', ('NotStacked',))
644
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
640
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
645
641
            _client=client)
646
642
        result = bzrdir.open_branch()
647
643
        self.assertFinished(client)
664
660
        client.add_success_response(
665
661
            'ok', '', rich_response, subtree_response, external_lookup,
666
662
            network_name)
667
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
663
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
668
664
            _client=client)
669
665
        result = bzrdir.open_repository()
670
666
        self.assertEqual(
716
712
            'BzrDir.create_branch', ('quack/', network_name),
717
713
            'success', ('ok', network_name, '', 'no', 'no', 'yes',
718
714
            reference_repo_name))
719
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
715
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
720
716
            _client=client)
721
717
        branch = a_bzrdir.create_branch()
722
718
        # We should have got a remote branch
725
721
        format = branch._format
726
722
        self.assertEqual(network_name, format.network_name())
727
723
 
728
 
    def test_already_open_repo_and_reused_medium(self):
729
 
        """Bug 726584: create_branch(..., repository=repo) should work
730
 
        regardless of what the smart medium's base URL is.
731
 
        """
732
 
        self.transport_server = test_server.SmartTCPServer_for_testing
733
 
        transport = self.get_transport('.')
734
 
        repo = self.make_repository('quack')
735
 
        # Client's medium rooted a transport root (not at the bzrdir)
736
 
        client = FakeClient(transport.base)
737
 
        transport = transport.clone('quack')
738
 
        reference_bzrdir_format = bzrdir.format_registry.get('default')()
739
 
        reference_format = reference_bzrdir_format.get_branch_format()
740
 
        network_name = reference_format.network_name()
741
 
        reference_repo_fmt = reference_bzrdir_format.repository_format
742
 
        reference_repo_name = reference_repo_fmt.network_name()
743
 
        client.add_expected_call(
744
 
            'BzrDir.create_branch', ('extra/quack/', network_name),
745
 
            'success', ('ok', network_name, '', 'no', 'no', 'yes',
746
 
            reference_repo_name))
747
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
748
 
            _client=client)
749
 
        branch = a_bzrdir.create_branch(repository=repo)
750
 
        # We should have got a remote branch
751
 
        self.assertIsInstance(branch, remote.RemoteBranch)
752
 
        # its format should have the settings from the response
753
 
        format = branch._format
754
 
        self.assertEqual(network_name, format.network_name())
755
 
 
756
724
 
757
725
class TestBzrDirCreateRepository(TestRemote):
758
726
 
779
747
                'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
780
748
                'False'),
781
749
            'success', ('ok', 'yes', 'yes', 'yes', network_name))
782
 
        a_bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
750
        a_bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
783
751
            _client=client)
784
752
        repo = a_bzrdir.create_repository()
785
753
        # We should have got a remote repository
814
782
        client.add_success_response('stat', '0', '65535')
815
783
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
816
784
            _client=client)
817
 
        bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
 
785
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
818
786
            _client=client)
819
787
        repo = bzrdir.open_repository()
820
788
        self.assertEqual(
847
815
        client.add_success_response('stat', '0', '65535')
848
816
        remote_transport = RemoteTransport(server_url + 'quack/', medium=False,
849
817
            _client=client)
850
 
        bzrdir = RemoteBzrDir(remote_transport, RemoteBzrDirFormat(),
 
818
        bzrdir = RemoteBzrDir(remote_transport, remote.RemoteBzrDirFormat(),
851
819
            _client=client)
852
820
        repo = bzrdir.open_repository()
853
821
        self.assertEqual(
868
836
        transport = transport.clone('quack')
869
837
        client = FakeClient(transport.base)
870
838
        client.add_success_response('ok', '', 'no', 'no', 'no', network_name)
871
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
839
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
872
840
            _client=client)
873
841
        repo = bzrdir.open_repository()
874
842
        self.assertEqual(
881
849
 
882
850
    def test_success(self):
883
851
        """Simple test for typical successful call."""
884
 
        fmt = RemoteBzrDirFormat()
 
852
        fmt = bzrdir.RemoteBzrDirFormat()
885
853
        default_format_name = BzrDirFormat.get_default_format().network_name()
886
854
        transport = self.get_transport()
887
855
        client = FakeClient(transport.base)
903
871
        """Error responses are translated, e.g. 'PermissionDenied' raises the
904
872
        corresponding error from the client.
905
873
        """
906
 
        fmt = RemoteBzrDirFormat()
 
874
        fmt = bzrdir.RemoteBzrDirFormat()
907
875
        default_format_name = BzrDirFormat.get_default_format().network_name()
908
876
        transport = self.get_transport()
909
877
        client = FakeClient(transport.base)
927
895
        """Integration test for error translation."""
928
896
        transport = self.make_smart_server('foo')
929
897
        transport = transport.clone('no-such-path')
930
 
        fmt = RemoteBzrDirFormat()
 
898
        fmt = bzrdir.RemoteBzrDirFormat()
931
899
        err = self.assertRaises(errors.NoSuchFile,
932
900
            fmt.initialize_on_transport_ex, transport, create_prefix=False)
933
901
 
964
932
 
965
933
    def make_remote_bzrdir(self, transport, client):
966
934
        """Make a RemotebzrDir using 'client' as the _client."""
967
 
        return RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
935
        return RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
968
936
            _client=client)
969
937
 
970
938
 
1172
1140
            [('set_tags_bytes', 'tags bytes')] * 2, real_branch.calls)
1173
1141
 
1174
1142
 
1175
 
class TestBranchHeadsToFetch(RemoteBranchTestCase):
1176
 
 
1177
 
    def test_uses_last_revision_info_and_tags_by_default(self):
1178
 
        transport = MemoryTransport()
1179
 
        client = FakeClient(transport.base)
1180
 
        client.add_expected_call(
1181
 
            'Branch.get_stacked_on_url', ('quack/',),
1182
 
            'error', ('NotStacked',))
1183
 
        client.add_expected_call(
1184
 
            'Branch.last_revision_info', ('quack/',),
1185
 
            'success', ('ok', '1', 'rev-tip'))
1186
 
        client.add_expected_call(
1187
 
            'Branch.get_config_file', ('quack/',),
1188
 
            'success', ('ok',), '')
1189
 
        transport.mkdir('quack')
1190
 
        transport = transport.clone('quack')
1191
 
        branch = self.make_remote_branch(transport, client)
1192
 
        result = branch.heads_to_fetch()
1193
 
        self.assertFinished(client)
1194
 
        self.assertEqual((set(['rev-tip']), set()), result)
1195
 
 
1196
 
    def test_uses_last_revision_info_and_tags_when_set(self):
1197
 
        transport = MemoryTransport()
1198
 
        client = FakeClient(transport.base)
1199
 
        client.add_expected_call(
1200
 
            'Branch.get_stacked_on_url', ('quack/',),
1201
 
            'error', ('NotStacked',))
1202
 
        client.add_expected_call(
1203
 
            'Branch.last_revision_info', ('quack/',),
1204
 
            'success', ('ok', '1', 'rev-tip'))
1205
 
        client.add_expected_call(
1206
 
            'Branch.get_config_file', ('quack/',),
1207
 
            'success', ('ok',), 'branch.fetch_tags = True')
1208
 
        # XXX: this will break if the default format's serialization of tags
1209
 
        # changes, or if the RPC for fetching tags changes from get_tags_bytes.
1210
 
        client.add_expected_call(
1211
 
            'Branch.get_tags_bytes', ('quack/',),
1212
 
            'success', ('d5:tag-17:rev-foo5:tag-27:rev-bare',))
1213
 
        transport.mkdir('quack')
1214
 
        transport = transport.clone('quack')
1215
 
        branch = self.make_remote_branch(transport, client)
1216
 
        result = branch.heads_to_fetch()
1217
 
        self.assertFinished(client)
1218
 
        self.assertEqual(
1219
 
            (set(['rev-tip']), set(['rev-foo', 'rev-bar'])), result)
1220
 
 
1221
 
    def test_uses_rpc_for_formats_with_non_default_heads_to_fetch(self):
1222
 
        transport = MemoryTransport()
1223
 
        client = FakeClient(transport.base)
1224
 
        client.add_expected_call(
1225
 
            'Branch.get_stacked_on_url', ('quack/',),
1226
 
            'error', ('NotStacked',))
1227
 
        client.add_expected_call(
1228
 
            'Branch.heads_to_fetch', ('quack/',),
1229
 
            'success', (['tip'], ['tagged-1', 'tagged-2']))
1230
 
        transport.mkdir('quack')
1231
 
        transport = transport.clone('quack')
1232
 
        branch = self.make_remote_branch(transport, client)
1233
 
        branch._format._use_default_local_heads_to_fetch = lambda: False
1234
 
        result = branch.heads_to_fetch()
1235
 
        self.assertFinished(client)
1236
 
        self.assertEqual((set(['tip']), set(['tagged-1', 'tagged-2'])), result)
1237
 
 
1238
 
    def make_branch_with_tags(self):
1239
 
        self.setup_smart_server_with_call_log()
1240
 
        # Make a branch with a single revision.
1241
 
        builder = self.make_branch_builder('foo')
1242
 
        builder.start_series()
1243
 
        builder.build_snapshot('tip', None, [
1244
 
            ('add', ('', 'root-id', 'directory', ''))])
1245
 
        builder.finish_series()
1246
 
        branch = builder.get_branch()
1247
 
        # Add two tags to that branch
1248
 
        branch.tags.set_tag('tag-1', 'rev-1')
1249
 
        branch.tags.set_tag('tag-2', 'rev-2')
1250
 
        return branch
1251
 
 
1252
 
    def test_backwards_compatible(self):
1253
 
        branch = self.make_branch_with_tags()
1254
 
        c = branch.get_config()
1255
 
        c.set_user_option('branch.fetch_tags', 'True')
1256
 
        self.addCleanup(branch.lock_read().unlock)
1257
 
        # Disable the heads_to_fetch verb
1258
 
        verb = 'Branch.heads_to_fetch'
1259
 
        self.disable_verb(verb)
1260
 
        self.reset_smart_call_log()
1261
 
        result = branch.heads_to_fetch()
1262
 
        self.assertEqual((set(['tip']), set(['rev-1', 'rev-2'])), result)
1263
 
        self.assertEqual(
1264
 
            ['Branch.last_revision_info', 'Branch.get_config_file',
1265
 
             'Branch.get_tags_bytes'],
1266
 
            [call.call.method for call in self.hpss_calls])
1267
 
 
1268
 
    def test_backwards_compatible_no_tags(self):
1269
 
        branch = self.make_branch_with_tags()
1270
 
        c = branch.get_config()
1271
 
        c.set_user_option('branch.fetch_tags', 'False')
1272
 
        self.addCleanup(branch.lock_read().unlock)
1273
 
        # Disable the heads_to_fetch verb
1274
 
        verb = 'Branch.heads_to_fetch'
1275
 
        self.disable_verb(verb)
1276
 
        self.reset_smart_call_log()
1277
 
        result = branch.heads_to_fetch()
1278
 
        self.assertEqual((set(['tip']), set()), result)
1279
 
        self.assertEqual(
1280
 
            ['Branch.last_revision_info', 'Branch.get_config_file'],
1281
 
            [call.call.method for call in self.hpss_calls])
1282
 
 
1283
 
 
1284
1143
class TestBranchLastRevisionInfo(RemoteBranchTestCase):
1285
1144
 
1286
1145
    def test_empty_branch(self):
1341
1200
        client.add_expected_call(
1342
1201
            'Branch.get_stacked_on_url', ('stacked/',),
1343
1202
            'success', ('ok', vfs_url))
1344
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
1203
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1345
1204
            _client=client)
1346
1205
        repo_fmt = remote.RemoteRepositoryFormat()
1347
1206
        repo_fmt._custom_format = stacked_branch.repository._format
1374
1233
        # this will also do vfs access, but that goes direct to the transport
1375
1234
        # and isn't seen by the FakeClient.
1376
1235
        bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1377
 
            RemoteBzrDirFormat(), _client=client)
 
1236
            remote.RemoteBzrDirFormat(), _client=client)
1378
1237
        branch = bzrdir.open_branch()
1379
1238
        result = branch.get_stacked_on_url()
1380
1239
        self.assertEqual('../base', result)
1407
1266
            'Branch.get_stacked_on_url', ('stacked/',),
1408
1267
            'success', ('ok', '../base'))
1409
1268
        bzrdir = RemoteBzrDir(self.get_transport('stacked'),
1410
 
            RemoteBzrDirFormat(), _client=client)
 
1269
            remote.RemoteBzrDirFormat(), _client=client)
1411
1270
        branch = bzrdir.open_branch()
1412
1271
        result = branch.get_stacked_on_url()
1413
1272
        self.assertEqual('../base', result)
1421
1280
class TestBranchSetLastRevision(RemoteBranchTestCase):
1422
1281
 
1423
1282
    def test_set_empty(self):
1424
 
        # _set_last_revision_info('null:') is translated to calling
 
1283
        # set_revision_history([]) is translated to calling
1425
1284
        # Branch.set_last_revision(path, '') on the wire.
1426
1285
        transport = MemoryTransport()
1427
1286
        transport.mkdir('branch')
1449
1308
        # unnecessarily invokes _ensure_real upon a call to lock_write.
1450
1309
        branch._ensure_real = lambda: None
1451
1310
        branch.lock_write()
1452
 
        result = branch._set_last_revision(NULL_REVISION)
 
1311
        result = branch.set_revision_history([])
1453
1312
        branch.unlock()
1454
1313
        self.assertEqual(None, result)
1455
1314
        self.assertFinished(client)
1456
1315
 
1457
1316
    def test_set_nonempty(self):
1458
 
        # set_last_revision_info(N, rev-idN) is translated to calling
 
1317
        # set_revision_history([rev-id1, ..., rev-idN]) is translated to calling
1459
1318
        # Branch.set_last_revision(path, rev-idN) on the wire.
1460
1319
        transport = MemoryTransport()
1461
1320
        transport.mkdir('branch')
1487
1346
        branch._ensure_real = lambda: None
1488
1347
        # Lock the branch, reset the record of remote calls.
1489
1348
        branch.lock_write()
1490
 
        result = branch._set_last_revision('rev-id2')
 
1349
        result = branch.set_revision_history(['rev-id1', 'rev-id2'])
1491
1350
        branch.unlock()
1492
1351
        self.assertEqual(None, result)
1493
1352
        self.assertFinished(client)
1523
1382
        branch = self.make_remote_branch(transport, client)
1524
1383
        branch.lock_write()
1525
1384
        self.assertRaises(
1526
 
            errors.NoSuchRevision, branch._set_last_revision, 'rev-id')
 
1385
            errors.NoSuchRevision, branch.set_revision_history, ['rev-id'])
1527
1386
        branch.unlock()
1528
1387
        self.assertFinished(client)
1529
1388
 
1560
1419
        branch._ensure_real = lambda: None
1561
1420
        branch.lock_write()
1562
1421
        # The 'TipChangeRejected' error response triggered by calling
1563
 
        # set_last_revision_info causes a TipChangeRejected exception.
 
1422
        # set_revision_history causes a TipChangeRejected exception.
1564
1423
        err = self.assertRaises(
1565
 
            errors.TipChangeRejected,
1566
 
            branch._set_last_revision, 'rev-id')
 
1424
            errors.TipChangeRejected, branch.set_revision_history, ['rev-id'])
1567
1425
        # The UTF-8 message from the response has been decoded into a unicode
1568
1426
        # object.
1569
1427
        self.assertIsInstance(err.msg, unicode)
1984
1842
        client = FakeClient(transport.base)
1985
1843
        transport = transport.clone(transport_path)
1986
1844
        # we do not want bzrdir to make any remote calls
1987
 
        bzrdir = RemoteBzrDir(transport, RemoteBzrDirFormat(),
 
1845
        bzrdir = RemoteBzrDir(transport, remote.RemoteBzrDirFormat(),
1988
1846
            _client=False)
1989
1847
        repo = RemoteRepository(bzrdir, None, _client=client)
1990
1848
        return repo, client
1998
1856
 
1999
1857
    def test_get_format_description(self):
2000
1858
        remote_format = RemoteBranchFormat()
2001
 
        real_format = branch.format_registry.get_default()
 
1859
        real_format = branch.BranchFormat.get_default_format()
2002
1860
        remote_format._network_name = real_format.network_name()
2003
1861
        self.assertEqual(remoted_description(real_format),
2004
1862
            remote_format.get_format_description())
2011
1869
        true_format = RemoteRepositoryFormat()
2012
1870
        true_format._network_name = true_name
2013
1871
        self.assertEqual(True, true_format.fast_deltas)
2014
 
        false_name = knitpack_repo.RepositoryFormatKnitPack1().network_name()
 
1872
        false_name = pack_repo.RepositoryFormatKnitPack1().network_name()
2015
1873
        false_format = RemoteRepositoryFormat()
2016
1874
        false_format._network_name = false_name
2017
1875
        self.assertEqual(False, false_format.fast_deltas)
2018
1876
 
2019
1877
    def test_get_format_description(self):
2020
1878
        remote_repo_format = RemoteRepositoryFormat()
2021
 
        real_format = repository.format_registry.get_default()
 
1879
        real_format = repository.RepositoryFormat.get_default_format()
2022
1880
        remote_repo_format._network_name = real_format.network_name()
2023
1881
        self.assertEqual(remoted_description(real_format),
2024
1882
            remote_repo_format.get_format_description())
2147
2005
        parents = repo.get_parent_map([rev_id])
2148
2006
        self.assertEqual(
2149
2007
            [('call_with_body_bytes_expecting_body',
2150
 
              'Repository.get_parent_map',
2151
 
              ('quack/', 'include-missing:', rev_id), '\n\n0'),
 
2008
              'Repository.get_parent_map', ('quack/', 'include-missing:',
 
2009
              rev_id), '\n\n0'),
2152
2010
             ('disconnect medium',),
2153
2011
             ('call_expecting_body', 'Repository.get_revision_graph',
2154
2012
              ('quack/', ''))],
2274
2132
        self.assertEqual({}, repo.get_parent_map(['non-existant']))
2275
2133
        self.assertLength(0, self.hpss_calls)
2276
2134
 
2277
 
    def test_exposes_get_cached_parent_map(self):
2278
 
        """RemoteRepository exposes get_cached_parent_map from
2279
 
        _unstacked_provider
2280
 
        """
2281
 
        r1 = u'\u0e33'.encode('utf8')
2282
 
        r2 = u'\u0dab'.encode('utf8')
2283
 
        lines = [' '.join([r2, r1]), r1]
2284
 
        encoded_body = bz2.compress('\n'.join(lines))
2285
 
 
2286
 
        transport_path = 'quack'
2287
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2288
 
        client.add_success_response_with_body(encoded_body, 'ok')
2289
 
        repo.lock_read()
2290
 
        # get_cached_parent_map should *not* trigger an RPC
2291
 
        self.assertEqual({}, repo.get_cached_parent_map([r1]))
2292
 
        self.assertEqual([], client._calls)
2293
 
        self.assertEqual({r2: (r1,)}, repo.get_parent_map([r2]))
2294
 
        self.assertEqual({r1: (NULL_REVISION,)},
2295
 
            repo.get_cached_parent_map([r1]))
2296
 
        self.assertEqual(
2297
 
            [('call_with_body_bytes_expecting_body',
2298
 
              'Repository.get_parent_map', ('quack/', 'include-missing:', r2),
2299
 
              '\n\n0')],
2300
 
            client._calls)
2301
 
        repo.unlock()
2302
 
 
2303
2135
 
2304
2136
class TestGetParentMapAllowsNew(tests.TestCaseWithTransport):
2305
2137
 
2608
2440
        the client is finished.
2609
2441
        """
2610
2442
        sink = repo._get_sink()
2611
 
        fmt = repository.format_registry.get_default()
 
2443
        fmt = repository.RepositoryFormat.get_default_format()
2612
2444
        resume_tokens, missing_keys = sink.insert_stream([], fmt, [])
2613
2445
        self.assertEqual([], resume_tokens)
2614
2446
        self.assertEqual(set(), missing_keys)
2714
2546
                return True
2715
2547
        repo._real_repository = FakeRealRepository()
2716
2548
        sink = repo._get_sink()
2717
 
        fmt = repository.format_registry.get_default()
 
2549
        fmt = repository.RepositoryFormat.get_default_format()
2718
2550
        stream = self.make_stream_with_inv_deltas(fmt)
2719
2551
        resume_tokens, missing_keys = sink.insert_stream(stream, fmt, [])
2720
2552
        # Every record from the first inventory delta should have been sent to
2940
2772
             ('pack collection autopack',)],
2941
2773
            client._calls)
2942
2774
 
2943
 
    def test_oom_error_reporting(self):
2944
 
        """An out-of-memory condition on the server is reported clearly"""
2945
 
        transport_path = 'quack'
2946
 
        repo, client = self.setup_fake_client_and_repository(transport_path)
2947
 
        client.add_expected_call(
2948
 
            'PackRepository.autopack', ('quack/',),
2949
 
            'error', ('MemoryError',))
2950
 
        err = self.assertRaises(errors.BzrError, repo.autopack)
2951
 
        self.assertContainsRe(str(err), "^remote server out of mem")
2952
 
 
2953
2775
 
2954
2776
class TestErrorTranslationBase(tests.TestCaseWithMemoryTransport):
2955
2777
    """Base class for unit tests for bzrlib.remote._translate_error."""
3028
2850
            detail='extra detail')
3029
2851
        self.assertEqual(expected_error, translated_error)
3030
2852
 
3031
 
    def test_norepository(self):
3032
 
        bzrdir = self.make_bzrdir('')
3033
 
        translated_error = self.translateTuple(('norepository',),
3034
 
            bzrdir=bzrdir)
3035
 
        expected_error = errors.NoRepositoryPresent(bzrdir)
3036
 
        self.assertEqual(expected_error, translated_error)
3037
 
 
3038
2853
    def test_LockContention(self):
3039
2854
        translated_error = self.translateTuple(('LockContention',))
3040
2855
        expected_error = errors.LockContention('(remote lock)')
3068
2883
        expected_error = errors.DivergedBranches(branch, other_branch)
3069
2884
        self.assertEqual(expected_error, translated_error)
3070
2885
 
3071
 
    def test_NotStacked(self):
3072
 
        branch = self.make_branch('')
3073
 
        translated_error = self.translateTuple(('NotStacked',), branch=branch)
3074
 
        expected_error = errors.NotStacked(branch)
3075
 
        self.assertEqual(expected_error, translated_error)
3076
 
 
3077
2886
    def test_ReadError_no_args(self):
3078
2887
        path = 'a path'
3079
2888
        translated_error = self.translateTuple(('ReadError',), path=path)
3095
2904
 
3096
2905
    def test_PermissionDenied_no_args(self):
3097
2906
        path = 'a path'
3098
 
        translated_error = self.translateTuple(('PermissionDenied',),
3099
 
            path=path)
 
2907
        translated_error = self.translateTuple(('PermissionDenied',), path=path)
3100
2908
        expected_error = errors.PermissionDenied(path)
3101
2909
        self.assertEqual(expected_error, translated_error)
3102
2910
 
3125
2933
        expected_error = errors.PermissionDenied(path, extra)
3126
2934
        self.assertEqual(expected_error, translated_error)
3127
2935
 
3128
 
    # GZ 2011-03-02: TODO test for PermissionDenied with non-ascii 'extra'
3129
 
 
3130
 
    def test_NoSuchFile_context_path(self):
3131
 
        local_path = "local path"
3132
 
        translated_error = self.translateTuple(('ReadError', "remote path"),
3133
 
            path=local_path)
3134
 
        expected_error = errors.ReadError(local_path)
3135
 
        self.assertEqual(expected_error, translated_error)
3136
 
 
3137
 
    def test_NoSuchFile_without_context(self):
3138
 
        remote_path = "remote path"
3139
 
        translated_error = self.translateTuple(('ReadError', remote_path))
3140
 
        expected_error = errors.ReadError(remote_path)
3141
 
        self.assertEqual(expected_error, translated_error)
3142
 
 
3143
 
    def test_ReadOnlyError(self):
3144
 
        translated_error = self.translateTuple(('ReadOnlyError',))
3145
 
        expected_error = errors.TransportNotPossible("readonly transport")
3146
 
        self.assertEqual(expected_error, translated_error)
3147
 
 
3148
 
    def test_MemoryError(self):
3149
 
        translated_error = self.translateTuple(('MemoryError',))
3150
 
        self.assertStartsWith(str(translated_error),
3151
 
            "remote server out of memory")
3152
 
 
3153
 
    def test_generic_IndexError_no_classname(self):
3154
 
        err = errors.ErrorFromSmartServer(('error', "list index out of range"))
3155
 
        translated_error = self.translateErrorFromSmartServer(err)
3156
 
        expected_error = errors.UnknownErrorFromSmartServer(err)
3157
 
        self.assertEqual(expected_error, translated_error)
3158
 
 
3159
 
    # GZ 2011-03-02: TODO test generic non-ascii error string
3160
 
 
3161
 
    def test_generic_KeyError(self):
3162
 
        err = errors.ErrorFromSmartServer(('error', 'KeyError', "1"))
3163
 
        translated_error = self.translateErrorFromSmartServer(err)
3164
 
        expected_error = errors.UnknownErrorFromSmartServer(err)
3165
 
        self.assertEqual(expected_error, translated_error)
3166
 
 
3167
2936
 
3168
2937
class TestErrorTranslationRobustness(TestErrorTranslationBase):
3169
2938
    """Unit tests for bzrlib.remote._translate_error's robustness.
3314
3083
        _, stacked = branch_factory()
3315
3084
        source = stacked.repository._get_source(target_repository_format)
3316
3085
        tip = stacked.last_revision()
3317
 
        stacked.repository._ensure_real()
3318
 
        graph = stacked.repository.get_graph()
3319
 
        revs = [r for (r,ps) in graph.iter_ancestry([tip])
3320
 
                if r != NULL_REVISION]
3321
 
        revs.reverse()
3322
 
        search = _mod_graph.PendingAncestryResult([tip], stacked.repository)
 
3086
        revs = stacked.repository.get_ancestry(tip)
 
3087
        search = graph.PendingAncestryResult([tip], stacked.repository)
3323
3088
        self.reset_smart_call_log()
3324
3089
        stream = source.get_stream(search)
 
3090
        if None in revs:
 
3091
            revs.remove(None)
3325
3092
        # We trust that if a revision is in the stream the rest of the new
3326
3093
        # content for it is too, as per our main fetch tests; here we are
3327
3094
        # checking that the revisions are actually included at all, and their
3366
3133
        self.assertEqual(expected_revs, rev_ord)
3367
3134
        # Getting topological sort requires VFS calls still - one of which is
3368
3135
        # pushing up from the bound branch.
3369
 
        self.assertLength(14, self.hpss_calls)
 
3136
        self.assertLength(13, self.hpss_calls)
3370
3137
 
3371
3138
    def test_stacked_get_stream_groupcompress(self):
3372
3139
        # Repository._get_source.get_stream() from a stacked repository with
3413
3180
 
3414
3181
    def test_copy_content_into_avoids_revision_history(self):
3415
3182
        local = self.make_branch('local')
3416
 
        builder = self.make_branch_builder('remote')
3417
 
        builder.build_commit(message="Commit.")
 
3183
        remote_backing_tree = self.make_branch_and_tree('remote')
 
3184
        remote_backing_tree.commit("Commit.")
3418
3185
        remote_branch_url = self.smart_server.get_url() + 'remote'
3419
3186
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
3420
3187
        local.repository.fetch(remote_branch.repository)
3421
3188
        self.hpss_calls = []
3422
3189
        remote_branch.copy_content_into(local)
3423
3190
        self.assertFalse('Branch.revision_history' in self.hpss_calls)
3424
 
 
3425
 
    def test_fetch_everything_needs_just_one_call(self):
3426
 
        local = self.make_branch('local')
3427
 
        builder = self.make_branch_builder('remote')
3428
 
        builder.build_commit(message="Commit.")
3429
 
        remote_branch_url = self.smart_server.get_url() + 'remote'
3430
 
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
3431
 
        self.hpss_calls = []
3432
 
        local.repository.fetch(
3433
 
            remote_branch.repository,
3434
 
            fetch_spec=_mod_graph.EverythingResult(remote_branch.repository))
3435
 
        self.assertEqual(['Repository.get_stream_1.19'], self.hpss_calls)
3436
 
 
3437
 
    def override_verb(self, verb_name, verb):
3438
 
        request_handlers = request.request_handlers
3439
 
        orig_verb = request_handlers.get(verb_name)
3440
 
        request_handlers.register(verb_name, verb, override_existing=True)
3441
 
        self.addCleanup(request_handlers.register, verb_name, orig_verb,
3442
 
                override_existing=True)
3443
 
 
3444
 
    def test_fetch_everything_backwards_compat(self):
3445
 
        """Can fetch with EverythingResult even with pre 2.4 servers.
3446
 
        
3447
 
        Pre-2.4 do not support 'everything' searches with the
3448
 
        Repository.get_stream_1.19 verb.
3449
 
        """
3450
 
        verb_log = []
3451
 
        class OldGetStreamVerb(SmartServerRepositoryGetStream_1_19):
3452
 
            """A version of the Repository.get_stream_1.19 verb patched to
3453
 
            reject 'everything' searches the way 2.3 and earlier do.
3454
 
            """
3455
 
            def recreate_search(self, repository, search_bytes,
3456
 
                                discard_excess=False):
3457
 
                verb_log.append(search_bytes.split('\n', 1)[0])
3458
 
                if search_bytes == 'everything':
3459
 
                    return (None,
3460
 
                            request.FailedSmartServerResponse(('BadSearch',)))
3461
 
                return super(OldGetStreamVerb,
3462
 
                        self).recreate_search(repository, search_bytes,
3463
 
                            discard_excess=discard_excess)
3464
 
        self.override_verb('Repository.get_stream_1.19', OldGetStreamVerb)
3465
 
        local = self.make_branch('local')
3466
 
        builder = self.make_branch_builder('remote')
3467
 
        builder.build_commit(message="Commit.")
3468
 
        remote_branch_url = self.smart_server.get_url() + 'remote'
3469
 
        remote_branch = bzrdir.BzrDir.open(remote_branch_url).open_branch()
3470
 
        self.hpss_calls = []
3471
 
        local.repository.fetch(
3472
 
            remote_branch.repository,
3473
 
            fetch_spec=_mod_graph.EverythingResult(remote_branch.repository))
3474
 
        # make sure the overridden verb was used
3475
 
        self.assertLength(1, verb_log)
3476
 
        # more than one HPSS call is needed, but because it's a VFS callback
3477
 
        # its hard to predict exactly how many.
3478
 
        self.assertTrue(len(self.hpss_calls) > 1)
3479
 
 
3480
 
 
3481
 
class TestUpdateBoundBranchWithModifiedBoundLocation(
3482
 
    tests.TestCaseWithTransport):
3483
 
    """Ensure correct handling of bound_location modifications.
3484
 
 
3485
 
    This is tested against a smart server as http://pad.lv/786980 was about a
3486
 
    ReadOnlyError (write attempt during a read-only transaction) which can only
3487
 
    happen in this context.
3488
 
    """
3489
 
 
3490
 
    def setUp(self):
3491
 
        super(TestUpdateBoundBranchWithModifiedBoundLocation, self).setUp()
3492
 
        self.transport_server = test_server.SmartTCPServer_for_testing
3493
 
 
3494
 
    def make_master_and_checkout(self, master_name, checkout_name):
3495
 
        # Create the master branch and its associated checkout
3496
 
        self.master = self.make_branch_and_tree(master_name)
3497
 
        self.checkout = self.master.branch.create_checkout(checkout_name)
3498
 
        # Modify the master branch so there is something to update
3499
 
        self.master.commit('add stuff')
3500
 
        self.last_revid = self.master.commit('even more stuff')
3501
 
        self.bound_location = self.checkout.branch.get_bound_location()
3502
 
 
3503
 
    def assertUpdateSucceeds(self, new_location):
3504
 
        self.checkout.branch.set_bound_location(new_location)
3505
 
        self.checkout.update()
3506
 
        self.assertEquals(self.last_revid, self.checkout.last_revision())
3507
 
 
3508
 
    def test_without_final_slash(self):
3509
 
        self.make_master_and_checkout('master', 'checkout')
3510
 
        # For unclear reasons some users have a bound_location without a final
3511
 
        # '/', simulate that by forcing such a value
3512
 
        self.assertEndsWith(self.bound_location, '/')
3513
 
        self.assertUpdateSucceeds(self.bound_location.rstrip('/'))
3514
 
 
3515
 
    def test_plus_sign(self):
3516
 
        self.make_master_and_checkout('+master', 'checkout')
3517
 
        self.assertUpdateSucceeds(self.bound_location.replace('%2B', '+', 1))
3518
 
 
3519
 
    def test_tilda(self):
3520
 
        # Embed ~ in the middle of the path just to avoid any $HOME
3521
 
        # interpretation
3522
 
        self.make_master_and_checkout('mas~ter', 'checkout')
3523
 
        self.assertUpdateSucceeds(self.bound_location.replace('%2E', '~', 1))