/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_bzrdir.py

  • Committer: Ian Clatworthy
  • Date: 2008-12-15 04:33:37 UTC
  • mto: (3904.1.1 ianc-integration)
  • mto: This revision was merged to the branch mainline in revision 3905.
  • Revision ID: ian.clatworthy@canonical.com-20081215043337-76fij4vq83wiz7bk
include feedback from poolie

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
 
 
17
"""Tests for the BzrDir facility and any format specific tests.
 
18
 
 
19
For interface contract tests, see tests/bzr_dir_implementations.
 
20
"""
 
21
 
 
22
import os
 
23
import os.path
 
24
from StringIO import StringIO
 
25
import subprocess
 
26
import sys
 
27
 
 
28
from bzrlib import (
 
29
    bzrdir,
 
30
    errors,
 
31
    help_topics,
 
32
    repository,
 
33
    osutils,
 
34
    symbol_versioning,
 
35
    urlutils,
 
36
    win32utils,
 
37
    workingtree,
 
38
    )
 
39
import bzrlib.branch
 
40
from bzrlib.errors import (NotBranchError,
 
41
                           UnknownFormatError,
 
42
                           UnsupportedFormatError,
 
43
                           )
 
44
from bzrlib.tests import (
 
45
    TestCase,
 
46
    TestCaseWithMemoryTransport,
 
47
    TestCaseWithTransport,
 
48
    TestSkipped,
 
49
    test_sftp_transport
 
50
    )
 
51
from bzrlib.tests.http_server import HttpServer
 
52
from bzrlib.tests.http_utils import (
 
53
    TestCaseWithTwoWebservers,
 
54
    HTTPServerRedirecting,
 
55
    )
 
56
from bzrlib.tests.test_http import TestWithTransport_pycurl
 
57
from bzrlib.transport import get_transport
 
58
from bzrlib.transport.http._urllib import HttpTransport_urllib
 
59
from bzrlib.transport.memory import MemoryServer
 
60
from bzrlib.repofmt import knitrepo, weaverepo
 
61
 
 
62
 
 
63
class TestDefaultFormat(TestCase):
 
64
 
 
65
    def test_get_set_default_format(self):
 
66
        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())
 
70
        # creating a bzr dir should now create an instrumented dir.
 
71
        try:
 
72
            result = bzrdir.BzrDir.create('memory:///')
 
73
            self.failUnless(isinstance(result, SampleBzrDir))
 
74
        finally:
 
75
            bzrdir.BzrDirFormat._set_default_format(old_format)
 
76
        self.assertEqual(old_format, bzrdir.BzrDirFormat.get_default_format())
 
77
 
 
78
 
 
79
class TestFormatRegistry(TestCase):
 
80
 
 
81
    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',
 
89
            'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
 
90
            'Format using knits',
 
91
            )
 
92
        my_format_registry.set_default('knit')
 
93
        my_format_registry.register_metadir(
 
94
            'branch6',
 
95
            'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
 
96
            'Experimental successor to knit.  Use at your own risk.',
 
97
            branch_format='bzrlib.branch.BzrBranchFormat6',
 
98
            experimental=True)
 
99
        my_format_registry.register_metadir(
 
100
            'hidden format',
 
101
            'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
 
102
            'Experimental successor to knit.  Use at your own risk.',
 
103
            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)
 
110
        return my_format_registry
 
111
 
 
112
    def test_format_registry(self):
 
113
        my_format_registry = self.make_format_registry()
 
114
        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)
 
118
        my_bzrdir = my_format_registry.make_bzrdir('default')
 
119
        self.assertIsInstance(my_bzrdir.repository_format, 
 
120
            knitrepo.RepositoryFormatKnit1)
 
121
        my_bzrdir = my_format_registry.make_bzrdir('knit')
 
122
        self.assertIsInstance(my_bzrdir.repository_format, 
 
123
            knitrepo.RepositoryFormatKnit1)
 
124
        my_bzrdir = my_format_registry.make_bzrdir('branch6')
 
125
        self.assertIsInstance(my_bzrdir.get_branch_format(),
 
126
                              bzrlib.branch.BzrBranchFormat6)
 
127
 
 
128
    def test_get_help(self):
 
129
        my_format_registry = self.make_format_registry()
 
130
        self.assertEqual('Format registered lazily',
 
131
                         my_format_registry.get_help('lazy'))
 
132
        self.assertEqual('Format using knits', 
 
133
                         my_format_registry.get_help('knit'))
 
134
        self.assertEqual('Format using knits', 
 
135
                         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'))
 
139
        
 
140
    def test_help_topic(self):
 
141
        topics = help_topics.HelpTopicRegistry()
 
142
        registry = self.make_format_registry()
 
143
        topics.register('current-formats', registry.help_topic, 
 
144
                        'Current formats')
 
145
        topics.register('other-formats', registry.help_topic, 
 
146
                        'Other formats')
 
147
        new = topics.get_detail('current-formats')
 
148
        rest = topics.get_detail('other-formats')
 
149
        experimental, deprecated = rest.split('Deprecated formats')
 
150
        self.assertContainsRe(new, 'bzr help formats')
 
151
        self.assertContainsRe(new, 
 
152
                ':knit:\n    \(native\) \(default\) Format using knits\n')
 
153
        self.assertContainsRe(experimental, 
 
154
                ':branch6:\n    \(native\) Experimental successor to knit')
 
155
        self.assertContainsRe(deprecated, 
 
156
                ':lazy:\n    \(native\) Format registered lazily\n')
 
157
        self.assertNotContainsRe(new, 'hidden')
 
158
 
 
159
    def test_set_default_repository(self):
 
160
        default_factory = bzrdir.format_registry.get('default')
 
161
        old_default = [k for k, v in bzrdir.format_registry.iteritems()
 
162
                       if v == default_factory and k != 'default'][0]
 
163
        bzrdir.format_registry.set_default_repository('dirstate-with-subtree')
 
164
        try:
 
165
            self.assertIs(bzrdir.format_registry.get('dirstate-with-subtree'),
 
166
                          bzrdir.format_registry.get('default'))
 
167
            self.assertIs(
 
168
                repository.RepositoryFormat.get_default_format().__class__,
 
169
                knitrepo.RepositoryFormatKnit3)
 
170
        finally:
 
171
            bzrdir.format_registry.set_default_repository(old_default)
 
172
 
 
173
    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())
 
182
    
 
183
 
 
184
class SampleBranch(bzrlib.branch.Branch):
 
185
    """A dummy branch for guess what, dummy use."""
 
186
 
 
187
    def __init__(self, dir):
 
188
        self.bzrdir = dir
 
189
 
 
190
 
 
191
class SampleBzrDir(bzrdir.BzrDir):
 
192
    """A sample BzrDir implementation to allow testing static methods."""
 
193
 
 
194
    def create_repository(self, shared=False):
 
195
        """See BzrDir.create_repository."""
 
196
        return "A repository"
 
197
 
 
198
    def open_repository(self):
 
199
        """See BzrDir.open_repository."""
 
200
        return "A repository"
 
201
 
 
202
    def create_branch(self):
 
203
        """See BzrDir.create_branch."""
 
204
        return SampleBranch(self)
 
205
 
 
206
    def create_workingtree(self):
 
207
        """See BzrDir.create_workingtree."""
 
208
        return "A tree"
 
209
 
 
210
 
 
211
class SampleBzrDirFormat(bzrdir.BzrDirFormat):
 
212
    """A sample format
 
213
 
 
214
    this format is initializable, unsupported to aid in testing the 
 
215
    open and open_downlevel routines.
 
216
    """
 
217
 
 
218
    def get_format_string(self):
 
219
        """See BzrDirFormat.get_format_string()."""
 
