~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/bzrdir_implementations/test_bzrdir.py

Merge in bzr-dir phase 3, enabling controlled upgrades and shared repositories.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
import bzrlib.branch
24
24
import bzrlib.bzrdir as bzrdir
25
25
from bzrlib.branch import Branch, needs_read_lock, needs_write_lock
 
26
from bzrlib.check import check
26
27
from bzrlib.commit import commit
27
28
import bzrlib.errors as errors
28
29
from bzrlib.errors import (FileExists,
32
33
                           NotBranchError,
33
34
                           )
34
35
import bzrlib.repository as repository
35
 
from bzrlib.tests import TestCase, TestCaseWithTransport, TestSkipped
 
36
from bzrlib.tests import (
 
37
                          ChrootedTestCase,
 
38
                          TestCase,
 
39
                          TestCaseWithTransport,
 
40
                          TestSkipped,
 
41
                          )
36
42
from bzrlib.trace import mutter
37
43
import bzrlib.transactions as transactions
38
44
import bzrlib.transport as transport
39
45
from bzrlib.transport import get_transport
 
46
import bzrlib.ui as ui
40
47
from bzrlib.upgrade import upgrade
41
48
import bzrlib.workingtree as workingtree
42
49
 
105
112
        self.assertNotEqual(dir.transport.base, target.transport.base)
106
113
        self.assertDirectoriesEqual(dir.root_transport, target.root_transport)
107
114
    
 
115
    def test_clone_bzrdir_empty_force_new_ignored(self):
 
116
        # the force_new_repo parameter should have no effect on an empty
 
117
        # bzrdir's clone logic
 
118
        dir = self.make_bzrdir('source')
 
119
        target = dir.clone(self.get_url('target'), force_new_repo=True)
 
120
        self.assertNotEqual(dir.transport.base, target.transport.base)
 
121
        self.assertDirectoriesEqual(dir.root_transport, target.root_transport)
 
122
    
108
123
    def test_clone_bzrdir_repository(self):
109
124
        dir = self.make_bzrdir('source')
110
125
        repo = dir.create_repository()
118
133
        self.assertNotEqual(dir.transport.base, target.transport.base)
119
134
        self.assertDirectoriesEqual(dir.root_transport, target.root_transport)
120
135
 
 
136
    def test_clone_bzrdir_repository_under_shared(self):
 
137
        dir = self.make_bzrdir('source')
 
138
        repo = dir.create_repository()
 
139
        # add some content to differentiate from an empty repository.
 
140
        repo.control_weaves.add_text('inventory',
 
141
                                     "A",
 
142
                                     [],
 
143
                                     [],
 
144
                                     repo.get_transaction())
 
145
        try:
 
146
            self.make_repository('target', shared=True)
 
147
        except errors.IncompatibleFormat:
 
148
            return
 
149
        target = dir.clone(self.get_url('target/child'))
 
150
        self.assertNotEqual(dir.transport.base, target.transport.base)
 
151
        self.assertRaises(errors.NoRepositoryPresent, target.open_repository)
 
152
        
 
153
    def test_clone_bzrdir_repository_under_shared_force_new_repo(self):
 
154
        dir = self.make_bzrdir('source')
 
155
        repo = dir.create_repository()
 
156
        # add some content to differentiate from an empty repository.
 
157
        repo.control_weaves.add_text('inventory',
 
158
                                     "A",
 
159
                                     [],
 
160
                                     [],
 
161
                                     repo.get_transaction())
 
162
        try:
 
163
            self.make_repository('target', shared=True)
 
164
        except errors.IncompatibleFormat:
 
165
            return
 
166
        target = dir.clone(self.get_url('target/child'), force_new_repo=True)
 
167
        self.assertNotEqual(dir.transport.base, target.transport.base)
 
168
        self.assertDirectoriesEqual(dir.root_transport, target.root_transport)
 
169
 
121
170
    def test_clone_bzrdir_repository_revision(self):
