~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_bzrdir.py

  • Committer: Jelmer Vernooij
  • Date: 2011-12-05 14:12:23 UTC
  • mto: This revision was merged to the branch mainline in revision 6348.
  • Revision ID: jelmer@samba.org-20111205141223-8qxae4h37satlzgq
Move more functionality to vf_search.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
1
# Copyright (C) 2006-2011 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
24
24
import sys
25
25
 
26
26
from bzrlib import (
 
27
    branch,
27
28
    bzrdir,
 
29
    config,
 
30
    controldir,
28
31
    errors,
29
32
    help_topics,
 
33
    lock,
30
34
    repository,
 
35
    revision as _mod_revision,
31
36
    osutils,
32
37
    remote,
 
38
    symbol_versioning,
 
39
    transport as _mod_transport,
33
40
    urlutils,
34
41
    win32utils,
35
 
    workingtree,
 
42
    workingtree_3,
 
43
    workingtree_4,
36
44
    )
37
45
import bzrlib.branch
38
 
from bzrlib.errors import (NotBranchError,
39
 
                           UnknownFormatError,
40
 
                           UnsupportedFormatError,
41
 
                           )
 
46
from bzrlib.errors import (
 
47
    NotBranchError,
 
48
    NoColocatedBranchSupport,
 
49
    UnknownFormatError,
 
50
    UnsupportedFormatError,
 
51
    )
42
52
from bzrlib.tests import (
43
53
    TestCase,
44
54
    TestCaseWithMemoryTransport,
51
61
    )
52
62
from bzrlib.tests.test_http import TestWithTransport_pycurl
53
63
from bzrlib.transport import (
54
 
    get_transport,
55
64
    memory,
 
65
    pathfilter,
56
66
    )
57
67
from bzrlib.transport.http._urllib import HttpTransport_urllib
58
68
from bzrlib.transport.nosmart import NoSmartTransportDecorator
59
69
from bzrlib.transport.readonly import ReadonlyTransportDecorator
60
 
from bzrlib.repofmt import knitrepo, weaverepo, pack_repo
 
70
from bzrlib.repofmt import knitrepo, knitpack_repo
61
71
 
62
72
 
63
73
class TestDefaultFormat(TestCase):
64
74
 
65
75
    def test_get_set_default_format(self):
66
76
        old_format = bzrdir.BzrDirFormat.get_default_format()
67
 
        # default is BzrDirFormat6
68
 
        self.failUnless(isinstance(old_format, bzrdir.BzrDirMetaFormat1))
69
 
        bzrdir.BzrDirFormat._set_default_format(SampleBzrDirFormat())
 
77
        # default is BzrDirMetaFormat1
 
78
        self.assertIsInstance(old_format, bzrdir.BzrDirMetaFormat1)
 
79
        controldir.ControlDirFormat._set_default_format(SampleBzrDirFormat())
70
80
        # creating a bzr dir should now create an instrumented dir.
71
81
        try:
72
82
            result = bzrdir.BzrDir.create('memory:///')
73
 
            self.failUnless(isinstance(result, SampleBzrDir))
 
83
            self.assertIsInstance(result, SampleBzrDir)
74
84
        finally:
75
 
            bzrdir.BzrDirFormat._set_default_format(old_format)
 
85
            controldir.ControlDirFormat._set_default_format(old_format)
76
86
        self.assertEqual(old_format, bzrdir.BzrDirFormat.get_default_format())
77
87
 
78
88
 
 
89
class DeprecatedBzrDirFormat(bzrdir.BzrDirFormat):
 
90
    """A deprecated bzr dir format."""
 
91
 
 
92
 
79
93
class TestFormatRegistry(TestCase):
80
94
 
81
95
    def make_format_registry(self):
82
 
        my_format_registry = bzrdir.BzrDirFormatRegistry()
83
 
        my_format_registry.register('weave', bzrdir.BzrDirFormat6,
84
 
            'Pre-0.8 format.  Slower and does not support checkouts or shared'
85
 
            ' repositories', deprecated=True)
86
 
        my_format_registry.register_lazy('lazy', 'bzrlib.bzrdir',
87
 
            'BzrDirFormat6', 'Format registered lazily', deprecated=True)