220
        return "Sample .bzr dir format."
 
221
 
 
222
    def initialize_on_transport(self, t):
 
223
        """Create a bzr dir."""
 
224
        t.mkdir('.bzr')
 
225
        t.put_bytes('.bzr/branch-format', self.get_format_string())
 
226
        return SampleBzrDir(t, self)
 
227
 
 
228
    def is_supported(self):
 
229
        return False
 
230
 
 
231
    def open(self, transport, _found=None):
 
232
        return "opened branch."
 
233
 
 
234
 
 
235
class TestBzrDirFormat(TestCaseWithTransport):
 
236
    """Tests for the BzrDirFormat facility."""
 
237
 
 
238
    def test_find_format(self):
 
239
        # is the right format object found for a branch?
 
240
        # create a branch with a few known format objects.
 
241
        # this is not quite the same as 
 
242
        t = get_transport(self.get_url())
 
243
        self.build_tree(["foo/", "bar/"], transport=t)
 
244
        def check_format(format, url):
 
245
            format.initialize(url)
 
246
            t = get_transport(url)
 
247
            found_format = bzrdir.BzrDirFormat.find_format(t)
 
248
            self.failUnless(isinstance(found_format, format.__class__))
 
249
        check_format(bzrdir.BzrDirFormat5(), "foo")
 
250
        check_format(bzrdir.BzrDirFormat6(), "bar")
 
251
        
 
252
    def test_find_format_nothing_there(self):
 
253
        self.assertRaises(NotBranchError,
 
254
                          bzrdir.BzrDirFormat.find_format,
 
255
                          get_transport('.'))
 
256
 
 
257
    def test_find_format_unknown_format(self):
 
258
        t = get_transport(self.get_url())
 
259
        t.mkdir('.bzr')
 
260
        t.put_bytes('.bzr/branch-format', '')
 
261
        self.assertRaises(UnknownFormatError,
 
262
                          bzrdir.BzrDirFormat.find_format,
 
263
                          get_transport('.'))
 
264
 
 
265
    def test_register_unregister_format(self):
 
266
        format = SampleBzrDirFormat()
 
267
        url = self.get_url()
 
268
        # make a bzrdir
 
269
        format.initialize(url)
 
270
        # register a format for it.
 
271
        bzrdir.BzrDirFormat.register_format(format)
 
272
        # which bzrdir.Open will refuse (not supported)
 
273
        self.assertRaises(UnsupportedFormatError, bzrdir.BzrDir.open, url)
 
274
        # which bzrdir.open_containing will refuse (not supported)
 
275
        self.assertRaises(UnsupportedFormatError, bzrdir.BzrDir.open_containing, url)
 
276
        # but open_downlevel will work
 
277
        t = get_transport(url)
 
278
        self.assertEqual(format.open(t), bzrdir.BzrDir.open_unsupported(url))
 
279
        # unregister the format
 
280
        bzrdir.BzrDirFormat.unregister_format(format)
 
281
        # now open_downlevel should fail too.
 
282
        self.assertRaises(UnknownFormatError, bzrdir.BzrDir.open_unsupported, url)
 
283
 
 
284
    def test_create_branch_and_repo_uses_default(self):
 
285
        format = SampleBzrDirFormat()
 
286
        branch = bzrdir.BzrDir.create_branch_and_repo(self.get_url(),
 
287
                                                      format=format)
 
288
        self.assertTrue(isinstance(branch, SampleBranch))
 
289
 
 
290
    def test_create_branch_and_repo_under_shared(self):
 
291
        # creating a branch and repo in a shared repo uses the
 
292
        # shared repository
 
293
        format = bzrdir.format_registry.make_bzrdir('knit')
 
294
        self.make_repository('.', shared=True, format=format)
 
295
        branch = bzrdir.BzrDir.create_branch_and_repo(
 
296
            self.get_url('child'), format=format)
 
297
        self.assertRaises(errors.NoRepositoryPresent,
 
298
                          branch.bzrdir.open_repository)
 
299
 
 
300
    def test_create_branch_and_repo_under_shared_force_new(self):
 
301
        # creating a branch and repo in a shared repo can be forced to 
 
302
        # make a new repo
 
303
        format = bzrdir.format_registry.make_bzrdir('knit')
 
304
        self.make_repository('.', shared=True, format=format)
 
305
        branch = bzrdir.BzrDir.create_branch_and_repo(self.get_url('child'),
 
306
                                                      force_new_repo=True,
 
307
                                                      format=format)
 
308
        branch.bzrdir.open_repository()
 
309
 
 
310
    def test_create_standalone_working_tree(self):
 
311
        format = SampleBzrDirFormat()
 
312
        # note this is deliberately readonly, as this failure should 
 
313
        # occur before any writes.
 
314
        self.assertRaises(errors.NotLocalUrl,
 
315
                          bzrdir.BzrDir.create_standalone_workingtree,
 
316
                          self.get_readonly_url(), format=format)
 
317
        tree = bzrdir.BzrDir.create_standalone_workingtree('.', 
 
318
                                                           format=format)
 
319
        self.assertEqual('A tree', tree)
 
320
 
 
321
    def test_create_standalone_working_tree_under_shared_repo(self):
 
322
        # create standalone working tree always makes a repo.
 
323
        format = bzrdir.format_registry.make_bzrdir('knit')
 
324
        self.make_repository('.', shared=True, format=format)
 
325
        # note this is deliberately readonly, as this failure should 
 
326
        # occur before any writes.
 
327
        self.assertRaises(errors.NotLocalUrl,
 
328
                          bzrdir.BzrDir.create_standalone_workingtree,
 
329
                          self.get_readonly_url('child'), format=format)
 
330
        tree = bzrdir.BzrDir.create_standalone_workingtree('child', 
 
331
            format=format)
 
332
        tree.bzrdir.open_repository()
 
333
 
 
334
    def test_create_branch_convenience(self):
 
335
        # outside a repo the default convenience output is a repo+branch_tree
 
336
        format = bzrdir.format_registry.make_bzrdir('knit')
 
337
        branch = bzrdir.BzrDir.create_branch_convenience('.', format=format)
 
338
        branch.bzrdir.open_workingtree()
 
339
        branch.bzrdir.open_repository()
 
340
 
 
341
    def test_create_branch_convenience_possible_transports(self):
 
342
        """Check that the optional 'possible_transports' is recognized"""
 
343
        format = bzrdir.format_registry.make_bzrdir('knit')
 
344
        t = self.get_transport()
 
345
        branch = bzrdir.BzrDir.create_branch_convenience(
 
346
            '.', format=format, possible_transports=[t])
 
347
        branch.bzrdir.open_workingtree()
 
348
        branch.bzrdir.open_repository()
 
349
 
 
350
    def test_create_branch_convenience_root(self):
 
351
        """Creating a branch at the root of a fs should work."""
 
352
        self.vfs_transport_factory = MemoryServer
 
353
        # outside a repo the default convenience output is a repo+branch_tree
 
354
        format = bzrdir.format_registry.make_bzrdir('knit')
 
355
        branch = bzrdir.BzrDir.create_branch_convenience(self.get_url(), 
 
356
                                                         format=format)
 
357
        self.assertRaises(errors.NoWorkingTree,
 
358
                          branch.bzrdir.open_workingtree)
 
359
        branch.bzrdir.open_repository()
 
360
 
 
361
    def test_create_branch_convenience_under_shared_repo(self):
 
362
        # inside a repo the default convenience output is a branch+ follow the
 
363
        # repo tree policy
 
364
        format = bzrdir.format_registry.make_bzrdir('knit')
 
365
        self.make_repository('.', shared=True, format=format)
 
366
        branch = bzrdir.BzrDir.create_branch_convenience('child',
 
367
            format=format)
 