122
171
        # test for revision limiting, [smoke test, not corner case checks].
123
172
        # make a repository with some revisions,
150
199
        self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
151
200
                                    ['./.bzr/stat-cache', './.bzr/checkout/stat-cache'])
152
201
 
 
202
    def test_clone_bzrdir_branch_and_repo_into_shared_repo(self):
 
203
        # by default cloning into a shared repo uses the shared repo.
 
204
        tree = self.make_branch_and_tree('commit_tree')
 
205
        self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
 
206
        tree.add('foo')
 
207
        tree.commit('revision 1')
 
208
        source = self.make_branch('source')
 
209
        tree.bzrdir.open_repository().copy_content_into(source.repository)
 
210
        tree.bzrdir.open_branch().copy_content_into(source)
 
211
        try:
 
212
            self.make_repository('target', shared=True)
 
213
        except errors.IncompatibleFormat:
 
214
            return
 
215
        dir = source.bzrdir
 
216
        target = dir.clone(self.get_url('target/child'))
 
217
        self.assertNotEqual(dir.transport.base, target.transport.base)
 
218
        self.assertRaises(errors.NoRepositoryPresent, target.open_repository)
 
219
        self.assertEqual(source.revision_history(),
 
220
                         target.open_branch().revision_history())
 
221
 
 
222
    def test_clone_bzrdir_branch_and_repo_into_shared_repo_force_new_repo(self):
 
223
        # by default cloning into a shared repo uses the shared repo.
 
224
        tree = self.make_branch_and_tree('commit_tree')
 
225
        self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
 
226
        tree.add('foo')
 
227
        tree.commit('revision 1')
 
228
        source = self.make_branch('source')
 
229
        tree.bzrdir.open_repository().copy_content_into(source.repository)
 
230
        tree.bzrdir.open_branch().copy_content_into(source)
 
231
        try:
 
232
            self.make_repository('target', shared=True)
 
233
        except errors.IncompatibleFormat:
 
234
            return
 
235
        dir = source.bzrdir
 
236
        target = dir.clone(self.get_url('target/child'), force_new_repo=True)
 
237
        self.assertNotEqual(dir.transport.base, target.transport.base)
 
238
        target.open_repository()
 
239
        self.assertDirectoriesEqual(dir.root_transport, target.root_transport)
 
240
 
153
241
    def test_clone_bzrdir_branch_reference(self):
154
242
        # cloning should preserve the reference status of the branch in a bzrdir
155
243
        referenced_branch = self.make_branch('referencced')
251
339
        target.open_repository()
252
340
        target.open_branch()
253
341
        target.open_workingtree()
 
342
 
 
343
    def test_sprout_bzrdir_empty_under_shared_repo(self):
 
344
        # sprouting an empty dir into a repo uses the repo
 
345
        dir = self.make_bzrdir('source')
 
346
        try:
 
347
            self.make_repository('target', shared=True)
 
348
        except errors.IncompatibleFormat:
 
349
            return
 
350
        target = dir.sprout(self.get_url('target/child'))
 
351
        self.assertRaises(errors.NoRepositoryPresent, target.open_repository)
 
352
        target.open_branch()
 
353
        target.open_workingtree()
 
354
 
 
355
    def test_sprout_bzrdir_empty_under_shared_repo(self):
 
356
        # the force_new_repo parameter should force use of a new repo in an empty
 
357
        # bzrdir's sprout logic
 
358
        dir = self.make_bzrdir('source')
 
359
        try:
 
360
            self.make_repository('target', shared=True)
 
361
        except errors.IncompatibleFormat:
 
362
            return
 
363
        target = dir.sprout(self.get_url('target/child'), force_new_repo=True)
 
364
        target.open_repository()
 
365
        target.open_branch()
 
366
        target.open_workingtree()
254
367
    
255
368
    def test_sprout_bzrdir_repository(self):
256
369
        dir = self.make_bzrdir('source')
