1
# (C) 2005 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.
22
from StringIO import StringIO
25
import bzrlib.bzrdir as bzrdir
26
import bzrlib.errors as errors
27
from bzrlib.errors import (NotBranchError,
29
UnsupportedFormatError,
31
import bzrlib.repository as repository
32
from bzrlib.tests import TestCase, TestCaseWithTransport
33
from bzrlib.tests.test_sftp_transport import TestCaseWithSFTPServer
34
from bzrlib.transport import get_transport
35
from bzrlib.transport.http import HttpServer
36
from bzrlib.transport.memory import MemoryServer
37
import bzrlib.workingtree as workingtree
40
class TestDefaultFormat(TestCase):
42
def test_get_set_default_format(self):
43
old_format = bzrdir.BzrDirFormat.get_default_format()
44
# default is BzrDirFormat6
45
self.failUnless(isinstance(old_format, bzrdir.BzrDirFormat6))
46
bzrdir.BzrDirFormat.set_default_format(SampleBzrDirFormat())
47
# creating a bzr dir should now create an instrumented dir.
49
result = bzrdir.BzrDir.create('memory:/')
50
self.failUnless(isinstance(result, SampleBzrDir))
52
bzrdir.BzrDirFormat.set_default_format(old_format)
53
self.assertEqual(old_format, bzrdir.BzrDirFormat.get_default_format())
56
class SampleBranch(bzrlib.branch.Branch):
57
"""A dummy branch for guess what, dummy use."""
59
def __init__(self, dir):
63
class SampleBzrDir(bzrdir.BzrDir):
64
"""A sample BzrDir implementation to allow testing static methods."""
66
def create_repository(self):
67
"""See BzrDir.create_repository."""
70
def open_repository(self):
71
"""See BzrDir.open_repository."""
74
def create_branch(self):
75
"""See BzrDir.create_branch."""
76
return SampleBranch(self)
78
def create_workingtree(self):
79
"""See BzrDir.create_workingtree."""
83
class SampleBzrDirFormat(bzrdir.BzrDirFormat):
86
this format is initializable, unsupported to aid in testing the
87
open and open_downlevel routines.
90
def get_format_string(self):
91
"""See BzrDirFormat.get_format_string()."""
92
return "Sample .bzr dir format."
94
def initialize(self, url):
95
"""Create a bzr dir."""
96
t = get_transport(url)
98
t.put('.bzr/branch-format', StringIO(self.get_format_string()))
99
return SampleBzrDir(t, self)
101
def is_supported(self):
104
def open(self, transport, _found=None):
105
return "opened branch."
108
class TestBzrDirFormat(TestCaseWithTransport):
109
"""Tests for the BzrDirFormat facility."""
111
def test_find_format(self):
112
# is the right format object found for a branch?
113
# create a branch with a few known format objects.
114
# this is not quite the same as
115
t = get_transport(self.get_url())
116
self.build_tree(["foo/", "bar/"], transport=t)
117
def check_format(format, url):
118
format.initialize(url)
119
t = get_transport(url)
120
found_format = bzrdir.BzrDirFormat.find_format(t)
121
self.failUnless(isinstance(found_format, format.__class__))
122
check_format(bzrdir.BzrDirFormat5(), "foo")
123
check_format(bzrdir.BzrDirFormat6(), "bar")
125
def test_find_format_nothing_there(self):
126
self.assertRaises(NotBranchError,
127
bzrdir.BzrDirFormat.find_format,
130
def test_find_format_unknown_format(self):
131
t = get_transport(self.get_url())
133
t.put('.bzr/branch-format', StringIO())
134
self.assertRaises(UnknownFormatError,
135
bzrdir.BzrDirFormat.find_format,
138
def test_register_unregister_format(self):
139
format = SampleBzrDirFormat()
142
format.initialize(url)
143
# register a format for it.
144
bzrdir.BzrDirFormat.register_format(format)
145
# which bzrdir.Open will refuse (not supported)
146
self.assertRaises(UnsupportedFormatError, bzrdir.BzrDir.open, url)
147
# but open_downlevel will work
148
t = get_transport(url)
149
self.assertEqual(format.open(t), bzrdir.BzrDir.open_unsupported(url))
150
# unregister the format
151
bzrdir.BzrDirFormat.unregister_format(format)
152
# now open_downlevel should fail too.
153
self.assertRaises(UnknownFormatError, bzrdir.BzrDir.open_unsupported, url)
155
def test_create_repository(self):
156
format = SampleBzrDirFormat()
157
old_format = bzrdir.BzrDirFormat.get_default_format()
158
bzrdir.BzrDirFormat.set_default_format(format)
160
repo = bzrdir.BzrDir.create_repository(self.get_url())
161
self.assertEqual('A repository', repo)
163
bzrdir.BzrDirFormat.set_default_format(old_format)
165
def test_create_repository_under_shared(self):
166
# an explicit create_repository always does so.
167
# we trust the format is right from the 'create_repository test'
168
old_format = bzrdir.BzrDirFormat.get_default_format()
169
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
171
self.make_repository('.', shared=True)
172
repo = bzrdir.BzrDir.create_repository(self.get_url('child'))
173
self.assertTrue(isinstance(repo, repository.Repository))
174
self.assertTrue(repo.bzrdir.root_transport.base.endswith('child/'))
176
bzrdir.BzrDirFormat.set_default_format(old_format)
178
def test_create_branch_and_repo_uses_default(self):
179
format = SampleBzrDirFormat()
180
old_format = bzrdir.BzrDirFormat.get_default_format()
181
bzrdir.BzrDirFormat.set_default_format(format)
183
branch = bzrdir.BzrDir.create_branch_and_repo(self.get_url())
184
self.assertTrue(isinstance(branch, SampleBranch))
186
bzrdir.BzrDirFormat.set_default_format(old_format)
188
def test_create_branch_and_repo_under_shared(self):
189
# creating a branch and repo in a shared repo uses the
191
old_format = bzrdir.BzrDirFormat.get_default_format()
192
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
194
self.make_repository('.', shared=True)
195
branch = bzrdir.BzrDir.create_branch_and_repo(self.get_url('child'))
196
self.assertRaises(errors.NoRepositoryPresent,
197
branch.bzrdir.open_repository)
199
bzrdir.BzrDirFormat.set_default_format(old_format)
201
def test_create_branch_and_repo_under_shared_force_new(self):
202
# creating a branch and repo in a shared repo can be forced to
204
old_format = bzrdir.BzrDirFormat.get_default_format()
205
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
207
self.make_repository('.', shared=True)
208
branch = bzrdir.BzrDir.create_branch_and_repo(self.get_url('child'),
210
branch.bzrdir.open_repository()
212
bzrdir.BzrDirFormat.set_default_format(old_format)
214
def test_create_standalone_working_tree(self):
215
format = SampleBzrDirFormat()
216
old_format = bzrdir.BzrDirFormat.get_default_format()
217
bzrdir.BzrDirFormat.set_default_format(format)
219
# note this is deliberately readonly, as this failure should
220
# occur before any writes.
221
self.assertRaises(errors.NotLocalUrl,
222
bzrdir.BzrDir.create_standalone_workingtree,
223
self.get_readonly_url())
224
tree = bzrdir.BzrDir.create_standalone_workingtree('.')
225
self.assertEqual('A tree', tree)
227
bzrdir.BzrDirFormat.set_default_format(old_format)
229
def test_create_standalone_working_tree_under_shared_repo(self):
230
# create standalone working tree always makes a repo.
231
old_format = bzrdir.BzrDirFormat.get_default_format()
232
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
234
self.make_repository('.', shared=True)
235
# note this is deliberately readonly, as this failure should
236
# occur before any writes.
237
self.assertRaises(errors.NotLocalUrl,
238
bzrdir.BzrDir.create_standalone_workingtree,
239
self.get_readonly_url('child'))
240
tree = bzrdir.BzrDir.create_standalone_workingtree('child')
241
tree.bzrdir.open_repository()
243
bzrdir.BzrDirFormat.set_default_format(old_format)
245
def test_create_branch_convenience(self):
246
# outside a repo the default convenience output is a repo+branch_tree
247
old_format = bzrdir.BzrDirFormat.get_default_format()
248
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
250
branch = bzrdir.BzrDir.create_branch_convenience('.')
251
branch.bzrdir.open_workingtree()
252
branch.bzrdir.open_repository()
254
bzrdir.BzrDirFormat.set_default_format(old_format)
256
def test_create_branch_convenience_under_shared_repo(self):
257
# inside a repo the default convenience output is a branch+ follow the
259
old_format = bzrdir.BzrDirFormat.get_default_format()
260
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
262
self.make_repository('.', shared=True)
263
branch = bzrdir.BzrDir.create_branch_convenience('child')
264
branch.bzrdir.open_workingtree()
265
self.assertRaises(errors.NoRepositoryPresent,
266
branch.bzrdir.open_repository)
268
bzrdir.BzrDirFormat.set_default_format(old_format)
270
def test_create_branch_convenience_under_shared_repo_force_no_tree(self):
271
# inside a repo the default convenience output is a branch+ follow the
272
# repo tree policy but we can override that
273
old_format = bzrdir.BzrDirFormat.get_default_format()
274
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
276
self.make_repository('.', shared=True)
277
branch = bzrdir.BzrDir.create_branch_convenience('child',
278
force_new_tree=False)
279
self.assertRaises(errors.NoWorkingTree,
280
branch.bzrdir.open_workingtree)
281
self.assertRaises(errors.NoRepositoryPresent,
282
branch.bzrdir.open_repository)
284
bzrdir.BzrDirFormat.set_default_format(old_format)
286
def test_create_branch_convenience_under_shared_repo_no_tree_policy(self):
287
# inside a repo the default convenience output is a branch+ follow the
289
old_format = bzrdir.BzrDirFormat.get_default_format()
290
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
292
repo = self.make_repository('.', shared=True)
293
repo.set_make_working_trees(False)
294
branch = bzrdir.BzrDir.create_branch_convenience('child')
295
self.assertRaises(errors.NoWorkingTree,
296
branch.bzrdir.open_workingtree)
297
self.assertRaises(errors.NoRepositoryPresent,
298
branch.bzrdir.open_repository)
300
bzrdir.BzrDirFormat.set_default_format(old_format)
302
def test_create_branch_convenience_under_shared_repo_no_tree_policy_force_tree(self):
303
# inside a repo the default convenience output is a branch+ follow the
304
# repo tree policy but we can override that
305
old_format = bzrdir.BzrDirFormat.get_default_format()
306
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
308
repo = self.make_repository('.', shared=True)
309
repo.set_make_working_trees(False)
310
branch = bzrdir.BzrDir.create_branch_convenience('child',
312
branch.bzrdir.open_workingtree()
313
self.assertRaises(errors.NoRepositoryPresent,
314
branch.bzrdir.open_repository)
316
bzrdir.BzrDirFormat.set_default_format(old_format)
318
def test_create_branch_convenience_under_shared_repo_force_new_repo(self):
319
# inside a repo the default convenience output is overridable to give
321
old_format = bzrdir.BzrDirFormat.get_default_format()
322
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
324
self.make_repository('.', shared=True)
325
branch = bzrdir.BzrDir.create_branch_convenience('child',
327
branch.bzrdir.open_repository()
328
branch.bzrdir.open_workingtree()
330
bzrdir.BzrDirFormat.set_default_format(old_format)
333
class ChrootedTests(TestCaseWithTransport):
334
"""A support class that provides readonly urls outside the local namespace.
336
This is done by checking if self.transport_server is a MemoryServer. if it
337
is then we are chrooted already, if it is not then an HttpServer is used
342
super(ChrootedTests, self).setUp()
343
if not self.transport_server == MemoryServer:
344
self.transport_readonly_server = HttpServer
346
def test_open_containing(self):
347
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing,
348
self.get_readonly_url(''))
349
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing,
350
self.get_readonly_url('g/p/q'))
351
control = bzrdir.BzrDir.create(self.get_url())
352
branch, relpath = bzrdir.BzrDir.open_containing(self.get_readonly_url(''))
353
self.assertEqual('', relpath)
354
branch, relpath = bzrdir.BzrDir.open_containing(self.get_readonly_url('g/p/q'))
355
self.assertEqual('g/p/q', relpath)
357
def test_open_containing_from_transport(self):
358
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing_from_transport,
359
get_transport(self.get_readonly_url('')))
360
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing_from_transport,
361
get_transport(self.get_readonly_url('g/p/q')))
362
control = bzrdir.BzrDir.create(self.get_url())
363
branch, relpath = bzrdir.BzrDir.open_containing_from_transport(
364
get_transport(self.get_readonly_url('')))
365
self.assertEqual('', relpath)
366
branch, relpath = bzrdir.BzrDir.open_containing_from_transport(
367
get_transport(self.get_readonly_url('g/p/q')))
368
self.assertEqual('g/p/q', relpath)
371
class TestMeta1DirFormat(TestCaseWithTransport):
372
"""Tests specific to the meta1 dir format."""
374
def test_right_base_dirs(self):
375
dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
377
branch_base = t.clone('branch').base
378
self.assertEqual(branch_base, dir.get_branch_transport(None).base)
379
self.assertEqual(branch_base,
380
dir.get_branch_transport(bzrlib.branch.BzrBranchFormat5()).base)
381
repository_base = t.clone('repository').base
382
self.assertEqual(repository_base, dir.get_repository_transport(None).base)
383
self.assertEqual(repository_base,
384
dir.get_repository_transport(repository.RepositoryFormat7()).base)
385
checkout_base = t.clone('checkout').base
386
self.assertEqual(checkout_base, dir.get_workingtree_transport(None).base)
387
self.assertEqual(checkout_base,
388
dir.get_workingtree_transport(workingtree.WorkingTreeFormat3()).base)
391
class TestFormat5(TestCaseWithTransport):
392
"""Tests specific to the version 5 bzrdir format."""
394
def test_same_lockfiles_between_tree_repo_branch(self):
395
# this checks that only a single lockfiles instance is created
396
# for format 5 objects
397
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
398
def check_dir_components_use_same_lock(dir):
399
ctrl_1 = dir.open_repository().control_files
400
ctrl_2 = dir.open_branch().control_files
401
ctrl_3 = dir.open_workingtree()._control_files
402
self.assertTrue(ctrl_1 is ctrl_2)
403
self.assertTrue(ctrl_2 is ctrl_3)
404
check_dir_components_use_same_lock(dir)
405
# and if we open it normally.
406
dir = bzrdir.BzrDir.open(self.get_url())
407
check_dir_components_use_same_lock(dir)
409
def test_can_convert(self):
410
# format 5 dirs are convertable
411
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
412
self.assertTrue(dir.can_convert_format())
414
def test_needs_conversion(self):
415
# format 5 dirs need a conversion if they are not the default.
416
# and they start of not the default.
417
old_format = bzrdir.BzrDirFormat.get_default_format()
418
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirFormat5())
420
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
421
self.assertFalse(dir.needs_format_conversion())
423
bzrdir.BzrDirFormat.set_default_format(old_format)
424
self.assertTrue(dir.needs_format_conversion())
427
class TestFormat6(TestCaseWithTransport):
428
"""Tests specific to the version 6 bzrdir format."""
430
def test_same_lockfiles_between_tree_repo_branch(self):
431
# this checks that only a single lockfiles instance is created
432
# for format 6 objects
433
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
434
def check_dir_components_use_same_lock(dir):
435
ctrl_1 = dir.open_repository().control_files
436
ctrl_2 = dir.open_branch().control_files
437
ctrl_3 = dir.open_workingtree()._control_files
438
self.assertTrue(ctrl_1 is ctrl_2)
439
self.assertTrue(ctrl_2 is ctrl_3)
440
check_dir_components_use_same_lock(dir)
441
# and if we open it normally.
442
dir = bzrdir.BzrDir.open(self.get_url())
443
check_dir_components_use_same_lock(dir)
445
def test_can_convert(self):
446
# format 6 dirs are convertable
447
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
448
self.assertTrue(dir.can_convert_format())
450
def test_needs_conversion(self):
451
# format 6 dirs need an conversion if they are not the default.
452
old_format = bzrdir.BzrDirFormat.get_default_format()
453
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
455
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
456
self.assertTrue(dir.needs_format_conversion())
458
bzrdir.BzrDirFormat.set_default_format(old_format)
459
self.assertFalse(dir.needs_format_conversion())
462
class NonLocalTests(TestCaseWithTransport):
463
"""Tests for bzrdir static behaviour on non local paths."""
466
super(NonLocalTests, self).setUp()
467
self.transport_server = MemoryServer
469
def test_create_branch_convenience(self):
470
# outside a repo the default convenience output is a repo+branch_tree
471
old_format = bzrdir.BzrDirFormat.get_default_format()
472
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
474
branch = bzrdir.BzrDir.create_branch_convenience(self.get_url('foo'))
475
self.assertRaises(errors.NoWorkingTree,
476
branch.bzrdir.open_workingtree)
477
branch.bzrdir.open_repository()
479
bzrdir.BzrDirFormat.set_default_format(old_format)
481
def test_create_branch_convenience_force_tree_not_local_fails(self):
482
# outside a repo the default convenience output is a repo+branch_tree
483
old_format = bzrdir.BzrDirFormat.get_default_format()
484
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
486
self.assertRaises(errors.NotLocalUrl,
487
bzrdir.BzrDir.create_branch_convenience,
490
t = get_transport(self.get_url('.'))
491
self.assertFalse(t.has('foo'))
493
bzrdir.BzrDirFormat.set_default_format(old_format)