368
        branch.bzrdir.open_workingtree()
 
369
        self.assertRaises(errors.NoRepositoryPresent,
 
370
                          branch.bzrdir.open_repository)
 
371
            
 
372
    def test_create_branch_convenience_under_shared_repo_force_no_tree(self):
 
373
        # inside a repo the default convenience output is a branch+ follow the
 
374
        # repo tree policy but we can override that
 
375
        format = bzrdir.format_registry.make_bzrdir('knit')
 
376
        self.make_repository('.', shared=True, format=format)
 
377
        branch = bzrdir.BzrDir.create_branch_convenience('child',
 
378
            force_new_tree=False, format=format)
 
379
        self.assertRaises(errors.NoWorkingTree,
 
380
                          branch.bzrdir.open_workingtree)
 
381
        self.assertRaises(errors.NoRepositoryPresent,
 
382
                          branch.bzrdir.open_repository)
 
383
            
 
384
    def test_create_branch_convenience_under_shared_repo_no_tree_policy(self):
 
385
        # inside a repo the default convenience output is a branch+ follow the
 
386
        # repo tree policy
 
387
        format = bzrdir.format_registry.make_bzrdir('knit')
 
388
        repo = self.make_repository('.', shared=True, format=format)
 
389
        repo.set_make_working_trees(False)
 
390
        branch = bzrdir.BzrDir.create_branch_convenience('child', 
 
391
                                                         format=format)
 
392
        self.assertRaises(errors.NoWorkingTree,
 
393
                          branch.bzrdir.open_workingtree)
 
394
        self.assertRaises(errors.NoRepositoryPresent,
 
395
                          branch.bzrdir.open_repository)
 
396
 
 
397
    def test_create_branch_convenience_under_shared_repo_no_tree_policy_force_tree(self):
 
398
        # inside a repo the default convenience output is a branch+ follow the
 
399
        # repo tree policy but we can override that
 
400
        format = bzrdir.format_registry.make_bzrdir('knit')
 
401
        repo = self.make_repository('.', shared=True, format=format)
 
402
        repo.set_make_working_trees(False)
 
403
        branch = bzrdir.BzrDir.create_branch_convenience('child',
 
404
            force_new_tree=True, format=format)
 
405
        branch.bzrdir.open_workingtree()
 
406
        self.assertRaises(errors.NoRepositoryPresent,
 
407
                          branch.bzrdir.open_repository)
 
408
 
 
409
    def test_create_branch_convenience_under_shared_repo_force_new_repo(self):
 
410
        # inside a repo the default convenience output is overridable to give
 
411
        # repo+branch+tree
 
412
        format = bzrdir.format_registry.make_bzrdir('knit')
 
413
        self.make_repository('.', shared=True, format=format)
 
414
        branch = bzrdir.BzrDir.create_branch_convenience('child',
 
415
            force_new_repo=True, format=format)
 
416
        branch.bzrdir.open_repository()
 
417
        branch.bzrdir.open_workingtree()
 
418
 
 
419
 
 
420
class TestRepositoryAcquisitionPolicy(TestCaseWithTransport):
 
421
 
 
422
    def test_acquire_repository_standalone(self):
 
423
        """The default acquisition policy should create a standalone branch."""
 
424
        my_bzrdir = self.make_bzrdir('.')
 
425
        repo_policy = my_bzrdir.determine_repository_policy()
 
426
        repo = repo_policy.acquire_repository()
 
427
        self.assertEqual(repo.bzrdir.root_transport.base,
 
428
                         my_bzrdir.root_transport.base)
 
429
        self.assertFalse(repo.is_shared())
 
430
 
 
431
 
 
432
    def test_determine_stacking_policy(self):
 
433
        parent_bzrdir = self.make_bzrdir('.')
 
434
        child_bzrdir = self.make_bzrdir('child')
 
435
        parent_bzrdir.get_config().set_default_stack_on('http://example.org')
 
436
        repo_policy = child_bzrdir.determine_repository_policy()
 
437
        self.assertEqual('http://example.org', repo_policy._stack_on)
 
438
 
 
439
    def test_determine_stacking_policy_relative(self):
 
440
        parent_bzrdir = self.make_bzrdir('.')
 
441
        child_bzrdir = self.make_bzrdir('child')
 
442
        parent_bzrdir.get_config().set_default_stack_on('child2')
 
443
        repo_policy = child_bzrdir.determine_repository_policy()
 
444
        self.assertEqual('child2', repo_policy._stack_on)
 
445
        self.assertEqual(parent_bzrdir.root_transport.base,
 
446
                         repo_policy._stack_on_pwd)
 
447
 
 
448
    def prepare_default_stacking(self, child_format='1.6'):
 
449
        parent_bzrdir = self.make_bzrdir('.')
 
450
        child_branch = self.make_branch('child', format=child_format)
 
451
        parent_bzrdir.get_config().set_default_stack_on(child_branch.base)
 
452
        new_child_transport = parent_bzrdir.transport.clone('child2')
 
453
        return child_branch, new_child_transport
 
454
 
 
455
    def test_clone_on_transport_obeys_stacking_policy(self):
 
456
        child_branch, new_child_transport = self.prepare_default_stacking()
 
457
        new_child = child_branch.bzrdir.clone_on_transport(new_child_transport)
 
458
        self.assertEqual(child_branch.base,
 
459
                         new_child.open_branch().get_stacked_on_url())
 
460
 
 
461
    def test_sprout_obeys_stacking_policy(self):
 
462
        child_branch, new_child_transport = self.prepare_default_stacking()
 
463
        new_child = child_branch.bzrdir.sprout(new_child_transport.base)
 
464
        self.assertEqual(child_branch.base,
 
465
                         new_child.open_branch().get_stacked_on_url())
 
466
 
 
467
    def test_clone_ignores_policy_for_unsupported_formats(self):
 
468
        child_branch, new_child_transport = self.prepare_default_stacking(
 
469
            child_format='pack-0.92')
 
470
        new_child = child_branch.bzrdir.clone_on_transport(new_child_transport)
 
471
        self.assertRaises(errors.UnstackableBranchFormat,
 
472
                          new_child.open_branch().get_stacked_on_url)
 
473
 
 
474
    def test_sprout_ignores_policy_for_unsupported_formats(self):
 
475
        child_branch, new_child_transport = self.prepare_default_stacking(
 
476
            child_format='pack-0.92')
 
477
        new_child = child_branch.bzrdir.sprout(new_child_transport.base)
 
478
        self.assertRaises(errors.UnstackableBranchFormat,
 
479
                          new_child.open_branch().get_stacked_on_url)
 
480
 
 
481
    def test_sprout_upgrades_format_if_stacked_specified(self):
 
482
        child_branch, new_child_transport = self.prepare_default_stacking(
 
483
            child_format='pack-0.92')
 
484
        new_child = child_branch.bzrdir.sprout(new_child_transport.base,
 
485
                                               stacked=True)
 
486
        self.assertEqual(child_branch.bzrdir.root_transport.base,
 
487
                         new_child.open_branch().get_stacked_on_url())
 
488
        repo = new_child.open_repository()
 
489
        self.assertTrue(repo._format.supports_external_lookups)
 
490
        self.assertFalse(repo.supports_rich_root())
 
491
 
 
492
    def test_clone_on_transport_upgrades_format_if_stacked_on_specified(self):
 
493
        child_branch, new_child_transport = self.prepare_default_stacking(
 
494
            child_format='pack-0.92')
 
495
        new_child = child_branch.bzrdir.clone_on_transport(new_child_transport,
 
496
            stacked_on=child_branch.bzrdir.root_transport.base)
 
497
        self.assertEqual(child_branch.bzrdir.root_transport.base,
 
498
                         new_child.open_branch().get_stacked_on_url())
 