265
378
        self.assertNotEqual(dir.transport.base, target.transport.base)
266
379
        self.assertDirectoriesEqual(dir.root_transport, target.root_transport)
267
380
 
 
381
    def test_sprout_bzrdir_repository_under_shared(self):
 
382
        tree = self.make_branch_and_tree('commit_tree')
 
383
        self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
 
384
        tree.add('foo')
 
385
        tree.commit('revision 1', rev_id='1')
 
386
        tree.bzrdir.open_branch().set_revision_history([])
 
387
        tree.set_last_revision(None)
 
388
        tree.commit('revision 2', rev_id='2')
 
389
        source = self.make_repository('source')
 
390
        tree.bzrdir.open_repository().copy_content_into(source)
 
391
        dir = source.bzrdir
 
392
        try:
 
393
            shared_repo = self.make_repository('target', shared=True)
 
394
        except errors.IncompatibleFormat:
 
395
            return
 
396
        target = dir.sprout(self.get_url('target/child'))
 
397
        self.assertNotEqual(dir.transport.base, target.transport.base)
 
398
        self.assertTrue(shared_repo.has_revision('1'))
 
399
 
 
400
    def test_sprout_bzrdir_repository_under_shared_force_new_repo(self):
 
401
        tree = self.make_branch_and_tree('commit_tree')
 
402
        self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
 
403
        tree.add('foo')
 
404
        tree.commit('revision 1', rev_id='1')
 
405
        tree.bzrdir.open_branch().set_revision_history([])
 
406
        tree.set_last_revision(None)
 
407
        tree.commit('revision 2', rev_id='2')
 
408
        source = self.make_repository('source')
 
409
        tree.bzrdir.open_repository().copy_content_into(source)
 
410
        dir = source.bzrdir
 
411
        try:
 
412
            shared_repo = self.make_repository('target', shared=True)
 
413
        except errors.IncompatibleFormat:
 
414
            return
 
415
        target = dir.sprout(self.get_url('target/child'), force_new_repo=True)
 
416
        self.assertNotEqual(dir.transport.base, target.transport.base)
 
417
        self.assertFalse(shared_repo.has_revision('1'))
 
418
 
268
419
    def test_sprout_bzrdir_repository_revision(self):
269
420
        # test for revision limiting, [smoke test, not corner case checks].
270
421
        # make a repository with some revisions,
296
447
        self.assertNotEqual(dir.transport.base, target.transport.base)
297
448
        self.assertDirectoriesEqual(dir.root_transport, target.root_transport)
298
449
 
 
450
    def test_sprout_bzrdir_branch_and_repo_shared(self):
 
451
        # sprouting a branch with a repo into a shared repo uses the shared
 
452
        # repo
 
453
        tree = self.make_branch_and_tree('commit_tree')
 
454
        self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
 
455
        tree.add('foo')
 
456
        tree.commit('revision 1', rev_id='1')
 
457
        source = self.make_branch('source')
 
458
        tree.bzrdir.open_repository().copy_content_into(source.repository)
 
459
        tree.bzrdir.open_branch().copy_content_into(source)
 
460
        dir = source.bzrdir
 
461
        try:
 
462
            shared_repo = self.make_repository('target', shared=True)
 
463
        except errors.IncompatibleFormat:
 
464
            return
 
465
        target = dir.sprout(self.get_url('target/child'))
 
466
        self.assertTrue(shared_repo.has_revision('1'))
 
467
 
 
468
    def test_sprout_bzrdir_branch_and_repo_shared_force_new_repo(self):
 
469
        # sprouting a branch with a repo into a shared repo uses the shared
 
470
        # repo
 
471
        tree = self.make_branch_and_tree('commit_tree')
 
472
        self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
 
473
        tree.add('foo')
 
474
        tree.commit('revision 1', rev_id='1')
 
475
        source = self.make_branch('source')
 
476
        tree.bzrdir.open_repository().copy_content_into(source.repository)
 