88
 
        my_format_registry.register_metadir('knit',
 
96
        my_format_registry = controldir.ControlDirFormatRegistry()
 
97
        my_format_registry.register('deprecated', DeprecatedBzrDirFormat,
 
98
            'Some format.  Slower and unawesome and deprecated.',
 
99
            deprecated=True)
 
100
        my_format_registry.register_lazy('lazy', 'bzrlib.tests.test_bzrdir',
 
101
            'DeprecatedBzrDirFormat', 'Format registered lazily',
 
102
            deprecated=True)
 
103
        bzrdir.register_metadir(my_format_registry, 'knit',
89
104
            'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
90
105
            'Format using knits',
91
106
            )
92
107
        my_format_registry.set_default('knit')
93
 
        my_format_registry.register_metadir(
 
108
        bzrdir.register_metadir(my_format_registry,
94
109
            'branch6',
95
110
            'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
96
111
            'Experimental successor to knit.  Use at your own risk.',
97
112
            branch_format='bzrlib.branch.BzrBranchFormat6',
98
113
            experimental=True)
99
 
        my_format_registry.register_metadir(
 
114
        bzrdir.register_metadir(my_format_registry,
100
115
            'hidden format',
101
116
            'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
102
117
            'Experimental successor to knit.  Use at your own risk.',
103
118
            branch_format='bzrlib.branch.BzrBranchFormat6', hidden=True)
104
 
        my_format_registry.register('hiddenweave', bzrdir.BzrDirFormat6,
105
 
            'Pre-0.8 format.  Slower and does not support checkouts or shared'
106
 
            ' repositories', hidden=True)
107
 
        my_format_registry.register_lazy('hiddenlazy', 'bzrlib.bzrdir',
108
 
            'BzrDirFormat6', 'Format registered lazily', deprecated=True,
109
 
            hidden=True)
 
119
        my_format_registry.register('hiddendeprecated', DeprecatedBzrDirFormat,
 
120
            'Old format.  Slower and does not support things. ', hidden=True)
 
121
        my_format_registry.register_lazy('hiddenlazy', 'bzrlib.tests.test_bzrdir',
 
122
            'DeprecatedBzrDirFormat', 'Format registered lazily',
 
123
            deprecated=True, hidden=True)
110
124
        return my_format_registry
111
125
 
112
126
    def test_format_registry(self):
113
127
        my_format_registry = self.make_format_registry()
114
128
        my_bzrdir = my_format_registry.make_bzrdir('lazy')
115
 
        self.assertIsInstance(my_bzrdir, bzrdir.BzrDirFormat6)
116
 
        my_bzrdir = my_format_registry.make_bzrdir('weave')
117
 
        self.assertIsInstance(my_bzrdir, bzrdir.BzrDirFormat6)
 
129
        self.assertIsInstance(my_bzrdir, DeprecatedBzrDirFormat)
 
130
        my_bzrdir = my_format_registry.make_bzrdir('deprecated')
 
131
        self.assertIsInstance(my_bzrdir, DeprecatedBzrDirFormat)
118
132
        my_bzrdir = my_format_registry.make_bzrdir('default')
119
133
        self.assertIsInstance(my_bzrdir.repository_format,
120
134
            knitrepo.RepositoryFormatKnit1)
133
147
                         my_format_registry.get_help('knit'))
134
148
        self.assertEqual('Format using knits',
135
149
                         my_format_registry.get_help('default'))
136
 
        self.assertEqual('Pre-0.8 format.  Slower and does not support'
137
 
                         ' checkouts or shared repositories',
138
 
                         my_format_registry.get_help('weave'))
 
150
        self.assertEqual('Some format.  Slower and unawesome and deprecated.',
 
151
                         my_format_registry.get_help('deprecated'))
139
152
 
140
153
    def test_help_topic(self):
141
154
        topics = help_topics.HelpTopicRegistry()
165
178
            self.assertIs(bzrdir.format_registry.get('dirstate-with-subtree'),
166
179
                          bzrdir.format_registry.get('default'))
167
180
            self.assertIs(
168
 
                repository.RepositoryFormat.get_default_format().__class__,
 
181
                repository.format_registry.get_default().__class__,
169
182
                knitrepo.RepositoryFormatKnit3)
170
183
        finally:
171
184
            bzrdir.format_registry.set_default_repository(old_default)
172
185
 
173
186
    def test_aliases(self):
174
 
        a_registry = bzrdir.BzrDirFormatRegistry()
175
 
        a_registry.register('weave', bzrdir.BzrDirFormat6,
176
 
            'Pre-0.8 format.  Slower and does not support checkouts or shared'
177
 
            ' repositories', deprecated=True)
178
 
        a_registry.register('weavealias', bzrdir.BzrDirFormat6,
179
 
            'Pre-0.8 format.  Slower and does not support checkouts or shared'
180
 
            ' repositories', deprecated=True, alias=True)
181
 
        self.assertEqual(frozenset(['weavealias']), a_registry.aliases())
 
187
        a_registry = controldir.ControlDirFormatRegistry()
 
188
        a_registry.register('deprecated', DeprecatedBzrDirFormat,
 
189
            'Old format.  Slower and does not support stuff',
 
190
            deprecated=True)
 
191
        a_registry.register('deprecatedalias', DeprecatedBzrDirFormat,
 
192
            'Old format.  Slower and does not support stuff',
 
193
            deprecated=True, alias=True)
 
194
        self.assertEqual(frozenset(['deprecatedalias']), a_registry.aliases())
182
195
 
183
196
 
184
197
class SampleBranch(bzrlib.branch.Branch):
206
219
        """See BzrDir.open_repository."""
207
220
        return SampleRepository(self)
208
221
 
209
 
    def create_branch(self):
 
222
    def create_branch(self, name=None):
210
223
        """See BzrDir.create_branch."""
 
224
        if name is not None:
 
225
            raise NoColocatedBranchSupport(self)
211
226
        return SampleBranch(self)
212
227
 
213
228
    def create_workingtree(self):
239
254
        return "opened branch."
240
255
 
241
256
 
 
257
class BzrDirFormatTest1(bzrdir.BzrDirMetaFormat1):
 
258
 
 
259
    @staticmethod
 
260
    def get_format_string():
 
261
        return "Test format 1"
 
262
 
 
263
 
 
264
class BzrDirFormatTest2(bzrdir.BzrDirMetaFormat1):
 
265
 
 
266
    @staticmethod
 
267
    def get_format_string():
 
268
        return "Test format 2"
 
269
 
 
270
 
242
271
class TestBzrDirFormat(TestCaseWithTransport):
243
272
    """Tests for the BzrDirFormat facility."""
244
273
 
245
274
    def test_find_format(self):
246
275
        # is the right format object found for a branch?
247
276
        # create a branch with a few known format objects.
248
 
        # this is not quite the same as
249
 
        t = get_transport(self.get_url())
 
277
        bzrdir.BzrProber.formats.register(BzrDirFormatTest1.get_format_string(),
 
278
            BzrDirFormatTest1())
 
279
        self.addCleanup(bzrdir.BzrProber.formats.remove,
 
280
            BzrDirFormatTest1.get_format_string())
 
281
        bzrdir.BzrProber.formats.register(BzrDirFormatTest2.get_format_string(),
 
282
            BzrDirFormatTest2())
 
283
        self.addCleanup(bzrdir.BzrProber.formats.remove,
 
284
            BzrDirFormatTest2.get_format_string())
 
285
        t = self.get_transport()
250
286
        self.build_tree(["foo/", "bar/"], transport=t)
251
287
        def check_format(format, url):
252
288
            format.initialize(url)
253
 
            t = get_transport(url)
 
289
            t = _mod_transport.get_transport_from_path(url)
254
290
            found_format = bzrdir.BzrDirFormat.find_format(t)
255
 
            self.failUnless(isinstance(found_format, format.__class__))
256
 
        check_format(bzrdir.BzrDirFormat5(), "foo")
257
 
        check_format(bzrdir.BzrDirFormat6(), "bar")
 
291
            self.assertIsInstance(found_format, format.__class__)
 
292
        check_format(BzrDirFormatTest1(), "foo")
 
293
        check_format(BzrDirFormatTest2(), "bar")
258
294
 
259
295
    def test_find_format_nothing_there(self):
260
296
        self.assertRaises(NotBranchError,
261
297
                          bzrdir.BzrDirFormat.find_format,
262
 
                          get_transport('.'))
 
298
                          _mod_transport.get_transport_from_path('.'))
263
299
 
264
300
    def test_find_format_unknown_format(self):
265
 
        t = get_transport(self.get_url())
 
301
        t = self.get_transport()
266
302
        t.mkdir('.bzr')
267
303
        t.put_bytes('.bzr/branch-format', '')
268
304
        self.assertRaises(UnknownFormatError,
269
305
                          bzrdir.BzrDirFormat.find_format,
270
 
                          get_transport('.'))
 
306
                          _mod_transport.get_transport_from_path('.'))