499
        repo = new_child.open_repository()
 
500
        self.assertTrue(repo._format.supports_external_lookups)
 
501
        self.assertFalse(repo.supports_rich_root())
 
502
 
 
503
    def test_sprout_upgrades_to_rich_root_format_if_needed(self):
 
504
        child_branch, new_child_transport = self.prepare_default_stacking(
 
505
            child_format='rich-root-pack')
 
506
        new_child = child_branch.bzrdir.sprout(new_child_transport.base,
 
507
                                               stacked=True)
 
508
        repo = new_child.open_repository()
 
509
        self.assertTrue(repo._format.supports_external_lookups)
 
510
        self.assertTrue(repo.supports_rich_root())
 
511
 
 
512
    def test_add_fallback_repo_handles_absolute_urls(self):
 
513
        stack_on = self.make_branch('stack_on', format='1.6')
 
514
        repo = self.make_repository('repo', format='1.6')
 
515
        policy = bzrdir.UseExistingRepository(repo, stack_on.base)
 
516
        policy._add_fallback(repo)
 
517
 
 
518
    def test_add_fallback_repo_handles_relative_urls(self):
 
519
        stack_on = self.make_branch('stack_on', format='1.6')
 
520
        repo = self.make_repository('repo', format='1.6')
 
521
        policy = bzrdir.UseExistingRepository(repo, '.', stack_on.base)
 
522
        policy._add_fallback(repo)
 
523
 
 
524
    def test_configure_relative_branch_stacking_url(self):
 
525
        stack_on = self.make_branch('stack_on', format='1.6')
 
526
        stacked = self.make_branch('stack_on/stacked', format='1.6')
 
527
        policy = bzrdir.UseExistingRepository(stacked.repository,
 
528
            '.', stack_on.base)
 
529
        policy.configure_branch(stacked)
 
530
        self.assertEqual('..', stacked.get_stacked_on_url())
 
531
 
 
532
    def test_relative_branch_stacking_to_absolute(self):
 
533
        stack_on = self.make_branch('stack_on', format='1.6')
 
534
        stacked = self.make_branch('stack_on/stacked', format='1.6')
 
535
        policy = bzrdir.UseExistingRepository(stacked.repository,
 
536
            '.', self.get_readonly_url('stack_on'))
 
537
        policy.configure_branch(stacked)
 
538
        self.assertEqual(self.get_readonly_url('stack_on'),
 
539
                         stacked.get_stacked_on_url())
 
540
 
 
541
 
 
542
class ChrootedTests(TestCaseWithTransport):
 
543
    """A support class that provides readonly urls outside the local namespace.
 
544
 
 
545
    This is done by checking if self.transport_server is a MemoryServer. if it
 
546
    is then we are chrooted already, if it is not then an HttpServer is used
 
547
    for readonly urls.
 
548
    """
 
549
 
 
550
    def setUp(self):
 
551
        super(ChrootedTests, self).setUp()
 
552
        if not self.vfs_transport_factory == MemoryServer:
 
553
            self.transport_readonly_server = HttpServer
 
554
 
 
555
    def local_branch_path(self, branch):
 
556
         return os.path.realpath(urlutils.local_path_from_url(branch.base))
 
557
 
 
558
    def test_open_containing(self):
 
559
        self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing,
 
560
                          self.get_readonly_url(''))
 
561
        self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing,
 
562
                          self.get_readonly_url('g/p/q'))
 
563
        control = bzrdir.BzrDir.create(self.get_url())
 
564
        branch, relpath = bzrdir.BzrDir.open_containing(self.get_readonly_url(''))
 
565
        self.assertEqual('', relpath)
 
566
        branch, relpath = bzrdir.BzrDir.open_containing(self.get_readonly_url('g/p/q'))
 
567
        self.assertEqual('g/p/q', relpath)
 
568
 
 
569
    def test_open_containing_tree_branch_or_repository_empty(self):
 
570
        self.assertRaises(errors.NotBranchError,
 
571
            bzrdir.BzrDir.open_containing_tree_branch_or_repository,
 
572
            self.get_readonly_url(''))
 
573
 
 
574
    def test_open_containing_tree_branch_or_repository_all(self):
 
575
        self.make_branch_and_tree('topdir')
 
576
        tree, branch, repo, relpath = \
 
577
            bzrdir.BzrDir.open_containing_tree_branch_or_repository(
 
578
                'topdir/foo')
 
579
        self.assertEqual(os.path.realpath('topdir'),
 
580
                         os.path.realpath(tree.basedir))
 
581
        self.assertEqual(os.path.realpath('topdir'),
 
582
                         self.local_branch_path(branch))
 
583
        self.assertEqual(
 
584
            osutils.realpath(os.path.join('topdir', '.bzr', 'repository')),
 
585
            repo.bzrdir.transport.local_abspath('repository'))
 
586
        self.assertEqual(relpath, 'foo')
 
587
 
 
588
    def test_open_containing_tree_branch_or_repository_no_tree(self):
 
589
        self.make_branch('branch')
 
590
        tree, branch, repo, relpath = \
 
591
            bzrdir.BzrDir.open_containing_tree_branch_or_repository(
 
592
                'branch/foo')
 
593
        self.assertEqual(tree, None)
 
594
        self.assertEqual(os.path.realpath('branch'),
 
595
                         self.local_branch_path(branch))
 
596
        self.assertEqual(
 
597
            osutils.realpath(os.path.join('branch', '.bzr', 'repository')),
 
598
            repo.bzrdir.transport.local_abspath('repository'))
 
599
        self.assertEqual(relpath, 'foo')
 
600
 
 
601
    def test_open_containing_tree_branch_or_repository_repo(self):
 
602
        self.make_repository('repo')
 
603
        tree, branch, repo, relpath = \
 
604
            bzrdir.BzrDir.open_containing_tree_branch_or_repository(
 
605
                'repo')
 
606
        self.assertEqual(tree, None)
 
607
        self.assertEqual(branch, None)
 
608
        self.assertEqual(
 
609
            osutils.realpath(os.path.join('repo', '.bzr', 'repository')),
 
610
            repo.bzrdir.transport.local_abspath('repository'))
 
611
        self.assertEqual(relpath, '')
 
612
 
 
613
    def test_open_containing_tree_branch_or_repository_shared_repo(self):
 
614
        self.make_repository('shared', shared=True)
 
615
        bzrdir.BzrDir.create_branch_convenience('shared/branch',
 
616
                                                force_new_tree=False)
 
617
        tree, branch, repo, relpath = \
 
618
            bzrdir.BzrDir.open_containing_tree_branch_or_repository(
 
619
                'shared/branch')
 
620
        self.assertEqual(tree, None)
 
621
        self.assertEqual(os.path.realpath('shared/branch'),
 
622
                         self.local_branch_path(branch))
 
623
        self.assertEqual(
 
624
            osutils.realpath(os.path.join('shared', '.bzr', 'repository')),
 
625
            repo.bzrdir.transport.local_abspath('repository'))
 
626
        self.assertEqual(relpath, '')
 
627
 
 
628
    def test_open_containing_tree_branch_or_repository_branch_subdir(self):
 
629
        self.make_branch_and_tree('foo')
 
630
        self.build_tree(['foo/bar/'])
 
631
        tree, branch, repo, relpath = \
 
632
            bzrdir.BzrDir.open_containing_tree_branch_or_repository(
 
633
                'foo/bar')
 
634
        self.assertEqual(os.path.realpath('foo'),
 
635
                         os.path.realpath(tree.basedir))
 
636
        self.assertEqual(os.path.realpath('foo'),
 
637
                         self.local_branch_path(branch))
 