477
        tree.bzrdir.open_branch().copy_content_into(source)
 
478
        dir = source.bzrdir
 
479
        try:
 
480
            shared_repo = self.make_repository('target', shared=True)
 
481
        except errors.IncompatibleFormat:
 
482
            return
 
483
        target = dir.sprout(self.get_url('target/child'), force_new_repo=True)
 
484
        self.assertNotEqual(dir.transport.base, target.transport.base)
 
485
        self.assertFalse(shared_repo.has_revision('1'))
 
486
 
299
487
    def test_sprout_bzrdir_branch_reference(self):
300
488
        # sprouting should create a repository if needed and a sprouted branch.
301
489
        referenced_branch = self.make_branch('referencced')
315
503
        # place
316
504
        target.open_repository()
317
505
 
 
506
    def test_sprout_bzrdir_branch_reference_shared(self):
 
507
        # sprouting should create a repository if needed and a sprouted branch.
 
508
        referenced_tree = self.make_branch_and_tree('referenced')
 
509
        referenced_tree.commit('1', rev_id='1', allow_pointless=True)
 
510
        dir = self.make_bzrdir('source')
 
511
        try:
 
512
            reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
 
513
                referenced_tree.branch)
 
514
        except errors.IncompatibleFormat:
 
515
            # this is ok too, not all formats have to support references.
 
516
            return
 
517
        self.assertRaises(errors.NoRepositoryPresent, dir.open_repository)
 
518
        try:
 
519
            shared_repo = self.make_repository('target', shared=True)
 
520
        except errors.IncompatibleFormat:
 
521
            return
 
522
        target = dir.sprout(self.get_url('target/child'))
 
523
        self.assertNotEqual(dir.transport.base, target.transport.base)
 
524
        # we want target to have a branch that is in-place.
 
525
        self.assertEqual(target, target.open_branch().bzrdir)
 
526
        # and we want no repository as the target is shared
 
527
        self.assertRaises(errors.NoRepositoryPresent, 
 
528
                          target.open_repository)
 
529
        # and we want revision '1' in the shared repo
 
530
        self.assertTrue(shared_repo.has_revision('1'))
 
531
 
 
532
    def test_sprout_bzrdir_branch_reference_shared_force_new_repo(self):
 
533
        # sprouting should create a repository if needed and a sprouted branch.
 
534
        referenced_tree = self.make_branch_and_tree('referenced')
 
535
        referenced_tree.commit('1', rev_id='1', allow_pointless=True)
 
536
        dir = self.make_bzrdir('source')
 
537
        try:
 
538
            reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
 
539
                referenced_tree.branch)
 
540
        except errors.IncompatibleFormat:
 
541
            # this is ok too, not all formats have to support references.
 
542
            return
 
543
        self.assertRaises(errors.NoRepositoryPresent, dir.open_repository)
 
544
        try:
 
545
            shared_repo = self.make_repository('target', shared=True)
 
546
        except errors.IncompatibleFormat:
 
547
            return
 
548
        target = dir.sprout(self.get_url('target/child'), force_new_repo=True)
 
549
        self.assertNotEqual(dir.transport.base, target.transport.base)
 
550
        # we want target to have a branch that is in-place.
 
551
        self.assertEqual(target, target.open_branch().bzrdir)
 
552
        # and we want revision '1' in the new repo
 
553
        self.assertTrue(target.open_repository().has_revision('1'))
 
554
        # but not the shared one
 
555
        self.assertFalse(shared_repo.has_revision('1'))
 
556
 
318
557
    def test_sprout_bzrdir_branch_revision(self):
319
558
        # test for revision limiting, [smoke test, not corner case checks].
320
559
        # make a repository with some revisions,
458
697
                          get_transport(self.get_readonly_url()))
459
698
 
460
699
    def test_create_branch(self):
461
 
        # a bzrdir can construct a repository for itself.
 
