1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
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.
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.
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
17
"""Tests for the BzrDir facility and any format specific tests.
19
For interface contract tests, see tests/bzr_dir_implementations.
24
from StringIO import StringIO
39
from bzrlib.errors import (NotBranchError,
41
UnsupportedFormatError,
43
from bzrlib.tests import (
45
TestCaseWithTransport,
49
from bzrlib.tests.http_server import HttpServer
50
from bzrlib.tests.http_utils import (
51
TestCaseWithTwoWebservers,
52
HTTPServerRedirecting,
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
61
class TestDefaultFormat(TestCase):
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.
70
result = bzrdir.BzrDir.create('memory:///')
71
self.failUnless(isinstance(result, SampleBzrDir))
73
bzrdir.BzrDirFormat._set_default_format(old_format)
74
self.assertEqual(old_format, bzrdir.BzrDirFormat.get_default_format())
77
class TestFormatRegistry(TestCase):
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',
90
my_format_registry.set_default('knit')
91
my_format_registry.register_metadir(
93
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
94
'Experimental successor to knit. Use at your own risk.',
95
branch_format='bzrlib.branch.BzrBranchFormat6',
97
my_format_registry.register_metadir(
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,
108
return my_format_registry
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)
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'))
138
def test_help_topic(self):
139
topics = help_topics.HelpTopicRegistry()
140
topics.register('formats', self.make_format_registry().help_topic,
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')
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')
160
self.assertIs(bzrdir.format_registry.get('dirstate-with-subtree'),
161
bzrdir.format_registry.get('default'))
163
repository.RepositoryFormat.get_default_format().__class__,
164
knitrepo.RepositoryFormatKnit3)
166
bzrdir.format_registry.set_default_repository(old_default)
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())
179
class SampleBranch(bzrlib.branch.Branch):
180
"""A dummy branch for guess what, dummy use."""
182
def __init__(self, dir):
186
class SampleBzrDir(bzrdir.BzrDir):
187
"""A sample BzrDir implementation to allow testing static methods."""
189
def create_repository(self, shared=False):
190
"""See BzrDir.create_repository."""
191
return "A repository"
193
def open_repository(self):
194
"""See BzrDir.open_repository."""
195
return "A repository"
197
def create_branch(self):
198
"""See BzrDir.create_branch."""
199
return SampleBranch(self)
201
def create_workingtree(self):
202
"""See BzrDir.create_workingtree."""
206
class SampleBzrDirFormat(bzrdir.BzrDirFormat):
209
this format is initializable, unsupported to aid in testing the
210
open and open_downlevel routines.
213
def get_format_string(self):
214
"""See BzrDirFormat.get_format_string()."""
215
return "Sample .bzr dir format."
217
def initialize_on_transport(self, t):
218
"""Create a bzr dir."""
220
t.put_bytes('.bzr/branch-format', self.get_format_string())
221
return SampleBzrDir(t, self)
223
def is_supported(self):
226
def open(self, transport, _found=None):
227
return "opened branch."
230
class TestBzrDirFormat(TestCaseWithTransport):
231
"""Tests for the BzrDirFormat facility."""
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")
247
def test_find_format_nothing_there(self):
248
self.assertRaises(NotBranchError,
249
bzrdir.BzrDirFormat.find_format,
252
def test_find_format_unknown_format(self):
253
t = get_transport(self.get_url())
255
t.put_bytes('.bzr/branch-format', '')
256
self.assertRaises(UnknownFormatError,
257
bzrdir.BzrDirFormat.find_format,
260
def test_register_unregister_format(self):
261
format = SampleBzrDirFormat()
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)
279
def test_create_branch_and_repo_uses_default(self):
280
format = SampleBzrDirFormat()
281
branch = bzrdir.BzrDir.create_branch_and_repo(self.get_url(),
283
self.assertTrue(isinstance(branch, SampleBranch))
285
def test_create_branch_and_repo_under_shared(self):
286
# creating a branch and repo in a shared repo uses the
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)
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
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'),
303
branch.bzrdir.open_repository()
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('.',
314
self.assertEqual('A tree', tree)
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',
327
tree.bzrdir.open_repository()
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()
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()
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(),
352
self.assertRaises(errors.NoWorkingTree,
353
branch.bzrdir.open_workingtree)
354
branch.bzrdir.open_repository()
356
def test_create_branch_convenience_under_shared_repo(self):
357
# inside a repo the default convenience output is a branch+ follow the
359
format = bzrdir.format_registry.make_bzrdir('knit')
360
self.make_repository('.', shared=True, format=format)
361
branch = bzrdir.BzrDir.create_branch_convenience('child',
363
branch.bzrdir.open_workingtree()
364
self.assertRaises(errors.NoRepositoryPresent,
365
branch.bzrdir.open_repository)
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)
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
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',
387
self.assertRaises(errors.NoWorkingTree,
388
branch.bzrdir.open_workingtree)
389
self.assertRaises(errors.NoRepositoryPresent,
390
branch.bzrdir.open_repository)
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)
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
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()
415
class TestRepositoryAcquisitionPolicy(TestCaseWithTransport):
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())
427
class ChrootedTests(TestCaseWithTransport):
428
"""A support class that provides readonly urls outside the local namespace.
430
This is done by checking if self.transport_server is a MemoryServer. if it
431
is then we are chrooted already, if it is not then an HttpServer is used
436
super(ChrootedTests, self).setUp()
437
if not self.vfs_transport_factory == MemoryServer:
438
self.transport_readonly_server = HttpServer
440
def local_branch_path(self, branch):
441
return os.path.realpath(urlutils.local_path_from_url(branch.base))
443
def test_open_containing(self):
444
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing,
445
self.get_readonly_url(''))
446
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing,
447
self.get_readonly_url('g/p/q'))
448
control = bzrdir.BzrDir.create(self.get_url())
449
branch, relpath = bzrdir.BzrDir.open_containing(self.get_readonly_url(''))
450
self.assertEqual('', relpath)
451
branch, relpath = bzrdir.BzrDir.open_containing(self.get_readonly_url('g/p/q'))
452
self.assertEqual('g/p/q', relpath)
454
def test_open_containing_tree_branch_or_repository_empty(self):
455
self.assertRaises(errors.NotBranchError,
456
bzrdir.BzrDir.open_containing_tree_branch_or_repository,
457
self.get_readonly_url(''))
459
def test_open_containing_tree_branch_or_repository_all(self):
460
self.make_branch_and_tree('topdir')
461
tree, branch, repo, relpath = \
462
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
464
self.assertEqual(os.path.realpath('topdir'),
465
os.path.realpath(tree.basedir))
466
self.assertEqual(os.path.realpath('topdir'),
467
self.local_branch_path(branch))
469
os.path.realpath(os.path.join('topdir', '.bzr', 'repository')),
470
repo.bzrdir.transport.local_abspath('repository'))
471
self.assertEqual(relpath, 'foo')
473
def test_open_containing_tree_branch_or_repository_no_tree(self):
474
self.make_branch('branch')
475
tree, branch, repo, relpath = \
476
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
478
self.assertEqual(tree, None)
479
self.assertEqual(os.path.realpath('branch'),
480
self.local_branch_path(branch))
482
os.path.realpath(os.path.join('branch', '.bzr', 'repository')),
483
repo.bzrdir.transport.local_abspath('repository'))
484
self.assertEqual(relpath, 'foo')
486
def test_open_containing_tree_branch_or_repository_repo(self):
487
self.make_repository('repo')
488
tree, branch, repo, relpath = \
489
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
491
self.assertEqual(tree, None)
492
self.assertEqual(branch, None)
494
os.path.realpath(os.path.join('repo', '.bzr', 'repository')),
495
repo.bzrdir.transport.local_abspath('repository'))
496
self.assertEqual(relpath, '')
498
def test_open_containing_tree_branch_or_repository_shared_repo(self):
499
self.make_repository('shared', shared=True)
500
bzrdir.BzrDir.create_branch_convenience('shared/branch',
501
force_new_tree=False)
502
tree, branch, repo, relpath = \
503
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
505
self.assertEqual(tree, None)
506
self.assertEqual(os.path.realpath('shared/branch'),
507
self.local_branch_path(branch))
509
os.path.realpath(os.path.join('shared', '.bzr', 'repository')),
510
repo.bzrdir.transport.local_abspath('repository'))
511
self.assertEqual(relpath, '')
513
def test_open_containing_tree_branch_or_repository_branch_subdir(self):
514
self.make_branch_and_tree('foo')
515
self.build_tree(['foo/bar/'])
516
tree, branch, repo, relpath = \
517
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
519
self.assertEqual(os.path.realpath('foo'),
520
os.path.realpath(tree.basedir))
521
self.assertEqual(os.path.realpath('foo'),
522
self.local_branch_path(branch))
524
os.path.realpath(os.path.join('foo', '.bzr', 'repository')),
525
repo.bzrdir.transport.local_abspath('repository'))
526
self.assertEqual(relpath, 'bar')
528
def test_open_containing_tree_branch_or_repository_repo_subdir(self):
529
self.make_repository('bar')
530
self.build_tree(['bar/baz/'])
531
tree, branch, repo, relpath = \
532
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
534
self.assertEqual(tree, None)
535
self.assertEqual(branch, None)
537
os.path.realpath(os.path.join('bar', '.bzr', 'repository')),
538
repo.bzrdir.transport.local_abspath('repository'))
539
self.assertEqual(relpath, 'baz')
541
def test_open_containing_from_transport(self):
542
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing_from_transport,
543
get_transport(self.get_readonly_url('')))
544
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing_from_transport,
545
get_transport(self.get_readonly_url('g/p/q')))
546
control = bzrdir.BzrDir.create(self.get_url())
547
branch, relpath = bzrdir.BzrDir.open_containing_from_transport(
548
get_transport(self.get_readonly_url('')))
549
self.assertEqual('', relpath)
550
branch, relpath = bzrdir.BzrDir.open_containing_from_transport(
551
get_transport(self.get_readonly_url('g/p/q')))
552
self.assertEqual('g/p/q', relpath)
554
def test_open_containing_tree_or_branch(self):
555
self.make_branch_and_tree('topdir')
556
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
558
self.assertEqual(os.path.realpath('topdir'),
559
os.path.realpath(tree.basedir))
560
self.assertEqual(os.path.realpath('topdir'),
561
self.local_branch_path(branch))
562
self.assertIs(tree.bzrdir, branch.bzrdir)
563
self.assertEqual('foo', relpath)
564
# opening from non-local should not return the tree
565
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
566
self.get_readonly_url('topdir/foo'))
567
self.assertEqual(None, tree)
568
self.assertEqual('foo', relpath)
570
self.make_branch('topdir/foo')
571
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
573
self.assertIs(tree, None)
574
self.assertEqual(os.path.realpath('topdir/foo'),
575
self.local_branch_path(branch))
576
self.assertEqual('', relpath)
578
def test_open_tree_or_branch(self):
579
self.make_branch_and_tree('topdir')
580
tree, branch = bzrdir.BzrDir.open_tree_or_branch('topdir')
581
self.assertEqual(os.path.realpath('topdir'),
582
os.path.realpath(tree.basedir))
583
self.assertEqual(os.path.realpath('topdir'),
584
self.local_branch_path(branch))
585
self.assertIs(tree.bzrdir, branch.bzrdir)
586
# opening from non-local should not return the tree
587
tree, branch = bzrdir.BzrDir.open_tree_or_branch(
588
self.get_readonly_url('topdir'))
589
self.assertEqual(None, tree)
591
self.make_branch('topdir/foo')
592
tree, branch = bzrdir.BzrDir.open_tree_or_branch('topdir/foo')
593
self.assertIs(tree, None)
594
self.assertEqual(os.path.realpath('topdir/foo'),
595
self.local_branch_path(branch))
597
def test_open_from_transport(self):
598
# transport pointing at bzrdir should give a bzrdir with root transport
599
# set to the given transport
600
control = bzrdir.BzrDir.create(self.get_url())
601
transport = get_transport(self.get_url())
602
opened_bzrdir = bzrdir.BzrDir.open_from_transport(transport)
603
self.assertEqual(transport.base, opened_bzrdir.root_transport.base)
604
self.assertIsInstance(opened_bzrdir, bzrdir.BzrDir)
606
def test_open_from_transport_no_bzrdir(self):
607
transport = get_transport(self.get_url())
608
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport,
611
def test_open_from_transport_bzrdir_in_parent(self):
612
control = bzrdir.BzrDir.create(self.get_url())
613
transport = get_transport(self.get_url())
614
transport.mkdir('subdir')
615
transport = transport.clone('subdir')
616
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport,
619
def test_sprout_recursive(self):
620
tree = self.make_branch_and_tree('tree1', format='dirstate-with-subtree')
621
sub_tree = self.make_branch_and_tree('tree1/subtree',
622
format='dirstate-with-subtree')
623
tree.add_reference(sub_tree)
624
self.build_tree(['tree1/subtree/file'])
626
tree.commit('Initial commit')
627
tree.bzrdir.sprout('tree2')
628
self.failUnlessExists('tree2/subtree/file')
630
def test_cloning_metadir(self):
631
"""Ensure that cloning metadir is suitable"""
632
bzrdir = self.make_bzrdir('bzrdir')
633
bzrdir.cloning_metadir()
634
branch = self.make_branch('branch', format='knit')
635
format = branch.bzrdir.cloning_metadir()
636
self.assertIsInstance(format.workingtree_format,
637
workingtree.WorkingTreeFormat3)
639
def test_sprout_recursive_treeless(self):
640
tree = self.make_branch_and_tree('tree1',
641
format='dirstate-with-subtree')
642
sub_tree = self.make_branch_and_tree('tree1/subtree',
643
format='dirstate-with-subtree')
644
tree.add_reference(sub_tree)
645
self.build_tree(['tree1/subtree/file'])
647
tree.commit('Initial commit')
648
tree.bzrdir.destroy_workingtree()
649
repo = self.make_repository('repo', shared=True,
650
format='dirstate-with-subtree')
651
repo.set_make_working_trees(False)
652
tree.bzrdir.sprout('repo/tree2')
653
self.failUnlessExists('repo/tree2/subtree')
654
self.failIfExists('repo/tree2/subtree/file')
656
def make_foo_bar_baz(self):
657
foo = bzrdir.BzrDir.create_branch_convenience('foo').bzrdir
658
bar = self.make_branch('foo/bar').bzrdir
659
baz = self.make_branch('baz').bzrdir
662
def test_find_bzrdirs(self):
663
foo, bar, baz = self.make_foo_bar_baz()
664
transport = get_transport(self.get_url())
665
self.assertEqualBzrdirs([baz, foo, bar],
666
bzrdir.BzrDir.find_bzrdirs(transport))
668
def test_find_bzrdirs_list_current(self):
669
def list_current(transport):
670
return [s for s in transport.list_dir('') if s != 'baz']
672
foo, bar, baz = self.make_foo_bar_baz()
673
transport = get_transport(self.get_url())
674
self.assertEqualBzrdirs([foo, bar],
675
bzrdir.BzrDir.find_bzrdirs(transport,
676
list_current=list_current))
679
def test_find_bzrdirs_evaluate(self):
680
def evaluate(bzrdir):
682
repo = bzrdir.open_repository()
683
except NoRepositoryPresent:
684
return True, bzrdir.root_transport.base
686
return False, bzrdir.root_transport.base
688
foo, bar, baz = self.make_foo_bar_baz()
689
transport = get_transport(self.get_url())
690
self.assertEqual([baz.root_transport.base, foo.root_transport.base],
691
list(bzrdir.BzrDir.find_bzrdirs(transport,
694
def assertEqualBzrdirs(self, first, second):
696
second = list(second)
697
self.assertEqual(len(first), len(second))
698
for x, y in zip(first, second):
699
self.assertEqual(x.root_transport.base, y.root_transport.base)
701
def test_find_branches(self):
702
root = self.make_repository('', shared=True)
703
foo, bar, baz = self.make_foo_bar_baz()
704
qux = self.make_bzrdir('foo/qux')
705
transport = get_transport(self.get_url())
706
branches = bzrdir.BzrDir.find_branches(transport)
707
self.assertEqual(baz.root_transport.base, branches[0].base)
708
self.assertEqual(foo.root_transport.base, branches[1].base)
709
self.assertEqual(bar.root_transport.base, branches[2].base)
711
# ensure this works without a top-level repo
712
branches = bzrdir.BzrDir.find_branches(transport.clone('foo'))
713
self.assertEqual(foo.root_transport.base, branches[0].base)
714
self.assertEqual(bar.root_transport.base, branches[1].base)
717
class TestMeta1DirFormat(TestCaseWithTransport):
718
"""Tests specific to the meta1 dir format."""
720
def test_right_base_dirs(self):
721
dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
723
branch_base = t.clone('branch').base
724
self.assertEqual(branch_base, dir.get_branch_transport(None).base)
725
self.assertEqual(branch_base,
726
dir.get_branch_transport(bzrlib.branch.BzrBranchFormat5()).base)
727
repository_base = t.clone('repository').base
728
self.assertEqual(repository_base, dir.get_repository_transport(None).base)
729
self.assertEqual(repository_base,
730
dir.get_repository_transport(weaverepo.RepositoryFormat7()).base)
731
checkout_base = t.clone('checkout').base
732
self.assertEqual(checkout_base, dir.get_workingtree_transport(None).base)
733
self.assertEqual(checkout_base,
734
dir.get_workingtree_transport(workingtree.WorkingTreeFormat3()).base)
736
def test_meta1dir_uses_lockdir(self):
737
"""Meta1 format uses a LockDir to guard the whole directory, not a file."""
738
dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
740
self.assertIsDirectory('branch-lock', t)
742
def test_comparison(self):
743
"""Equality and inequality behave properly.
745
Metadirs should compare equal iff they have the same repo, branch and
748
mydir = bzrdir.format_registry.make_bzrdir('knit')
749
self.assertEqual(mydir, mydir)
750
self.assertFalse(mydir != mydir)
751
otherdir = bzrdir.format_registry.make_bzrdir('knit')
752
self.assertEqual(otherdir, mydir)
753
self.assertFalse(otherdir != mydir)
754
otherdir2 = bzrdir.format_registry.make_bzrdir('dirstate-with-subtree')
755
self.assertNotEqual(otherdir2, mydir)
756
self.assertFalse(otherdir2 == mydir)
758
def test_needs_conversion_different_working_tree(self):
759
# meta1dirs need an conversion if any element is not the default.
760
old_format = bzrdir.BzrDirFormat.get_default_format()
762
new_default = bzrdir.format_registry.make_bzrdir('dirstate')
763
bzrdir.BzrDirFormat._set_default_format(new_default)
765
tree = self.make_branch_and_tree('tree', format='knit')
766
self.assertTrue(tree.bzrdir.needs_format_conversion())
768
bzrdir.BzrDirFormat._set_default_format(old_format)
771
class TestFormat5(TestCaseWithTransport):
772
"""Tests specific to the version 5 bzrdir format."""
774
def test_same_lockfiles_between_tree_repo_branch(self):
775
# this checks that only a single lockfiles instance is created
776
# for format 5 objects
777
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
778
def check_dir_components_use_same_lock(dir):
779
ctrl_1 = dir.open_repository().control_files
780
ctrl_2 = dir.open_branch().control_files
781
ctrl_3 = dir.open_workingtree()._control_files
782
self.assertTrue(ctrl_1 is ctrl_2)
783
self.assertTrue(ctrl_2 is ctrl_3)
784
check_dir_components_use_same_lock(dir)
785
# and if we open it normally.
786
dir = bzrdir.BzrDir.open(self.get_url())
787
check_dir_components_use_same_lock(dir)
789
def test_can_convert(self):
790
# format 5 dirs are convertable
791
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
792
self.assertTrue(dir.can_convert_format())
794
def test_needs_conversion(self):
795
# format 5 dirs need a conversion if they are not the default.
796
# and they start of not the default.
797
old_format = bzrdir.BzrDirFormat.get_default_format()
798
bzrdir.BzrDirFormat._set_default_format(bzrdir.BzrDirFormat5())
800
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
801
self.assertFalse(dir.needs_format_conversion())
803
bzrdir.BzrDirFormat._set_default_format(old_format)
804
self.assertTrue(dir.needs_format_conversion())
807
class TestFormat6(TestCaseWithTransport):
808
"""Tests specific to the version 6 bzrdir format."""
810
def test_same_lockfiles_between_tree_repo_branch(self):
811
# this checks that only a single lockfiles instance is created
812
# for format 6 objects
813
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
814
def check_dir_components_use_same_lock(dir):
815
ctrl_1 = dir.open_repository().control_files
816
ctrl_2 = dir.open_branch().control_files
817
ctrl_3 = dir.open_workingtree()._control_files
818
self.assertTrue(ctrl_1 is ctrl_2)
819
self.assertTrue(ctrl_2 is ctrl_3)
820
check_dir_components_use_same_lock(dir)
821
# and if we open it normally.
822
dir = bzrdir.BzrDir.open(self.get_url())
823
check_dir_components_use_same_lock(dir)
825
def test_can_convert(self):
826
# format 6 dirs are convertable
827
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
828
self.assertTrue(dir.can_convert_format())
830
def test_needs_conversion(self):
831
# format 6 dirs need an conversion if they are not the default.
832
old_format = bzrdir.BzrDirFormat.get_default_format()
833
bzrdir.BzrDirFormat._set_default_format(bzrdir.BzrDirMetaFormat1())
835
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
836
self.assertTrue(dir.needs_format_conversion())
838
bzrdir.BzrDirFormat._set_default_format(old_format)
841
class NotBzrDir(bzrlib.bzrdir.BzrDir):
842
"""A non .bzr based control directory."""
844
def __init__(self, transport, format):
845
self._format = format
846
self.root_transport = transport
847
self.transport = transport.clone('.not')
850
class NotBzrDirFormat(bzrlib.bzrdir.BzrDirFormat):
851
"""A test class representing any non-.bzr based disk format."""
853
def initialize_on_transport(self, transport):
854
"""Initialize a new .not dir in the base directory of a Transport."""
855
transport.mkdir('.not')
856
return self.open(transport)
858
def open(self, transport):
859
"""Open this directory."""
860
return NotBzrDir(transport, self)
863
def _known_formats(self):
864
return set([NotBzrDirFormat()])
867
def probe_transport(self, transport):
868
"""Our format is present if the transport ends in '.not/'."""
869
if transport.has('.not'):
870
return NotBzrDirFormat()
873
class TestNotBzrDir(TestCaseWithTransport):
874
"""Tests for using the bzrdir api with a non .bzr based disk format.
876
If/when one of these is in the core, we can let the implementation tests
880
def test_create_and_find_format(self):
881
# create a .notbzr dir
882
format = NotBzrDirFormat()
883
dir = format.initialize(self.get_url())
884
self.assertIsInstance(dir, NotBzrDir)
886
bzrlib.bzrdir.BzrDirFormat.register_control_format(format)
888
found = bzrlib.bzrdir.BzrDirFormat.find_format(
889
get_transport(self.get_url()))
890
self.assertIsInstance(found, NotBzrDirFormat)
892
bzrlib.bzrdir.BzrDirFormat.unregister_control_format(format)
894
def test_included_in_known_formats(self):
895
bzrlib.bzrdir.BzrDirFormat.register_control_format(NotBzrDirFormat)
897
formats = bzrlib.bzrdir.BzrDirFormat.known_formats()
898
for format in formats:
899
if isinstance(format, NotBzrDirFormat):
901
self.fail("No NotBzrDirFormat in %s" % formats)
903
bzrlib.bzrdir.BzrDirFormat.unregister_control_format(NotBzrDirFormat)
906
class NonLocalTests(TestCaseWithTransport):
907
"""Tests for bzrdir static behaviour on non local paths."""
910
super(NonLocalTests, self).setUp()
911
self.vfs_transport_factory = MemoryServer
913
def test_create_branch_convenience(self):
914
# outside a repo the default convenience output is a repo+branch_tree
915
format = bzrdir.format_registry.make_bzrdir('knit')
916
branch = bzrdir.BzrDir.create_branch_convenience(
917
self.get_url('foo'), format=format)
918
self.assertRaises(errors.NoWorkingTree,
919
branch.bzrdir.open_workingtree)
920
branch.bzrdir.open_repository()
922
def test_create_branch_convenience_force_tree_not_local_fails(self):
923
# outside a repo the default convenience output is a repo+branch_tree
924
format = bzrdir.format_registry.make_bzrdir('knit')
925
self.assertRaises(errors.NotLocalUrl,
926
bzrdir.BzrDir.create_branch_convenience,
930
t = get_transport(self.get_url('.'))
931
self.assertFalse(t.has('foo'))
933
def test_clone(self):
934
# clone into a nonlocal path works
935
format = bzrdir.format_registry.make_bzrdir('knit')
936
branch = bzrdir.BzrDir.create_branch_convenience('local',
938
branch.bzrdir.open_workingtree()
939
result = branch.bzrdir.clone(self.get_url('remote'))
940
self.assertRaises(errors.NoWorkingTree,
941
result.open_workingtree)
943
result.open_repository()
945
def test_checkout_metadir(self):
946
# checkout_metadir has reasonable working tree format even when no
947
# working tree is present
948
self.make_branch('branch-knit2', format='dirstate-with-subtree')
949
my_bzrdir = bzrdir.BzrDir.open(self.get_url('branch-knit2'))
950
checkout_format = my_bzrdir.checkout_metadir()
951
self.assertIsInstance(checkout_format.workingtree_format,
952
workingtree.WorkingTreeFormat3)
955
class TestHTTPRedirectionLoop(object):
956
"""Test redirection loop between two http servers.
958
This MUST be used by daughter classes that also inherit from
959
TestCaseWithTwoWebservers.
961
We can't inherit directly from TestCaseWithTwoWebservers or the
962
test framework will try to create an instance which cannot
963
run, its implementation being incomplete.
966
# Should be defined by daughter classes to ensure redirection
967
# still use the same transport implementation (not currently
968
# enforced as it's a bit tricky to get right (see the FIXME
969
# in BzrDir.open_from_transport for the unique use case so
973
def create_transport_readonly_server(self):
974
return HTTPServerRedirecting()
976
def create_transport_secondary_server(self):
977
return HTTPServerRedirecting()
980
# Both servers redirect to each server creating a loop
981
super(TestHTTPRedirectionLoop, self).setUp()
982
# The redirections will point to the new server
983
self.new_server = self.get_readonly_server()
984
# The requests to the old server will be redirected
985
self.old_server = self.get_secondary_server()
986
# Configure the redirections
987
self.old_server.redirect_to(self.new_server.host, self.new_server.port)
988
self.new_server.redirect_to(self.old_server.host, self.old_server.port)
990
def _qualified_url(self, host, port):
991
return 'http+%s://%s:%s' % (self._qualifier, host, port)
994
# Starting from either server should loop
995
old_url = self._qualified_url(self.old_server.host,
996
self.old_server.port)
997
oldt = self._transport(old_url)
998
self.assertRaises(errors.NotBranchError,
999
bzrdir.BzrDir.open_from_transport, oldt)
1000
new_url = self._qualified_url(self.new_server.host,
1001
self.new_server.port)
1002
newt = self._transport(new_url)
1003
self.assertRaises(errors.NotBranchError,
1004
bzrdir.BzrDir.open_from_transport, newt)
1007
class TestHTTPRedirections_urllib(TestHTTPRedirectionLoop,
1008
TestCaseWithTwoWebservers):
1009
"""Tests redirections for urllib implementation"""
1011
_qualifier = 'urllib'
1012
_transport = HttpTransport_urllib
1016
class TestHTTPRedirections_pycurl(TestWithTransport_pycurl,
1017
TestHTTPRedirectionLoop,
1018
TestCaseWithTwoWebservers):
1019
"""Tests redirections for pycurl implementation"""
1021
_qualifier = 'pycurl'
1024
class TestDotBzrHidden(TestCaseWithTransport):
1027
if sys.platform == 'win32':
1028
ls = [os.environ['COMSPEC'], '/C', 'dir', '/B']
1031
f = subprocess.Popen(self.ls, stdout=subprocess.PIPE,
1032
stderr=subprocess.PIPE)
1033
out, err = f.communicate()
1034
self.assertEqual(0, f.returncode, 'Calling %s failed: %s'
1036
return out.splitlines()
1038
def test_dot_bzr_hidden(self):
1039
if sys.platform == 'win32' and not win32utils.has_win32file:
1040
raise TestSkipped('unable to make file hidden without pywin32 library')
1041
b = bzrdir.BzrDir.create('.')
1042
self.build_tree(['a'])
1043
self.assertEquals(['a'], self.get_ls())
1045
def test_dot_bzr_hidden_with_url(self):
1046
if sys.platform == 'win32' and not win32utils.has_win32file:
1047
raise TestSkipped('unable to make file hidden without pywin32 library')
1048
b = bzrdir.BzrDir.create(urlutils.local_path_to_url('.'))
1049
self.build_tree(['a'])
1050
self.assertEquals(['a'], self.get_ls())