638
        self.assertEqual(
 
639
            osutils.realpath(os.path.join('foo', '.bzr', 'repository')),
 
640
            repo.bzrdir.transport.local_abspath('repository'))
 
641
        self.assertEqual(relpath, 'bar')
 
642
 
 
643
    def test_open_containing_tree_branch_or_repository_repo_subdir(self):
 
644
        self.make_repository('bar')
 
645
        self.build_tree(['bar/baz/'])
 
646
        tree, branch, repo, relpath = \
 
647
            bzrdir.BzrDir.open_containing_tree_branch_or_repository(
 
648
                'bar/baz')
 
649
        self.assertEqual(tree, None)
 
650
        self.assertEqual(branch, None)
 
651
        self.assertEqual(
 
652
            osutils.realpath(os.path.join('bar', '.bzr', 'repository')),
 
653
            repo.bzrdir.transport.local_abspath('repository'))
 
654
        self.assertEqual(relpath, 'baz')
 
655
 
 
656
    def test_open_containing_from_transport(self):
 
657
        self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing_from_transport,
 
658
                          get_transport(self.get_readonly_url('')))
 
659
        self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing_from_transport,
 
660
                          get_transport(self.get_readonly_url('g/p/q')))
 
661
        control = bzrdir.BzrDir.create(self.get_url())
 
662
        branch, relpath = bzrdir.BzrDir.open_containing_from_transport(
 
663
            get_transport(self.get_readonly_url('')))
 
664
        self.assertEqual('', relpath)
 
665
        branch, relpath = bzrdir.BzrDir.open_containing_from_transport(
 
666
            get_transport(self.get_readonly_url('g/p/q')))
 
667
        self.assertEqual('g/p/q', relpath)
 
668
 
 
669
    def test_open_containing_tree_or_branch(self):
 
670
        self.make_branch_and_tree('topdir')
 
671
        tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
 
672
            'topdir/foo')
 
673
        self.assertEqual(os.path.realpath('topdir'),
 
674
                         os.path.realpath(tree.basedir))
 
675
        self.assertEqual(os.path.realpath('topdir'),
 
676
                         self.local_branch_path(branch))
 
677
        self.assertIs(tree.bzrdir, branch.bzrdir)
 
678
        self.assertEqual('foo', relpath)
 
679
        # opening from non-local should not return the tree
 
680
        tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
 
681
            self.get_readonly_url('topdir/foo'))
 
682
        self.assertEqual(None, tree)
 
683
        self.assertEqual('foo', relpath)
 
684
        # without a tree:
 
685
        self.make_branch('topdir/foo')
 
686
        tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
 
687
            'topdir/foo')
 
688
        self.assertIs(tree, None)
 
689
        self.assertEqual(os.path.realpath('topdir/foo'),
 
690
                         self.local_branch_path(branch))
 
691
        self.assertEqual('', relpath)
 
692
 
 
693
    def test_open_tree_or_branch(self):
 
694
        self.make_branch_and_tree('topdir')
 
695
        tree, branch = bzrdir.BzrDir.open_tree_or_branch('topdir')
 
696
        self.assertEqual(os.path.realpath('topdir'),
 
697
                         os.path.realpath(tree.basedir))
 
698
        self.assertEqual(os.path.realpath('topdir'),
 
699
                         self.local_branch_path(branch))
 
700
        self.assertIs(tree.bzrdir, branch.bzrdir)
 
701
        # opening from non-local should not return the tree
 
702
        tree, branch = bzrdir.BzrDir.open_tree_or_branch(
 
703
            self.get_readonly_url('topdir'))
 
704
        self.assertEqual(None, tree)
 
705
        # without a tree:
 
706
        self.make_branch('topdir/foo')
 
707
        tree, branch = bzrdir.BzrDir.open_tree_or_branch('topdir/foo')
 
708
        self.assertIs(tree, None)
 
709
        self.assertEqual(os.path.realpath('topdir/foo'),
 
710
                         self.local_branch_path(branch))
 
711
 
 
712
    def test_open_from_transport(self):
 
713
        # transport pointing at bzrdir should give a bzrdir with root transport
 
714
        # set to the given transport
 
715
        control = bzrdir.BzrDir.create(self.get_url())
 
716
        transport = get_transport(self.get_url())
 
717
        opened_bzrdir = bzrdir.BzrDir.open_from_transport(transport)
 
718
        self.assertEqual(transport.base, opened_bzrdir.root_transport.base)
 
719
        self.assertIsInstance(opened_bzrdir, bzrdir.BzrDir)
 
720
        
 
721
    def test_open_from_transport_no_bzrdir(self):
 
722
        transport = get_transport(self.get_url())
 
723
        self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport,
 
724
                          transport)
 
725
 
 
726
    def test_open_from_transport_bzrdir_in_parent(self):
 
727
        control = bzrdir.BzrDir.create(self.get_url())
 
728
        transport = get_transport(self.get_url())
 
729
        transport.mkdir('subdir')
 
730
        transport = transport.clone('subdir')
 
731
        self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport,
 
732
                          transport)
 
733
 
 
734
    def test_sprout_recursive(self):
 
735
        tree = self.make_branch_and_tree('tree1', format='dirstate-with-subtree')
 
736
        sub_tree = self.make_branch_and_tree('tree1/subtree',
 
737
            format='dirstate-with-subtree')
 
738
        tree.add_reference(sub_tree)
 
739
        self.build_tree(['tree1/subtree/file'])
 
740
        sub_tree.add('file')
 
741
        tree.commit('Initial commit')
 
742
        tree.bzrdir.sprout('tree2')
 
743
        self.failUnlessExists('tree2/subtree/file')
 
744
 
 
745
    def test_cloning_metadir(self):
 
746
        """Ensure that cloning metadir is suitable"""
 
747
        bzrdir = self.make_bzrdir('bzrdir')
 
748
        bzrdir.cloning_metadir()
 
749
        branch = self.make_branch('branch', format='knit')
 
750
        format = branch.bzrdir.cloning_metadir()
 
751
        self.assertIsInstance(format.workingtree_format,
 
752
            workingtree.WorkingTreeFormat3)
 
753
 
 
754
    def test_sprout_recursive_treeless(self):
 
755
        tree = self.make_branch_and_tree('tree1',
 
756
            format='dirstate-with-subtree')
 
757
        sub_tree = self.make_branch_and_tree('tree1/subtree',
 
758
            format='dirstate-with-subtree')
 
759
        tree.add_reference(sub_tree)
 
760
        self.build_tree(['tree1/subtree/file'])
 
761
        sub_tree.add('file')
 
762
        tree.commit('Initial commit')
 
763
        tree.bzrdir.destroy_workingtree()
 
764
        repo = self.make_repository('repo', shared=True,
 
765
            format='dirstate-with-subtree')
 
766
        repo.set_make_working_trees(False)
 
767
        tree.bzrdir.sprout('repo/tree2')
 
768
        self.failUnlessExists('repo/tree2/subtree')
 
769
        self.failIfExists('repo/tree2/subtree/file')
 
770
 
 
771
    def make_foo_bar_baz(self):
 
772
        foo = bzrdir.BzrDir.create_branch_convenience('foo').bzrdir
 
773
        bar = self.make_branch('foo/bar').bzrdir
 
774
        baz = self.make_branch('baz').bzrdir
 
775
        return foo, bar, baz
 
776
 
 
777
    def test_find_bzrdirs(self):
 
778
        foo, bar, baz = self.make_foo_bar_baz()
 
779
        transport = get_transport(self.get_url())
 
780
        self.assertEqualBzrdirs([baz, foo, bar],
 
781
                                bzrdir.BzrDir.find_bzrdirs(transport))
 
782
 
 
783
    def test_find_bzrdirs_list_current(self):
 