271
307
 
272
308
    def test_register_unregister_format(self):
273
309
        format = SampleBzrDirFormat()
275
311
        # make a bzrdir
276
312
        format.initialize(url)
277
313
        # register a format for it.
278
 
        bzrdir.BzrDirFormat.register_format(format)
 
314
        bzrdir.BzrProber.formats.register(format.get_format_string(), format)
279
315
        # which bzrdir.Open will refuse (not supported)
280
316
        self.assertRaises(UnsupportedFormatError, bzrdir.BzrDir.open, url)
281
317
        # which bzrdir.open_containing will refuse (not supported)
282
318
        self.assertRaises(UnsupportedFormatError, bzrdir.BzrDir.open_containing, url)
283
319
        # but open_downlevel will work
284
 
        t = get_transport(url)
 
320
        t = _mod_transport.get_transport_from_url(url)
285
321
        self.assertEqual(format.open(t), bzrdir.BzrDir.open_unsupported(url))
286
322
        # unregister the format
287
 
        bzrdir.BzrDirFormat.unregister_format(format)
 
323
        bzrdir.BzrProber.formats.remove(format.get_format_string())
288
324
        # now open_downlevel should fail too.
289
325
        self.assertRaises(UnknownFormatError, bzrdir.BzrDir.open_unsupported, url)
290
326
 
467
503
    def test_default_stacking_with_stackable_branch_unstackable_repo(self):
468
504
        # Make stackable source branch with an unstackable repo format.
469
505
        source_bzrdir = self.make_bzrdir('source')
470
 
        pack_repo.RepositoryFormatKnitPack1().initialize(source_bzrdir)
471
 
        source_branch = bzrlib.branch.BzrBranchFormat7().initialize(source_bzrdir)
 
506
        knitpack_repo.RepositoryFormatKnitPack1().initialize(source_bzrdir)
 
507
        source_branch = bzrlib.branch.BzrBranchFormat7().initialize(
 
508
            source_bzrdir)
472
509
        # Make a directory with a default stacking policy
473
510
        parent_bzrdir = self.make_bzrdir('parent')
474
511
        stacked_on = self.make_branch('parent/stacked-on', format='pack-0.92')
476
513
        # Clone source into directory
477
514
        target = source_bzrdir.clone(self.get_url('parent/target'))
478
515
 
 
516
    def test_format_initialize_on_transport_ex_stacked_on(self):
 
517
        # trunk is a stackable format.  Note that its in the same server area
 
518
        # which is what launchpad does, but not sufficient to exercise the
 
519
        # general case.
 
520
        trunk = self.make_branch('trunk', format='1.9')
 
521
        t = self.get_transport('stacked')
 
522
        old_fmt = bzrdir.format_registry.make_bzrdir('pack-0.92')
 
523
        repo_name = old_fmt.repository_format.network_name()
 
524
        # Should end up with a 1.9 format (stackable)
 
525
        repo, control, require_stacking, repo_policy = \
 
526
            old_fmt.initialize_on_transport_ex(t,
 
527
                    repo_format_name=repo_name, stacked_on='../trunk',
 
528
                    stack_on_pwd=t.base)
 
529
        if repo is not None:
 
530
            # Repositories are open write-locked
 
531
            self.assertTrue(repo.is_write_locked())
 
532
            self.addCleanup(repo.unlock)
 
533
        else:
 
534
            repo = control.open_repository()
 
535
        self.assertIsInstance(control, bzrdir.BzrDir)
 
536
        opened = bzrdir.BzrDir.open(t.base)
 
537
        if not isinstance(old_fmt, remote.RemoteBzrDirFormat):
 
538
            self.assertEqual(control._format.network_name(),
 
539
                old_fmt.network_name())
 
540
            self.assertEqual(control._format.network_name(),
 
541
                opened._format.network_name())
 
