~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_bzrdir.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2008-07-16 18:36:24 UTC
  • mfrom: (3514.2.19 weave_merge)
  • Revision ID: pqm@pqm.ubuntu.com-20080716183624-7yu6n1raw6sa4x80
(jam) Restore the real Weave merge for --format=weave.

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