784
        def list_current(transport):
 
785
            return [s for s in transport.list_dir('') if s != 'baz']
 
786
 
 
787
        foo, bar, baz = self.make_foo_bar_baz()
 
788
        transport = get_transport(self.get_url())
 
789
        self.assertEqualBzrdirs([foo, bar],
 
790
                                bzrdir.BzrDir.find_bzrdirs(transport,
 
791
                                    list_current=list_current))
 
792
 
 
793
 
 
794
    def test_find_bzrdirs_evaluate(self):
 
795
        def evaluate(bzrdir):
 
796
            try:
 
797
                repo = bzrdir.open_repository()
 
798
            except NoRepositoryPresent:
 
799
                return True, bzrdir.root_transport.base
 
800
            else:
 
801
                return False, bzrdir.root_transport.base
 
802
 
 
803
        foo, bar, baz = self.make_foo_bar_baz()
 
804
        transport = get_transport(self.get_url())
 
805
        self.assertEqual([baz.root_transport.base, foo.root_transport.base],
 
806
                         list(bzrdir.BzrDir.find_bzrdirs(transport,
 
807
                                                         evaluate=evaluate)))
 
808
 
 
809
    def assertEqualBzrdirs(self, first, second):
 
810
        first = list(first)
 
811
        second = list(second)
 
812
        self.assertEqual(len(first), len(second))
 
813
        for x, y in zip(first, second):
 
814
            self.assertEqual(x.root_transport.base, y.root_transport.base)
 
815
 
 
816
    def test_find_branches(self):
 
817
        root = self.make_repository('', shared=True)
 
818
        foo, bar, baz = self.make_foo_bar_baz()
 
819
        qux = self.make_bzrdir('foo/qux')
 
820
        transport = get_transport(self.get_url())
 
821
        branches = bzrdir.BzrDir.find_branches(transport)
 
822
        self.assertEqual(baz.root_transport.base, branches[0].base)
 
823
        self.assertEqual(foo.root_transport.base, branches[1].base)
 
824
        self.assertEqual(bar.root_transport.base, branches[2].base)
 
825
 
 
826
        # ensure this works without a top-level repo
 
827
        branches = bzrdir.BzrDir.find_branches(transport.clone('foo'))
 
828
        self.assertEqual(foo.root_transport.base, branches[0].base)
 
829
        self.assertEqual(bar.root_transport.base, branches[1].base)
 
830
 
 
831
 
 
832
class TestMeta1DirFormat(TestCaseWithTransport):
 
833
    """Tests specific to the meta1 dir format."""
 
834
 
 
835
    def test_right_base_dirs(self):
 
836
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
 
837
        t = dir.transport
 
838
        branch_base = t.clone('branch').base
 
839
        self.assertEqual(branch_base, dir.get_branch_transport(None).base)
 
840
        self.assertEqual(branch_base,
 
841
                         dir.get_branch_transport(bzrlib.branch.BzrBranchFormat5()).base)
 
842
        repository_base = t.clone('repository').base
 
843
        self.assertEqual(repository_base, dir.get_repository_transport(None).base)
 
844
        self.assertEqual(repository_base,
 
845
                         dir.get_repository_transport(weaverepo.RepositoryFormat7()).base)
 
846
        checkout_base = t.clone('checkout').base
 
847
        self.assertEqual(checkout_base, dir.get_workingtree_transport(None).base)
 
848
        self.assertEqual(checkout_base,
 
849
                         dir.get_workingtree_transport(workingtree.WorkingTreeFormat3()).base)
 
850
 
 
851
    def test_meta1dir_uses_lockdir(self):
 
852
        """Meta1 format uses a LockDir to guard the whole directory, not a file."""
 
853
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
 
854
        t = dir.transport
 
855
        self.assertIsDirectory('branch-lock', t)
 
856
 
 
857
    def test_comparison(self):
 
858
        """Equality and inequality behave properly.
 
859
 
 
860
        Metadirs should compare equal iff they have the same repo, branch and
 
861
        tree formats.
 
862
        """
 
863
        mydir = bzrdir.format_registry.make_bzrdir('knit')
 
864
        self.assertEqual(mydir, mydir)
 
865
        self.assertFalse(mydir != mydir)
 
866
        otherdir = bzrdir.format_registry.make_bzrdir('knit')
 
867
        self.assertEqual(otherdir, mydir)
 
868
        self.assertFalse(otherdir != mydir)
 
869
        otherdir2 = bzrdir.format_registry.make_bzrdir('dirstate-with-subtree')
 
870
        self.assertNotEqual(otherdir2, mydir)
 
871
        self.assertFalse(otherdir2 == mydir)
 
872
 
 
873
    def test_needs_conversion_different_working_tree(self):
 
874
        # meta1dirs need an conversion if any element is not the default.
 
875
        old_format = bzrdir.BzrDirFormat.get_default_format()
 
876
        # test with 
 
877
        new_default = bzrdir.format_registry.make_bzrdir('dirstate')
 
878
        bzrdir.BzrDirFormat._set_default_format(new_default)
 
879
        try:
 
880
            tree = self.make_branch_and_tree('tree', format='knit')
 
881
            self.assertTrue(tree.bzrdir.needs_format_conversion())
 
882
        finally:
 
883
            bzrdir.BzrDirFormat._set_default_format(old_format)
 
884
 
 
885
 
 
886
class TestFormat5(TestCaseWithTransport):
 
887
    """Tests specific to the version 5 bzrdir format."""
 
888
 
 
889
    def test_same_lockfiles_between_tree_repo_branch(self):
 
890
        # this checks that only a single lockfiles instance is created 
 
891
        # for format 5 objects
 
892
        dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
 
893
        def check_dir_components_use_same_lock(dir):
 
894
            ctrl_1 = dir.open_repository().control_files
 
895
            ctrl_2 = dir.open_branch().control_files
 
896
            ctrl_3 = dir.open_workingtree()._control_files
 
897
            self.assertTrue(ctrl_1 is ctrl_2)
 
898
            self.assertTrue(ctrl_2 is ctrl_3)
 
899
        check_dir_components_use_same_lock(dir)
 
900
        # and if we open it normally.
 
901
        dir = bzrdir.BzrDir.open(self.get_url())
 
902
        check_dir_components_use_same_lock(dir)
 
903
    
 
904
    def test_can_convert(self):
 
905
        # format 5 dirs are convertable
 
906
        dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
 
907
        self.assertTrue(dir.can_convert_format())
 
908
    
 
909
    def test_needs_conversion(self):
 
910
        # format 5 dirs need a conversion if they are not the default.
 
911
        # and they start of not the default.
 
912
        old_format = bzrdir.BzrDirFormat.get_default_format()
 
913
        bzrdir.BzrDirFormat._set_default_format(bzrdir.BzrDirFormat5())
 
914
        try:
 
915
            dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
 
916
            self.assertFalse(dir.needs_format_conversion())
 
917
        finally:
 
918
            bzrdir.BzrDirFormat._set_default_format(old_format)
 
919
        self.assertTrue(dir.needs_format_conversion())
 
920
 
 
921
 
 
922
class TestFormat6(TestCaseWithTransport):
 
923
    """Tests specific to the version 6 bzrdir format."""
 
924
 
 
925
    def test_same_lockfiles_between_tree_repo_branch(self):
 
926
        # this checks that only a single lockfiles instance is created 
 
927
        # for format 6 objects
 
928
        dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
 
929
        def check_dir_components_use_same_lock(dir):
 
930
            ctrl_1 = dir.open_repository().control_files
 
931
            ctrl_2 = dir.open_branch().control_files
 
932
            ctrl_3 = dir.open_workingtree()._control_files
 
933
            self.assertTrue(ctrl_1 is ctrl_2)
 