700
        # a bzrdir can construct a branch and repository for itself.
462
701
        if not self.bzrdir_format.is_supported():
463
702
            # unsupported formats are not loopback testable
464
703
            # because the default open will not open them and
628
867
        self.assertEqual(dir.root_transport.base,
629
868
                         get_transport(self.get_url('.')).base)
630
869
 
 
870
    def test_find_repository_no_repo_under_standalone_branch(self):
 
871
        # finding a repo stops at standalone branches even if there is a
 
872
        # higher repository available.
 
873
        try:
 
874
            repo = self.make_repository('.', shared=True)
 
875
        except errors.IncompatibleFormat:
 
876
            # need a shared repository to test this.
 
877
            return
 
878
        url = self.get_url('intermediate')
 
879
        get_transport(self.get_url()).mkdir('intermediate')
 
880
        get_transport(self.get_url()).mkdir('intermediate/child')
 
881
        made_control = self.bzrdir_format.initialize(url)
 
882
        made_control.create_repository()
 
883
        innermost_control = self.bzrdir_format.initialize(
 
884
            self.get_url('intermediate/child'))
 
885
        try:
 
886
            child_repo = innermost_control.open_repository()
 
887
            # if there is a repository, then the format cannot ever hit this 
 
888
            # code path.
 
889
            return
 
890
        except errors.NoRepositoryPresent:
 
891
            pass
 
892
        self.assertRaises(errors.NoRepositoryPresent,
 
893
                          innermost_control.find_repository)
 
894
 
 
895
    def test_find_repository_containing_shared_repository(self):
 
896
        # find repo inside a shared repo with an empty control dir
 
897
        # returns the shared repo.
 
898
        try:
 
899
            repo = self.make_repository('.', shared=True)
 
900
        except errors.IncompatibleFormat:
 
901
            # need a shared repository to test this.
 
902
            return
 
903
        url = self.get_url('childbzrdir')
 
904
        get_transport(self.get_url()).mkdir('childbzrdir')
 
905
        made_control = self.bzrdir_format.initialize(url)
 
906
        try:
 
907
            child_repo = made_control.open_repository()
 
908
            # if there is a repository, then the format cannot ever hit this 
 
909
            # code path.
 
910
            return
 
911
        except errors.NoRepositoryPresent:
 
912
            pass
 
913
        found_repo = made_control.find_repository()
 
914
        self.assertEqual(repo.bzrdir.root_transport.base,
 
915
                         found_repo.bzrdir.root_transport.base)
 
916
        
 
917
    def test_find_repository_standalone_with_containing_shared_repository(self):
 
918
        # find repo inside a standalone repo inside a shared repo finds the standalone repo
 
919
        try:
 
920
            containing_repo = self.make_repository('.', shared=True)
 
921
        except errors.IncompatibleFormat:
 
922
            # need a shared repository to test this.
 
923
            return
 
924
        child_repo = self.make_repository('childrepo')
 
925
        opened_control = bzrdir.BzrDir.open(self.get_url('childrepo'))
 
926
        found_repo = opened_control.find_repository()
 
927
        self.assertEqual(child_repo.bzrdir.root_transport.base,
 
928
                         found_repo.bzrdir.root_transport.base)
 
929
 
 
930
    def test_find_repository_shared_within_shared_repository(self):
 
931
        # find repo at a shared repo inside a shared repo finds the inner repo
 
932
        try:
 
933
            containing_repo = self.make_repository('.', shared=True)
 
934
        except errors.IncompatibleFormat:
 
935
            # need a shared repository to test this.
 
936
            return
 
937
        url = self.get_url('childrepo')
 
938
        get_transport(self.get_url()).mkdir('childrepo')
 
939
        child_control = self.bzrdir_format.initialize(url)
 
940
        child_repo = child_control.create_repository(shared=True)
 
941
        opened_control = bzrdir.BzrDir.open(self.get_url('childrepo'))
 