542
        self.assertEqual(control.__class__, opened.__class__)
 
543
        self.assertLength(1, repo._fallback_repositories)
 
544
 
479
545
    def test_sprout_obeys_stacking_policy(self):
480
546
        child_branch, new_child_transport = self.prepare_default_stacking()
481
547
        new_child = child_branch.bzrdir.sprout(new_child_transport.base)
672
738
        self.assertEqual(relpath, 'baz')
673
739
 
674
740
    def test_open_containing_from_transport(self):
675
 
        self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing_from_transport,
676
 
                          get_transport(self.get_readonly_url('')))
677
 
        self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing_from_transport,
678
 
                          get_transport(self.get_readonly_url('g/p/q')))
 
741
        self.assertRaises(NotBranchError,
 
742
            bzrdir.BzrDir.open_containing_from_transport,
 
743
            _mod_transport.get_transport_from_url(self.get_readonly_url('')))
 
744
        self.assertRaises(NotBranchError,
 
745
            bzrdir.BzrDir.open_containing_from_transport,
 
746
            _mod_transport.get_transport_from_url(
 
747
                self.get_readonly_url('g/p/q')))
679
748
        control = bzrdir.BzrDir.create(self.get_url())
680
749
        branch, relpath = bzrdir.BzrDir.open_containing_from_transport(
681
 
            get_transport(self.get_readonly_url('')))
 
750
            _mod_transport.get_transport_from_url(
 
751
                self.get_readonly_url('')))
682
752
        self.assertEqual('', relpath)
683
753
        branch, relpath = bzrdir.BzrDir.open_containing_from_transport(
684
 
            get_transport(self.get_readonly_url('g/p/q')))
 
754
            _mod_transport.get_transport_from_url(
 
755
                self.get_readonly_url('g/p/q')))
685
756
        self.assertEqual('g/p/q', relpath)
686
757
 
687
758
    def test_open_containing_tree_or_branch(self):
731
802
        # transport pointing at bzrdir should give a bzrdir with root transport
732
803
        # set to the given transport
733
804
        control = bzrdir.BzrDir.create(self.get_url())
734
 
        transport = get_transport(self.get_url())
735
 
        opened_bzrdir = bzrdir.BzrDir.open_from_transport(transport)
736
 
        self.assertEqual(transport.base, opened_bzrdir.root_transport.base)
 
805
        t = self.get_transport()
 
806
        opened_bzrdir = bzrdir.BzrDir.open_from_transport(t)
 
807
        self.assertEqual(t.base, opened_bzrdir.root_transport.base)
737
808
        self.assertIsInstance(opened_bzrdir, bzrdir.BzrDir)
738
809
 
739
810
    def test_open_from_transport_no_bzrdir(self):
740
 
        transport = get_transport(self.get_url())
741
 
        self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport,
742
 
                          transport)
 
811
        t = self.get_transport()
 
812
        self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport, t)
743
813
 
744
814
    def test_open_from_transport_bzrdir_in_parent(self):
745
815
        control = bzrdir.BzrDir.create(self.get_url())
746
 
        transport = get_transport(self.get_url())
747
 
        transport.mkdir('subdir')
748
 
        transport = transport.clone('subdir')
749
 
        self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport,
750
 
                          transport)
 
816
        t = self.get_transport()
 
817
        t.mkdir('subdir')
 
818
        t = t.clone('subdir')
 
819
        self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport, t)
751
820
 
752
821
    def test_sprout_recursive(self):
753
822
        tree = self.make_branch_and_tree('tree1',
762
831
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
763
832
        tree2.lock_read()
764
833
        self.addCleanup(tree2.unlock)
765
 
        self.failUnlessExists('tree2/subtree/file')
 
834
        self.assertPathExists('tree2/subtree/file')
766
835
        self.assertEqual('tree-reference', tree2.kind('subtree-root'))
767
836
 
768
837
    def test_cloning_metadir(self):
772
841
        branch = self.make_branch('branch', format='knit')
773
842
        format = branch.bzrdir.cloning_metadir()
774
843
        self.assertIsInstance(format.workingtree_format,
775
 
            workingtree.WorkingTreeFormat3)
 
844
            workingtree_4.WorkingTreeFormat6)
776
845
 
777
846
    def test_sprout_recursive_treeless(self):