934
            self.assertTrue(ctrl_2 is ctrl_3)
 
935
        check_dir_components_use_same_lock(dir)
 
936
        # and if we open it normally.
 
937
        dir = bzrdir.BzrDir.open(self.get_url())
 
938
        check_dir_components_use_same_lock(dir)
 
939
    
 
940
    def test_can_convert(self):
 
941
        # format 6 dirs are convertable
 
942
        dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
 
943
        self.assertTrue(dir.can_convert_format())
 
944
    
 
945
    def test_needs_conversion(self):
 
946
        # format 6 dirs need an conversion if they are not the default.
 
947
        old_format = bzrdir.BzrDirFormat.get_default_format()
 
948
        bzrdir.BzrDirFormat._set_default_format(bzrdir.BzrDirMetaFormat1())
 
949
        try:
 
950
            dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
 
951
            self.assertTrue(dir.needs_format_conversion())
 
952
        finally:
 
953
            bzrdir.BzrDirFormat._set_default_format(old_format)
 
954
 
 
955
 
 
956
class NotBzrDir(bzrlib.bzrdir.BzrDir):
 
957
    """A non .bzr based control directory."""
 
958
 
 
959
    def __init__(self, transport, format):
 
960
        self._format = format
 
961
        self.root_transport = transport
 
962
        self.transport = transport.clone('.not')
 
963
 
 
964
 
 
965
class NotBzrDirFormat(bzrlib.bzrdir.BzrDirFormat):
 
966
    """A test class representing any non-.bzr based disk format."""
 
967
 
 
968
    def initialize_on_transport(self, transport):
 
969
        """Initialize a new .not dir in the base directory of a Transport."""
 
970
        transport.mkdir('.not')
 
971
        return self.open(transport)
 
972
 
 
973
    def open(self, transport):
 
974
        """Open this directory."""
 
975
        return NotBzrDir(transport, self)
 
976
 
 
977
    @classmethod
 
978
    def _known_formats(self):
 
979
        return set([NotBzrDirFormat()])
 
980
 
 
981
    @classmethod
 
982
    def probe_transport(self, transport):
 
983
        """Our format is present if the transport ends in '.not/'."""
 
984
        if transport.has('.not'):
 
985
            return NotBzrDirFormat()
 
986
 
 
987
 
 
988
class TestNotBzrDir(TestCaseWithTransport):
 
989
    """Tests for using the bzrdir api with a non .bzr based disk format.
 
990
    
 
991
    If/when one of these is in the core, we can let the implementation tests
 
992
    verify this works.
 
993
    """
 
994
 
 
995
    def test_create_and_find_format(self):
 
996
        # create a .notbzr dir 
 
997
        format = NotBzrDirFormat()
 
998
        dir = format.initialize(self.get_url())
 
999
        self.assertIsInstance(dir, NotBzrDir)
 
1000
        # now probe for it.
 
1001
        bzrlib.bzrdir.BzrDirFormat.register_control_format(format)
 
1002
        try:
 
1003
            found = bzrlib.bzrdir.BzrDirFormat.find_format(
 
1004
                get_transport(self.get_url()))
 
1005
            self.assertIsInstance(found, NotBzrDirFormat)
 
1006
        finally:
 
1007
            bzrlib.bzrdir.BzrDirFormat.unregister_control_format(format)
 
1008
 
 
1009
    def test_included_in_known_formats(self):
 
1010
        bzrlib.bzrdir.BzrDirFormat.register_control_format(NotBzrDirFormat)
 
1011
        try:
 
1012
            formats = bzrlib.bzrdir.BzrDirFormat.known_formats()
 
1013
            for format in formats:
 
1014
                if isinstance(format, NotBzrDirFormat):
 
1015
                    return
 
1016
            self.fail("No NotBzrDirFormat in %s" % formats)
 
1017
        finally:
 
1018
            bzrlib.bzrdir.BzrDirFormat.unregister_control_format(NotBzrDirFormat)
 
1019
 
 
1020
 
 
1021
class NonLocalTests(TestCaseWithTransport):
 
1022
    """Tests for bzrdir static behaviour on non local paths."""
 
1023
 
 
1024
    def setUp(self):
 
1025
        super(NonLocalTests, self).setUp()
 
1026
        self.vfs_transport_factory = MemoryServer
 
1027
    
 
1028
    def test_create_branch_convenience(self):
 
1029
        # outside a repo the default convenience output is a repo+branch_tree
 
1030
        format = bzrdir.format_registry.make_bzrdir('knit')
 
1031
        branch = bzrdir.BzrDir.create_branch_convenience(
 
1032
            self.get_url('foo'), format=format)
 
1033
        self.assertRaises(errors.NoWorkingTree,
 
1034
                          branch.bzrdir.open_workingtree)
 
1035
        branch.bzrdir.open_repository()
 
1036
 
 
1037
    def test_create_branch_convenience_force_tree_not_local_fails(self):
 
1038
        # outside a repo the default convenience output is a repo+branch_tree
 
1039
        format = bzrdir.format_registry.make_bzrdir('knit')
 
1040
        self.assertRaises(errors.NotLocalUrl,
 
1041
            bzrdir.BzrDir.create_branch_convenience,
 
1042
            self.get_url('foo'),
 
1043
            force_new_tree=True,
 
1044
            format=format)
 
1045
        t = get_transport(self.get_url('.'))
 
1046
        self.assertFalse(t.has('foo'))
 
1047
 
 
1048
    def test_clone(self):
 
1049
        # clone into a nonlocal path works
 
1050
        format = bzrdir.format_registry.make_bzrdir('knit')
 
1051
        branch = bzrdir.BzrDir.create_branch_convenience('local',
 
1052
                                                         format=format)
 
1053
        branch.bzrdir.open_workingtree()
 
1054
        result = branch.bzrdir.clone(self.get_url('remote'))
 
1055
        self.assertRaises(errors.NoWorkingTree,
 
1056
                          result.open_workingtree)
 
1057
        result.open_branch()
 
1058
        result.open_repository()
 
1059
 
 
1060
    def test_checkout_metadir(self):
 
1061
        # checkout_metadir has reasonable working tree format even when no
 
1062
        # working tree is present
 
1063
        self.make_branch('branch-knit2', format='dirstate-with-subtree')
 
1064
        my_bzrdir = bzrdir.BzrDir.open(self.get_url('branch-knit2'))
 
1065
        checkout_format = my_bzrdir.checkout_metadir()
 
1066
        self.assertIsInstance(checkout_format.workingtree_format,
 
1067
                              workingtree.WorkingTreeFormat3)
 
1068
 
 
1069
 
 
1070
class TestHTTPRedirectionLoop(object):
 
1071
    """Test redirection loop between two http servers.
 
1072
 
 
1073
    This MUST be used by daughter classes that also inherit from
 
1074
    TestCaseWithTwoWebservers.
 
1075
 
 
1076
    We can't inherit directly from TestCaseWithTwoWebservers or the
 
1077
    test framework will try to create an instance which cannot
 
1078
    run, its implementation being incomplete. 
 
1079
    """
 
1080
 
 
1081
    # Should be defined by daughter classes to ensure redirection
 
1082
    # still use the same transport implementation (not currently
 
1083
    # enforced as it's a bit tricky to get right (see the FIXME
 
1084
    # in BzrDir.open_from_transport for the unique use case so
 
1085
    # far)
 
1086
    _qualifier = None
 
1087
 
 
1088
    def create_transport_readonly_server(self):
 
1089
        return HTTPServerRedirecting()
 
1090
 
 
1091
    def create_transport_secondary_server(self):
 
1092
        return HTTPServerRedirecting()
 
1093
 
 
1094
    def setUp(self):
 
