/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: Canonical.com Patch Queue Manager
  • Date: 2009-01-09 05:29:09 UTC
  • mfrom: (3928.3.4 stacking_tweaks)
  • Revision ID: pqm@pqm.ubuntu.com-20090109052909-3jh4taiu906vin4p
(jam) Some fixes to stacked branches to avoid opening multiple
        connections.

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