778
847
        tree = self.make_branch_and_tree('tree1',
783
852
        self.build_tree(['tree1/subtree/file'])
784
853
        sub_tree.add('file')
785
854
        tree.commit('Initial commit')
 
855
        # The following line force the orhaning to reveal bug #634470
 
856
        tree.branch.get_config().set_user_option(
 
857
            'bzr.transform.orphan_policy', 'move')
786
858
        tree.bzrdir.destroy_workingtree()
 
859
        # FIXME: subtree/.bzr is left here which allows the test to pass (or
 
860
        # fail :-( ) -- vila 20100909
787
861
        repo = self.make_repository('repo', shared=True,
788
862
            format='dirstate-with-subtree')
789
863
        repo.set_make_working_trees(False)
790
 
        tree.bzrdir.sprout('repo/tree2')
791
 
        self.failUnlessExists('repo/tree2/subtree')
792
 
        self.failIfExists('repo/tree2/subtree/file')
 
864
        # FIXME: we just deleted the workingtree and now we want to use it ????
 
865
        # At a minimum, we should use tree.branch below (but this fails too
 
866
        # currently) or stop calling this test 'treeless'. Specifically, I've
 
867
        # turn the line below into an assertRaises when 'subtree/.bzr' is
 
868
        # orphaned and sprout tries to access the branch there (which is left
 
869
        # by bzrdir.BzrDirMeta1.destroy_workingtree when it ignores the
 
870
        # [DeletingParent('Not deleting', u'subtree', None)] conflict). See bug
 
871
        # #634470.  -- vila 20100909
 
872
        self.assertRaises(errors.NotBranchError,
 
873
                          tree.bzrdir.sprout, 'repo/tree2')
 
874
#        self.assertPathExists('repo/tree2/subtree')
 
875
#        self.assertPathDoesNotExist('repo/tree2/subtree/file')
793
876
 
794
877
    def make_foo_bar_baz(self):
795
878
        foo = bzrdir.BzrDir.create_branch_convenience('foo').bzrdir
799
882
 
800
883
    def test_find_bzrdirs(self):
801
884
        foo, bar, baz = self.make_foo_bar_baz()
802
 
        transport = get_transport(self.get_url())
803
 
        self.assertEqualBzrdirs([baz, foo, bar],
804
 
                                bzrdir.BzrDir.find_bzrdirs(transport))
 
885
        t = self.get_transport()
 
886
        self.assertEqualBzrdirs([baz, foo, bar], bzrdir.BzrDir.find_bzrdirs(t))
 
887
 
 
888
    def make_fake_permission_denied_transport(self, transport, paths):
 
889
        """Create a transport that raises PermissionDenied for some paths."""
 
890
        def filter(path):
 
891
            if path in paths:
 
892
                raise errors.PermissionDenied(path)
 
893
            return path
 
894
        path_filter_server = pathfilter.PathFilteringServer(transport, filter)
 
895
        path_filter_server.start_server()
 
896
        self.addCleanup(path_filter_server.stop_server)
 
897
        path_filter_transport = pathfilter.PathFilteringTransport(
 
898
            path_filter_server, '.')
 
899
        return (path_filter_server, path_filter_transport)
 
900
 
 
901
    def assertBranchUrlsEndWith(self, expect_url_suffix, actual_bzrdirs):
 
902
        """Check that each branch url ends with the given suffix."""
 
903
        for actual_bzrdir in actual_bzrdirs:
 
904
            self.assertEndsWith(actual_bzrdir.user_url, expect_url_suffix)
 
905
 
 
906
    def test_find_bzrdirs_permission_denied(self):
 
907
        foo, bar, baz = self.make_foo_bar_baz()
 
908
        t = self.get_transport()
 
909
        path_filter_server, path_filter_transport = \
 
910
            self.make_fake_permission_denied_transport(t, ['foo'])
 
911
        # local transport
 
912
        self.assertBranchUrlsEndWith('/baz/',
 
913
            bzrdir.BzrDir.find_bzrdirs(path_filter_transport))
 
914
        # smart server
 
915
        smart_transport = self.make_smart_server('.',
 
916
            backing_server=path_filter_server)
 
917
        self.assertBranchUrlsEndWith('/baz/',
 
918
            bzrdir.BzrDir.find_bzrdirs(smart_transport))
805
919
 
806
920
    def test_find_bzrdirs_list_current(self):
807
921
        def list_current(transport):
808
922
            return [s for s in transport.list_dir('') if s != 'baz']
809
923
 
810
924
        foo, bar, baz = self.make_foo_bar_baz()
811
 
        transport = get_transport(self.get_url())
812
 
        self.assertEqualBzrdirs([foo, bar],
813
 
                                bzrdir.BzrDir.find_bzrdirs(transport,
814
 
                                    list_current=list_current))
815
 
 
 
925
        t = self.get_transport()
 
926
        self.assertEqualBzrdirs(
 
927
            [foo, bar],
 
928
            bzrdir.BzrDir.find_bzrdirs(t, list_current=list_current))
816
929
 
817
930
    def test_find_bzrdirs_evaluate(self):
818
931
        def evaluate(bzrdir):
819
932
            try:
820
933
                repo = bzrdir.open_repository()
821
 
            except NoRepositoryPresent:
 
934
            except errors.NoRepositoryPresent:
822
935
                return True, bzrdir.root_transport.base
823
936
            else:
824
937
                return False, bzrdir.root_transport.base
825
938
 
826
939
        foo, bar, baz = self.make_foo_bar_baz()
827
 
        transport = get_transport(self.get_url())
 
940
        t = self.get_transport()
828
941
        self.assertEqual([baz.root_transport.base, foo.root_transport.base],
829
 
                         list(bzrdir.BzrDir.find_bzrdirs(transport,
830
 
                                                         evaluate=evaluate)))
 
942
                         list(bzrdir.BzrDir.find_bzrdirs(t, evaluate=evaluate)))
831
943
 
832
944
    def assertEqualBzrdirs(self, first, second):
833
945
        first = list(first)
840
952
        root = self.make_repository('', shared=True)
841
953
        foo, bar, baz = self.make_foo_bar_baz()
842
954
        qux = self.make_bzrdir('foo/qux')
843
 
        transport = get_transport(self.get_url())
844
 
        branches = bzrdir.BzrDir.find_branches(transport)
 
955
        t = self.get_transport()
 
956
        branches = bzrdir.BzrDir.find_branches(t)
845
957
        self.assertEqual(baz.root_transport.base, branches[0].base)
846
958
        self.assertEqual(foo.root_transport.base, branches[1].base)
847
959
        self.assertEqual(bar.root_transport.base, branches[2].base)
848
960
 
849
961
        # ensure this works without a top-level repo
850
 
        branches = bzrdir.BzrDir.find_branches(transport.clone('foo'))
 
962
        branches = bzrdir.BzrDir.find_branches(t.clone('foo'))
851
963
        self.assertEqual(foo.root_transport.base, branches[0].base)