1095
        # Both servers redirect to each server creating a loop
 
1096
        super(TestHTTPRedirectionLoop, self).setUp()
 
1097
        # The redirections will point to the new server
 
1098
        self.new_server = self.get_readonly_server()
 
1099
        # The requests to the old server will be redirected
 
1100
        self.old_server = self.get_secondary_server()
 
1101
        # Configure the redirections
 
1102
        self.old_server.redirect_to(self.new_server.host, self.new_server.port)
 
1103
        self.new_server.redirect_to(self.old_server.host, self.old_server.port)
 
1104
 
 
1105
    def _qualified_url(self, host, port):
 
1106
        return 'http+%s://%s:%s' % (self._qualifier, host, port)
 
1107
 
 
1108
    def test_loop(self):
 
1109
        # Starting from either server should loop
 
1110
        old_url = self._qualified_url(self.old_server.host, 
 
1111
                                      self.old_server.port)
 
1112
        oldt = self._transport(old_url)
 
1113
        self.assertRaises(errors.NotBranchError,
 
1114
                          bzrdir.BzrDir.open_from_transport, oldt)
 
1115
        new_url = self._qualified_url(self.new_server.host, 
 
1116
                                      self.new_server.port)
 
1117
        newt = self._transport(new_url)
 
1118
        self.assertRaises(errors.NotBranchError,
 
1119
                          bzrdir.BzrDir.open_from_transport, newt)
 
1120
 
 
1121
 
 
1122
class TestHTTPRedirections_urllib(TestHTTPRedirectionLoop,
 
1123
                                  TestCaseWithTwoWebservers):
 
1124
    """Tests redirections for urllib implementation"""
 
1125
 
 
1126
    _qualifier = 'urllib'
 
1127
    _transport = HttpTransport_urllib
 
1128
 
 
1129
 
 
1130
 
 
1131
class TestHTTPRedirections_pycurl(TestWithTransport_pycurl,
 
1132
                                  TestHTTPRedirectionLoop,
 
1133
                                  TestCaseWithTwoWebservers):
 
1134
    """Tests redirections for pycurl implementation"""
 
1135
 
 
1136
    _qualifier = 'pycurl'
 
1137
 
 
1138
 
 
1139
class TestDotBzrHidden(TestCaseWithTransport):
 
1140
 
 
1141
    ls = ['ls']
 
1142
    if sys.platform == 'win32':
 
1143
        ls = [os.environ['COMSPEC'], '/C', 'dir', '/B']
 
1144
 
 
1145
    def get_ls(self):
 
1146
        f = subprocess.Popen(self.ls, stdout=subprocess.PIPE,
 
1147
            stderr=subprocess.PIPE)
 
1148
        out, err = f.communicate()
 
1149
        self.assertEqual(0, f.returncode, 'Calling %s failed: %s'
 
1150
                         % (self.ls, err))
 
1151
        return out.splitlines()
 
1152
 
 
1153
    def test_dot_bzr_hidden(self):
 
1154
        if sys.platform == 'win32' and not win32utils.has_win32file:
 
1155
            raise TestSkipped('unable to make file hidden without pywin32 library')
 
1156
        b = bzrdir.BzrDir.create('.')
 
1157
        self.build_tree(['a'])
 
1158
        self.assertEquals(['a'], self.get_ls())
 
1159
 
 
1160
    def test_dot_bzr_hidden_with_url(self):
 
1161
        if sys.platform == 'win32' and not win32utils.has_win32file:
 
1162
            raise TestSkipped('unable to make file hidden without pywin32 library')
 
1163
        b = bzrdir.BzrDir.create(urlutils.local_path_to_url('.'))
 
1164
        self.build_tree(['a'])
 
1165
        self.assertEquals(['a'], self.get_ls())
 
1166
 
 
1167
 
 
1168
class _TestBzrDirFormat(bzrdir.BzrDirMetaFormat1):
 
1169
    """Test BzrDirFormat implementation for TestBzrDirSprout."""
 
1170
 
 
1171
    def _open(self, transport):
 
1172
        return _TestBzrDir(transport, self)
 
1173
 
 
1174
 
 
1175
class _TestBzrDir(bzrdir.BzrDirMeta1):
 
1176
    """Test BzrDir implementation for TestBzrDirSprout.
 
1177
    
 
1178
    When created a _TestBzrDir already has repository and a branch.  The branch
 
1179
    is a test double as well.
 
1180
    """
 
1181
 
 
1182
    def __init__(self, *args, **kwargs):
 
1183
        super(_TestBzrDir, self).__init__(*args, **kwargs)
 
1184
        self.test_branch = _TestBranch()
 
1185
        self.test_branch.repository = self.create_repository()
 
1186
 
 
1187
    def open_branch(self, unsupported=False):
 
1188
        return self.test_branch
 
1189
 
 
1190
    def cloning_metadir(self, require_stacking=False):
 
1191
        return _TestBzrDirFormat()
 
1192
 
 
1193
 
 
1194
class _TestBranch(bzrlib.branch.Branch):
 
1195
    """Test Branch implementation for TestBzrDirSprout."""
 
1196
 
 
1197
    def __init__(self, *args, **kwargs):
 
1198
        super(_TestBranch, self).__init__(*args, **kwargs)
 
1199
        self.calls = []
 
1200
        self._parent = None
 
1201
 
 
1202
    def sprout(self, *args, **kwargs):
 
1203
        self.calls.append('sprout')
 
1204
        return _TestBranch()
 
1205
 
 
1206
    def copy_content_into(self, destination, revision_id=None):
 
1207
        self.calls.append('copy_content_into')
 
1208
 
 
1209
    def get_parent(self):
 
1210
        return self._parent
 
1211
 
 
1212
    def set_parent(self, parent):
 
1213
        self._parent = parent
 
1214
 
 
1215
 
 
1216
class TestBzrDirSprout(TestCaseWithMemoryTransport):
 
1217
 
 
1218
    def test_sprout_uses_branch_sprout(self):
 
1219
        """BzrDir.sprout calls Branch.sprout.
 
1220
 
 
1221
        Usually, BzrDir.sprout should delegate to the branch's sprout method
 
1222
        for part of the work.  This allows the source branch to control the
 
1223
        choice of format for the new branch.
 
1224
        
 
1225
        There are exceptions, but this tests avoids them:
 
1226
          - if there's no branch in the source bzrdir,
 
1227
          - or if the stacking has been requested and the format needs to be
 
1228
            overridden to satisfy that.
 
1229
        """
 
1230
        # Make an instrumented bzrdir.
 
1231
        t = self.get_transport('source')
 
1232
        t.ensure_base()
 
1233
        source_bzrdir = _TestBzrDirFormat().initialize_on_transport(t)
 
1234
        # The instrumented bzrdir has a test_branch attribute that logs calls
 
1235
        # made to the branch contained in that bzrdir.  Initially the test
 
1236
        # branch exists but no calls have been made to it.
 
1237
        self.assertEqual([], source_bzrdir.test_branch.calls)
 
1238
 
 
1239
        # Sprout the bzrdir
 
1240
        target_url = self.get_url('target')
 
1241
        result = source_bzrdir.sprout(target_url, recurse='no')
 
1242
 
 
1243
        # The bzrdir called the branch's sprout method.
 
1244
        self.assertSubset(['sprout'], source_bzrdir.test_branch.calls)
 
1245
 
 
1246
    def test_sprout_parent(self):
 
1247
        grandparent_tree = self.make_branch('grandparent')
 
1248
        parent = grandparent_tree.bzrdir.sprout('parent').open_branch()
 
1249
        branch_tree = parent.bzrdir.sprout('branch').open_branch()
 
1250
        self.assertContainsRe(branch_tree.get_parent(), '/parent/$')