942
        found_repo = opened_control.find_repository()
 
943
        self.assertEqual(child_repo.bzrdir.root_transport.base,
 
944
                         found_repo.bzrdir.root_transport.base)
 
945
        self.assertNotEqual(child_repo.bzrdir.root_transport.base,
 
946
                            containing_repo.bzrdir.root_transport.base)
 
947
 
 
948
    def test_find_repository_with_nested_dirs_works(self):
 
949
        # find repo inside a bzrdir inside a bzrdir inside a shared repo 
 
950
        # finds the outer shared repo.
 
951
        try:
 
952
            repo = self.make_repository('.', shared=True)
 
953
        except errors.IncompatibleFormat:
 
954
            # need a shared repository to test this.
 
955
            return
 
956
        url = self.get_url('intermediate')
 
957
        get_transport(self.get_url()).mkdir('intermediate')
 
958
        get_transport(self.get_url()).mkdir('intermediate/child')
 
959
        made_control = self.bzrdir_format.initialize(url)
 
960
        try:
 
961
            child_repo = made_control.open_repository()
 
962
            # if there is a repository, then the format cannot ever hit this 
 
963
            # code path.
 
964
            return
 
965
        except errors.NoRepositoryPresent:
 
966
            pass
 
967
        innermost_control = self.bzrdir_format.initialize(
 
968
            self.get_url('intermediate/child'))
 
969
        try:
 
970
            child_repo = innermost_control.open_repository()
 
971
            # if there is a repository, then the format cannot ever hit this 
 
972
            # code path.
 
973
            return
 
974
        except errors.NoRepositoryPresent:
 
975
            pass
 
976
        found_repo = innermost_control.find_repository()
 
977
        self.assertEqual(repo.bzrdir.root_transport.base,
 
978
                         found_repo.bzrdir.root_transport.base)
 
979
        
 
980
    def test_can_and_needs_format_conversion(self):
 
981
        # check that we can ask an instance if its upgradable
 
982
        dir = self.make_bzrdir('.')
 
983
        if dir.can_convert_format():
 
984
            # if its updatable there must be an updater
 
985
            self.assertTrue(isinstance(dir._format.get_converter(),
 
986
                                       bzrdir.Converter))
 
987
        dir.needs_format_conversion(None)
 
988
 
 
989
    def test_upgrade_new_instance(self):
 
990
        """Does an available updater work ?."""
 
991
        dir = self.make_bzrdir('.')
 
992
        if dir.can_convert_format():
 
993
            dir._format.get_converter(None).convert(dir, ui.ui_factory.progress_bar())
 
994
            # and it should pass 'check' now.
 
995
            check(bzrdir.BzrDir.open(self.get_url('.')).open_branch(), False)
 
996
 
 
997
 
 
998
class ChrootedBzrDirTests(ChrootedTestCase):
 
999
 
 
1000
    def test_find_repository_no_repository(self):
 
1001
        # loopback test to check the current format fails to find a 
 
1002
        # share repository correctly.
 
1003
        if not self.bzrdir_format.is_supported():
 
1004
            # unsupported formats are not loopback testable
 
1005
            # because the default open will not open them and
 
1006
            # they may not be initializable.
 
1007
            return
 
1008
        # supported formats must be able to init and open
 
1009
        url = self.get_url('subdir')
 
1010
        get_transport(self.get_url()).mkdir('subdir')
 
1011
        made_control = self.bzrdir_format.initialize(url)
 
1012
        try:
 
1013
            repo = made_control.open_repository()
 
1014
            # if there is a repository, then the format cannot ever hit this 
 
1015
            # code path.
 
1016
            return
 
1017
        except errors.NoRepositoryPresent:
 
1018
            pass
 
1019
        opened_control = bzrdir.BzrDir.open(self.get_readonly_url('subdir'))
 
1020
        self.assertRaises(errors.NoRepositoryPresent,
 
1021
                          opened_control.find_repository)
 
1022