852
964
        self.assertEqual(bar.root_transport.base, branches[1].base)
853
965
 
854
966
 
 
967
class TestMissingRepoBranchesSkipped(TestCaseWithMemoryTransport):
 
968
 
 
969
    def test_find_bzrdirs_missing_repo(self):
 
970
        t = self.get_transport()
 
971
        arepo = self.make_repository('arepo', shared=True)
 
972
        abranch_url = arepo.user_url + '/abranch'
 
973
        abranch = bzrdir.BzrDir.create(abranch_url).create_branch()
 
974
        t.delete_tree('arepo/.bzr')
 
975
        self.assertRaises(errors.NoRepositoryPresent,
 
976
            branch.Branch.open, abranch_url)
 
977
        self.make_branch('baz')
 
978
        for actual_bzrdir in bzrdir.BzrDir.find_branches(t):
 
979
            self.assertEndsWith(actual_bzrdir.user_url, '/baz/')
 
980
 
 
981
 
855
982
class TestMeta1DirFormat(TestCaseWithTransport):
856
983
    """Tests specific to the meta1 dir format."""
857
984
 
864
991
                         dir.get_branch_transport(bzrlib.branch.BzrBranchFormat5()).base)
865
992
        repository_base = t.clone('repository').base
866
993
        self.assertEqual(repository_base, dir.get_repository_transport(None).base)
 
994
        repository_format = repository.format_registry.get_default()
867
995
        self.assertEqual(repository_base,
868
 
                         dir.get_repository_transport(weaverepo.RepositoryFormat7()).base)
 
996
                         dir.get_repository_transport(repository_format).base)
869
997
        checkout_base = t.clone('checkout').base
870
998
        self.assertEqual(checkout_base, dir.get_workingtree_transport(None).base)
871
999
        self.assertEqual(checkout_base,
872
 
                         dir.get_workingtree_transport(workingtree.WorkingTreeFormat3()).base)
 
1000
                         dir.get_workingtree_transport(workingtree_3.WorkingTreeFormat3()).base)
873
1001
 
874
1002
    def test_meta1dir_uses_lockdir(self):
875
1003
        """Meta1 format uses a LockDir to guard the whole directory, not a file."""
917
1045
        self.assertEqual(2, rpc_count)
918
1046
 
919
1047
 
920
 
class TestFormat5(TestCaseWithTransport):
921
 
    """Tests specific to the version 5 bzrdir format."""
922
 
 
923
 
    def test_same_lockfiles_between_tree_repo_branch(self):
924
 
        # this checks that only a single lockfiles instance is created
925
 
        # for format 5 objects
926
 
        dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
927
 
        def check_dir_components_use_same_lock(dir):
928
 
            ctrl_1 = dir.open_repository().control_files
929
 
            ctrl_2 = dir.open_branch().control_files
930
 
            ctrl_3 = dir.open_workingtree()._control_files
931
 
            self.assertTrue(ctrl_1 is ctrl_2)
932
 
            self.assertTrue(ctrl_2 is ctrl_3)
933
 
        check_dir_components_use_same_lock(dir)
934
 
        # and if we open it normally.
935
 
        dir = bzrdir.BzrDir.open(self.get_url())
936
 
        check_dir_components_use_same_lock(dir)
937
 
 
938
 
    def test_can_convert(self):
939
 
        # format 5 dirs are convertable
940
 
        dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
941
 
        self.assertTrue(dir.can_convert_format())
942
 
 
943
 
    def test_needs_conversion(self):
944
 
        # format 5 dirs need a conversion if they are not the default,
945
 
        # and they aren't
946
 
        dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
947
 
        # don't need to convert it to itself
948
 
        self.assertFalse(dir.needs_format_conversion(bzrdir.BzrDirFormat5()))
949
 
        # do need to convert it to the current default
950
 
        self.assertTrue(dir.needs_format_conversion(
951
 
            bzrdir.BzrDirFormat.get_default_format()))
952
 
 
953
 
 
954
 
class TestFormat6(TestCaseWithTransport):
955
 
    """Tests specific to the version 6 bzrdir format."""
956
 
 
957
 
    def test_same_lockfiles_between_tree_repo_branch(self):
958
 
        # this checks that only a single lockfiles instance is created
959
 
        # for format 6 objects
960
 
        dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
961
 
        def check_dir_components_use_same_lock(dir):
962
 
            ctrl_1 = dir.open_repository().control_files
963
 
            ctrl_2 = dir.open_branch().control_files
964
 
            ctrl_3 = dir.open_workingtree()._control_files
965
 
            self.assertTrue(ctrl_1 is ctrl_2)
966
 
            self.assertTrue(ctrl_2 is ctrl_3)
967
 
        check_dir_components_use_same_lock(dir)
968
 
        # and if we open it normally.
969
 
        dir = bzrdir.BzrDir.open(self.get_url())
970
 
        check_dir_components_use_same_lock(dir)
971
 
 
972
 
    def test_can_convert(self):
973
 
        # format 6 dirs are convertable
974
 
        dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
975
 
        self.assertTrue(dir.can_convert_format())
976
 
 
977
 
    def test_needs_conversion(self):
978
 
        # format 6 dirs need an conversion if they are not the default.
979
 
        dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
980
 
        self.assertTrue(dir.needs_format_conversion(
981
 
            bzrdir.BzrDirFormat.get_default_format()))
982
 
 
983
 
 
984
 
class NotBzrDir(bzrlib.bzrdir.BzrDir):
985
 
    """A non .bzr based control directory."""
986
 
 
987
 
    def __init__(self, transport, format):
988
 
        self._format = format
989
 
        self.root_transport = transport
990
 
        self.transport = transport.clone('.not')
991
 
 
992
 
 
993
 
class NotBzrDirFormat(bzrlib.bzrdir.BzrDirFormat):
994
 
    """A test class representing any non-.bzr based disk format."""
995
 
 
996
 
    def initialize_on_transport(self, transport):
997
 
        """Initialize a new .not dir in the base directory of a Transport."""
998
 
        transport.mkdir('.not')
999
 
        return self.open(transport)
1000
 
 
1001
 
    def open(self, transport):
1002
 
        """Open this directory."""
1003
 
        return NotBzrDir(transport, self)
1004
 
 
1005
 
    @classmethod
1006
 
    def _known_formats(self):
1007
 
        return set([NotBzrDirFormat()])
1008
 
 
1009
 
    @classmethod
1010
 
    def probe_transport(self, transport):
1011
 
        """Our format is present if the transport ends in '.not/'."""
1012
 
        if transport.has('.not'):
1013
 
            return NotBzrDirFormat()
1014
 
 
1015
 
 
1016
 
class TestNotBzrDir(TestCaseWithTransport):
1017
 
    """Tests for using the bzrdir api with a non .bzr based disk format.
1018
 
 
1019
 
    If/when one of these is in the core, we can let the implementation tests
1020
 
    verify this works.
1021
 
    """
1022
 
 
1023
 
    def test_create_and_find_format(self):
1024
 
        # create a .notbzr dir
1025
 
        format = NotBzrDirFormat()
1026
 
        dir = format.initialize(self.get_url())
1027
 
        self.assertIsInstance(dir, NotBzrDir)
1028
 
        # now probe for it.
1029
 
        bzrlib.bzrdir.BzrDirFormat.register_control_format(format)
1030
 
        try:
1031
 
            found = bzrlib.bzrdir.BzrDirFormat.find_format(
1032
 
                get_transport(self.get_url()))
1033
 
            self.assertIsInstance(found, NotBzrDirFormat)
1034
 
        finally:
1035
 
            bzrlib.bzrdir.BzrDirFormat.unregister_control_format(format)
1036
 
 
1037
 
    def test_included_in_known_formats(self):
1038
 
        bzrlib.bzrdir.BzrDirFormat.register_control_format(NotBzrDirFormat)
1039
 
        try:
1040
 
            formats = bzrlib.bzrdir.BzrDirFormat.known_formats()
1041
 
            for format in formats:
1042
 
                if isinstance(format, NotBzrDirFormat):
1043
 
                    return
1044
 
            self.fail("No NotBzrDirFormat in %s" % formats)
1045
 
        finally:
1046
 
            bzrlib.bzrdir.BzrDirFormat.unregister_control_format(NotBzrDirFormat)
1047
 
 
1048
 
 
1049
1048
class NonLocalTests(TestCaseWithTransport):
1050
1049
    """Tests for bzrdir static behaviour on non local paths."""
1051
1050
 
1070
1069
            self.get_url('foo'),
1071
1070
            force_new_tree=True,
1072
1071
            format=format)
1073
 
        t = get_transport(self.get_url('.'))
 
1072
        t = self.get_transport()
1074
1073
        self.assertFalse(t.has('foo'))
1075
1074
 
1076
1075
    def test_clone(self):
1092
1091
        my_bzrdir = bzrdir.BzrDir.open(self.get_url('branch-knit2'))
1093
1092
        checkout_format = my_bzrdir.checkout_metadir()
1094
1093
        self.assertIsInstance(checkout_format.workingtree_format,
1095
 
                              workingtree.WorkingTreeFormat3)
 
1094
                              workingtree_4.WorkingTreeFormat4)
1096
1095
 
1097
1096
 
1098
1097
class TestHTTPRedirections(object):
1107
1106
    """
1108
1107
 
1109
1108
    def create_transport_readonly_server(self):
 
1109
        # We don't set the http protocol version, relying on the default
1110
1110
        return http_utils.HTTPServerRedirecting()
1111
1111
 
1112
1112
    def create_transport_secondary_server(self):
 
1113
        # We don't set the http protocol version, relying on the default
1113
1114
        return http_utils.HTTPServerRedirecting()
1114
1115
 
1115
1116
    def setUp(self):
1240
1241
 
1241
1242
    def __init__(self, *args, **kwargs):
1242
1243
        super(_TestBzrDir, self).__init__(*args, **kwargs)
1243
 
        self.test_branch = _TestBranch()
 
1244
        self.test_branch = _TestBranch(self.transport)
1244
1245
        self.test_branch.repository = self.create_repository()
1245
1246
 
1246
 
    def open_branch(self, unsupported=False):
 
1247
    def open_branch(self, unsupported=False, possible_transports=None):
1247
1248
        return self.test_branch
1248
1249
 
1249
1250
    def cloning_metadir(self, require_stacking=False):
1257
1258
class _TestBranch(bzrlib.branch.Branch):
1258
1259
    """Test Branch implementation for TestBzrDirSprout."""
1259
1260
 
1260
 
    def __init__(self, *args, **kwargs):
 
1261
    def __init__(self, transport, *args, **kwargs):
1261
1262
        self._format = _TestBranchFormat()
 
1263
        self._transport = transport
 
1264
        self.base = transport.base
1262
1265
        super(_TestBranch, self).__init__(*args, **kwargs)
1263
1266
        self.calls = []
1264
1267
        self._parent = None
1265
1268
 
1266
1269
    def sprout(self, *args, **kwargs):
1267
1270
        self.calls.append('sprout')
1268
 
        return _TestBranch()
 
1271
        return _TestBranch(self._transport)
1269
1272
 
1270
1273
    def copy_content_into(self, destination, revision_id=None):
1271
1274
        self.calls.append('copy_content_into')
1272
1275
 
 
1276
    def last_revision(self):
 
1277
        return _mod_revision.NULL_REVISION
 
1278
 
1273
1279
    def get_parent(self):
1274
1280
        return self._parent
1275
1281
 
 
1282
    def _get_config(self):
 
1283
        return config.TransportConfig(self._transport, 'branch.conf')
 
1284
 
1276
1285
    def set_parent(self, parent):
1277
1286
        self._parent = parent
1278
1287
 
 
1288
    def lock_read(self):
 
1289
        return lock.LogicalLockResult(self.unlock)
 
1290
 
 
1291
    def unlock(self):
 
1292
        return
 
1293
 
1279
1294
 
1280
1295
class TestBzrDirSprout(TestCaseWithMemoryTransport):
1281
1296
 
1335
1350
        url = transport.base
1336
1351
        err = self.assertRaises(errors.BzrError, bzrdir.BzrDir.open, url)
1337
1352
        self.assertEqual('fail', err._preformatted_string)
 
1353
 
 
1354
    def test_post_repo_init(self):
 
1355
        from bzrlib.controldir import RepoInitHookParams
 
1356
        calls = []
 
1357
        bzrdir.BzrDir.hooks.install_named_hook('post_repo_init',
 
1358
            calls.append, None)
 
1359
        self.make_repository('foo')
 
1360
        self.assertLength(1, calls)
 
1361
        params = calls[0]
 
1362
        self.assertIsInstance(params, RepoInitHookParams)
 
1363
        self.assertTrue(hasattr(params, 'bzrdir'))
 
1364
        self.assertTrue(hasattr(params, 'repository'))
 
1365
 
 
1366
    def test_post_repo_init_hook_repr(self):
 
1367
        param_reprs = []
 
1368
        bzrdir.BzrDir.hooks.install_named_hook('post_repo_init',
 
1369
            lambda params: param_reprs.append(repr(params)), None)
 
1370
        self.make_repository('foo')
 
1371
        self.assertLength(1, param_reprs)
 
1372
        param_repr = param_reprs[0]
 
1373
        self.assertStartsWith(param_repr, '<RepoInitHookParams for ')
 
1374
 
 
1375
 
 
1376
class TestGenerateBackupName(TestCaseWithMemoryTransport):
 
1377
    # FIXME: This may need to be unified with test_osutils.TestBackupNames or
 
1378
    # moved to per_bzrdir or per_transport for better coverage ?
 
1379
    # -- vila 20100909
 
1380
 
 
1381
    def setUp(self):
 
1382
        super(TestGenerateBackupName, self).setUp()
 
1383
        self._transport = self.get_transport()
 
1384
        bzrdir.BzrDir.create(self.get_url(),
 
1385
            possible_transports=[self._transport])
 
1386
        self._bzrdir = bzrdir.BzrDir.open_from_transport(self._transport)
 
1387
 
 
1388
    def test_deprecated_generate_backup_name(self):
 
1389
        res = self.applyDeprecated(
 
1390
                symbol_versioning.deprecated_in((2, 3, 0)),
 
1391
                self._bzrdir.generate_backup_name, 'whatever')
 
1392
 
 
1393
    def test_new(self):
 
1394
        self.assertEqual("a.~1~", self._bzrdir._available_backup_name("a"))
 
1395
 
 
1396
    def test_exiting(self):
 
1397
        self._transport.put_bytes("a.~1~", "some content")
 
1398
        self.assertEqual("a.~2~", self._bzrdir._available_backup_name("a"))
 
1399
 
 
1400
 
 
1401
class TestMeta1DirColoFormat(TestCaseWithTransport):
 
1402
    """Tests specific to the meta1 dir with colocated branches format."""
 
1403
 
 
1404
    def test_supports_colo(self):
 
1405
        format = bzrdir.BzrDirMetaFormat1Colo()
 
1406
        self.assertTrue(format.colocated_branches)
 
1407
 
 
1408
    def test_upgrade_from_2a(self):
 
1409
        tree = self.make_branch_and_tree('.', format='2a')
 
1410
        format = bzrdir.BzrDirMetaFormat1Colo()
 
1411
        self.assertTrue(tree.bzrdir.needs_format_conversion(format))
 
1412
        converter = tree.bzrdir._format.get_converter(format)
 
1413
        result = converter.convert(tree.bzrdir, None)
 
1414
        self.assertIsInstance(result._format, bzrdir.BzrDirMetaFormat1Colo)
 
1415
        self.assertFalse(result.needs_format_conversion(format))
 
1416
 
 
1417
    def test_downgrade_to_2a(self):
 
1418
        tree = self.make_branch_and_tree('.', format='development-colo')
 
1419
        format = bzrdir.BzrDirMetaFormat1()
 
1420
        self.assertTrue(tree.bzrdir.needs_format_conversion(format))
 
1421
        converter = tree.bzrdir._format.get_converter(format)
 
1422
        result = converter.convert(tree.bzrdir, None)
 
1423
        self.assertIsInstance(result._format, bzrdir.BzrDirMetaFormat1)
 
1424
        self.assertFalse(result.needs_format_conversion(format))
 
1425
 
 
1426
    def test_downgrade_to_2a_too_many_branches(self):
 
1427
        tree = self.make_branch_and_tree('.', format='development-colo')
 
1428
        tree.bzrdir.create_branch(name="another-colocated-branch")
 
1429
        converter = tree.bzrdir._format.get_converter(
 
1430
            bzrdir.BzrDirMetaFormat1())
 
1431
        self.assertRaises(errors.BzrError, converter.convert, tree.bzrdir,
 
1432
            None)
 
1433