1
# Copyright (C) 2006-2013, 2016 Canonical Ltd
1
# Copyright (C) 2005, 2006 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
11
# GNU General Public License for more details.
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
17
"""Tests for the BzrDir facility and any format specific tests.
19
For interface contract tests, see tests/per_bzr_dir.
19
For interface contract tests, see tests/bzr_dir_implementations.
22
from StringIO import StringIO
35
revision as _mod_revision,
37
transport as _mod_transport,
49
import breezy.bzr.branch
50
from ..bzr.fullhistory import BzrBranchFormat5
51
from ..errors import (
53
NoColocatedBranchSupport,
55
UnsupportedFormatError,
59
TestCaseWithMemoryTransport,
60
TestCaseWithTransport,
67
from ..transport import (
71
from ..transport.http import HttpTransport
72
from ..transport.nosmart import NoSmartTransportDecorator
73
from ..transport.readonly import ReadonlyTransportDecorator
74
from ..bzr import knitrepo, knitpack_repo
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.transport import get_transport
34
from bzrlib.transport.http import HttpServer
35
from bzrlib.transport.memory import MemoryServer
36
import bzrlib.workingtree as workingtree
77
39
class TestDefaultFormat(TestCase):
79
41
def test_get_set_default_format(self):
80
42
old_format = bzrdir.BzrDirFormat.get_default_format()
81
# default is BzrDirMetaFormat1
82
self.assertIsInstance(old_format, bzrdir.BzrDirMetaFormat1)
83
controldir.ControlDirFormat._set_default_format(SampleBzrDirFormat())
43
# default is BzrDirFormat6
44
self.failUnless(isinstance(old_format, bzrdir.BzrDirMetaFormat1))
45
bzrdir.BzrDirFormat.set_default_format(SampleBzrDirFormat())
84
46
# creating a bzr dir should now create an instrumented dir.
86
result = bzrdir.BzrDir.create('memory:///')
87
self.assertIsInstance(result, SampleBzrDir)
48
result = bzrdir.BzrDir.create('memory:/')
49
self.failUnless(isinstance(result, SampleBzrDir))
89
controldir.ControlDirFormat._set_default_format(old_format)
51
bzrdir.BzrDirFormat.set_default_format(old_format)
90
52
self.assertEqual(old_format, bzrdir.BzrDirFormat.get_default_format())
93
class DeprecatedBzrDirFormat(bzrdir.BzrDirFormat):
94
"""A deprecated bzr dir format."""
97
class TestFormatRegistry(TestCase):
99
def make_format_registry(self):
100
my_format_registry = controldir.ControlDirFormatRegistry()
101
my_format_registry.register('deprecated', DeprecatedBzrDirFormat,
102
'Some format. Slower and unawesome and deprecated.',
104
my_format_registry.register_lazy('lazy', 'breezy.tests.test_bzrdir',
105
'DeprecatedBzrDirFormat', 'Format registered lazily',
107
bzr.register_metadir(my_format_registry, 'knit',
108
'breezy.bzr.knitrepo.RepositoryFormatKnit1',
109
'Format using knits',
111
my_format_registry.set_default('knit')
112
bzr.register_metadir(my_format_registry,
114
'breezy.bzr.knitrepo.RepositoryFormatKnit3',
115
'Experimental successor to knit. Use at your own risk.',
116
branch_format='breezy.bzr.branch.BzrBranchFormat6',
118
bzr.register_metadir(my_format_registry,
120
'breezy.bzr.knitrepo.RepositoryFormatKnit3',
121
'Experimental successor to knit. Use at your own risk.',
122
branch_format='breezy.bzr.branch.BzrBranchFormat6', hidden=True)
123
my_format_registry.register('hiddendeprecated', DeprecatedBzrDirFormat,
124
'Old format. Slower and does not support things. ', hidden=True)
125
my_format_registry.register_lazy('hiddenlazy', 'breezy.tests.test_bzrdir',
126
'DeprecatedBzrDirFormat', 'Format registered lazily',
127
deprecated=True, hidden=True)
128
return my_format_registry
130
def test_format_registry(self):
131
my_format_registry = self.make_format_registry()
132
my_bzrdir = my_format_registry.make_controldir('lazy')
133
self.assertIsInstance(my_bzrdir, DeprecatedBzrDirFormat)
134
my_bzrdir = my_format_registry.make_controldir('deprecated')
135
self.assertIsInstance(my_bzrdir, DeprecatedBzrDirFormat)
136
my_bzrdir = my_format_registry.make_controldir('default')
137
self.assertIsInstance(my_bzrdir.repository_format,
138
knitrepo.RepositoryFormatKnit1)
139
my_bzrdir = my_format_registry.make_controldir('knit')
140
self.assertIsInstance(my_bzrdir.repository_format,
141
knitrepo.RepositoryFormatKnit1)
142
my_bzrdir = my_format_registry.make_controldir('branch6')
143
self.assertIsInstance(my_bzrdir.get_branch_format(),
144
breezy.bzr.branch.BzrBranchFormat6)
146
def test_get_help(self):
147
my_format_registry = self.make_format_registry()
148
self.assertEqual('Format registered lazily',
149
my_format_registry.get_help('lazy'))
150
self.assertEqual('Format using knits',
151
my_format_registry.get_help('knit'))
152
self.assertEqual('Format using knits',
153
my_format_registry.get_help('default'))
154
self.assertEqual('Some format. Slower and unawesome and deprecated.',
155
my_format_registry.get_help('deprecated'))
157
def test_help_topic(self):
158
topics = help_topics.HelpTopicRegistry()
159
registry = self.make_format_registry()
160
topics.register('current-formats', registry.help_topic,
162
topics.register('other-formats', registry.help_topic,
164
new = topics.get_detail('current-formats')
165
rest = topics.get_detail('other-formats')
166
experimental, deprecated = rest.split('Deprecated formats')
167
self.assertContainsRe(new, 'formats-help')
168
self.assertContainsRe(new,
169
':knit:\n \\(native\\) \\(default\\) Format using knits\n')
170
self.assertContainsRe(experimental,
171
':branch6:\n \\(native\\) Experimental successor to knit')
172
self.assertContainsRe(deprecated,
173
':lazy:\n \\(native\\) Format registered lazily\n')
174
self.assertNotContainsRe(new, 'hidden')
176
def test_set_default_repository(self):
177
default_factory = controldir.format_registry.get('default')
178
old_default = [k for k, v in controldir.format_registry.iteritems()
179
if v == default_factory and k != 'default'][0]
180
controldir.format_registry.set_default_repository(
181
'dirstate-with-subtree')
183
self.assertIs(controldir.format_registry.get('dirstate-with-subtree'),
184
controldir.format_registry.get('default'))
186
repository.format_registry.get_default().__class__,
187
knitrepo.RepositoryFormatKnit3)
189
controldir.format_registry.set_default_repository(old_default)
191
def test_aliases(self):
192
a_registry = controldir.ControlDirFormatRegistry()
193
a_registry.register('deprecated', DeprecatedBzrDirFormat,
194
'Old format. Slower and does not support stuff',
196
a_registry.register_alias('deprecatedalias', 'deprecated')
197
self.assertEqual({'deprecatedalias': 'deprecated'},
198
a_registry.aliases())
201
class SampleBranch(breezy.branch.Branch):
55
class SampleBranch(bzrlib.branch.Branch):
202
56
"""A dummy branch for guess what, dummy use."""
204
58
def __init__(self, dir):
205
self.controldir = dir
208
class SampleRepository(breezy.repository.Repository):
211
def __init__(self, dir):
212
self.controldir = dir
215
62
class SampleBzrDir(bzrdir.BzrDir):
216
63
"""A sample BzrDir implementation to allow testing static methods."""
218
def create_repository(self, shared=False):
219
"""See ControlDir.create_repository."""
65
def create_repository(self):
66
"""See BzrDir.create_repository."""
220
67
return "A repository"
222
69
def open_repository(self):
223
"""See ControlDir.open_repository."""
224
return SampleRepository(self)
70
"""See BzrDir.open_repository."""
226
def create_branch(self, name=None):
227
"""See ControlDir.create_branch."""
229
raise NoColocatedBranchSupport(self)
73
def create_branch(self):
74
"""See BzrDir.create_branch."""
230
75
return SampleBranch(self)
232
77
def create_workingtree(self):
233
"""See ControlDir.create_workingtree."""
78
"""See BzrDir.create_workingtree."""
237
82
class SampleBzrDirFormat(bzrdir.BzrDirFormat):
238
83
"""A sample format
240
this format is initializable, unsupported to aid in testing the
85
this format is initializable, unsupported to aid in testing the
241
86
open and open_downlevel routines.
244
89
def get_format_string(self):
245
90
"""See BzrDirFormat.get_format_string()."""
246
return b"Sample .bzr dir format."
91
return "Sample .bzr dir format."
248
def initialize_on_transport(self, t):
93
def initialize(self, url):
249
94
"""Create a bzr dir."""
95
t = get_transport(url)
251
t.put_bytes('.bzr/branch-format', self.get_format_string())
97
t.put('.bzr/branch-format', StringIO(self.get_format_string()))
252
98
return SampleBzrDir(t, self)
254
100
def is_supported(self):
329
141
format.initialize(url)
330
142
# register a format for it.
331
bzr.BzrProber.formats.register(format.get_format_string(), format)
143
bzrdir.BzrDirFormat.register_format(format)
332
144
# which bzrdir.Open will refuse (not supported)
333
145
self.assertRaises(UnsupportedFormatError, bzrdir.BzrDir.open, url)
334
146
# which bzrdir.open_containing will refuse (not supported)
335
self.assertRaises(UnsupportedFormatError,
336
bzrdir.BzrDir.open_containing, url)
147
self.assertRaises(UnsupportedFormatError, bzrdir.BzrDir.open_containing, url)
337
148
# but open_downlevel will work
338
t = _mod_transport.get_transport_from_url(url)
149
t = get_transport(url)
339
150
self.assertEqual(format.open(t), bzrdir.BzrDir.open_unsupported(url))
340
151
# unregister the format
341
bzr.BzrProber.formats.remove(format.get_format_string())
152
bzrdir.BzrDirFormat.unregister_format(format)
342
153
# now open_downlevel should fail too.
343
self.assertRaises(UnknownFormatError,
344
bzrdir.BzrDir.open_unsupported, url)
154
self.assertRaises(UnknownFormatError, bzrdir.BzrDir.open_unsupported, url)
156
def test_create_repository(self):
157
format = SampleBzrDirFormat()
158
old_format = bzrdir.BzrDirFormat.get_default_format()
159
bzrdir.BzrDirFormat.set_default_format(format)
161
repo = bzrdir.BzrDir.create_repository(self.get_url())
162
self.assertEqual('A repository', repo)
164
bzrdir.BzrDirFormat.set_default_format(old_format)
166
def test_create_repository_under_shared(self):
167
# an explicit create_repository always does so.
168
# we trust the format is right from the 'create_repository test'
169
old_format = bzrdir.BzrDirFormat.get_default_format()
170
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
172
self.make_repository('.', shared=True)
173
repo = bzrdir.BzrDir.create_repository(self.get_url('child'))
174
self.assertTrue(isinstance(repo, repository.Repository))
175
self.assertTrue(repo.bzrdir.root_transport.base.endswith('child/'))
177
bzrdir.BzrDirFormat.set_default_format(old_format)
346
179
def test_create_branch_and_repo_uses_default(self):
347
180
format = SampleBzrDirFormat()
348
branch = bzrdir.BzrDir.create_branch_and_repo(self.get_url(),
350
self.assertTrue(isinstance(branch, SampleBranch))
181
old_format = bzrdir.BzrDirFormat.get_default_format()
182
bzrdir.BzrDirFormat.set_default_format(format)
184
branch = bzrdir.BzrDir.create_branch_and_repo(self.get_url())
185
self.assertTrue(isinstance(branch, SampleBranch))
187
bzrdir.BzrDirFormat.set_default_format(old_format)
352
189
def test_create_branch_and_repo_under_shared(self):
353
190
# creating a branch and repo in a shared repo uses the
354
191
# shared repository
355
format = controldir.format_registry.make_controldir('knit')
356
self.make_repository('.', shared=True, format=format)
357
branch = bzrdir.BzrDir.create_branch_and_repo(
358
self.get_url('child'), format=format)
359
self.assertRaises(errors.NoRepositoryPresent,
360
branch.controldir.open_repository)
192
old_format = bzrdir.BzrDirFormat.get_default_format()
193
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
195
self.make_repository('.', shared=True)
196
branch = bzrdir.BzrDir.create_branch_and_repo(self.get_url('child'))
197
self.assertRaises(errors.NoRepositoryPresent,
198
branch.bzrdir.open_repository)
200
bzrdir.BzrDirFormat.set_default_format(old_format)
362
202
def test_create_branch_and_repo_under_shared_force_new(self):
363
# creating a branch and repo in a shared repo can be forced to
203
# creating a branch and repo in a shared repo can be forced to
364
204
# make a new repo
365
format = controldir.format_registry.make_controldir('knit')
366
self.make_repository('.', shared=True, format=format)
367
branch = bzrdir.BzrDir.create_branch_and_repo(self.get_url('child'),
370
branch.controldir.open_repository()
205
old_format = bzrdir.BzrDirFormat.get_default_format()
206
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
208
self.make_repository('.', shared=True)
209
branch = bzrdir.BzrDir.create_branch_and_repo(self.get_url('child'),
211
branch.bzrdir.open_repository()
213
bzrdir.BzrDirFormat.set_default_format(old_format)
372
215
def test_create_standalone_working_tree(self):
373
216
format = SampleBzrDirFormat()
374
# note this is deliberately readonly, as this failure should
375
# occur before any writes.
376
self.assertRaises(errors.NotLocalUrl,
377
bzrdir.BzrDir.create_standalone_workingtree,
378
self.get_readonly_url(), format=format)
379
tree = bzrdir.BzrDir.create_standalone_workingtree('.',
381
self.assertEqual('A tree', tree)
217
old_format = bzrdir.BzrDirFormat.get_default_format()
218
bzrdir.BzrDirFormat.set_default_format(format)
220
# note this is deliberately readonly, as this failure should
221
# occur before any writes.
222
self.assertRaises(errors.NotLocalUrl,
223
bzrdir.BzrDir.create_standalone_workingtree,
224
self.get_readonly_url())
225
tree = bzrdir.BzrDir.create_standalone_workingtree('.')
226
self.assertEqual('A tree', tree)
228
bzrdir.BzrDirFormat.set_default_format(old_format)
383
230
def test_create_standalone_working_tree_under_shared_repo(self):
384
231
# create standalone working tree always makes a repo.
385
format = controldir.format_registry.make_controldir('knit')
386
self.make_repository('.', shared=True, format=format)
387
# note this is deliberately readonly, as this failure should
388
# occur before any writes.
389
self.assertRaises(errors.NotLocalUrl,
390
bzrdir.BzrDir.create_standalone_workingtree,
391
self.get_readonly_url('child'), format=format)
392
tree = bzrdir.BzrDir.create_standalone_workingtree('child',
394
tree.controldir.open_repository()
232
old_format = bzrdir.BzrDirFormat.get_default_format()
233
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
235
self.make_repository('.', shared=True)
236
# note this is deliberately readonly, as this failure should
237
# occur before any writes.
238
self.assertRaises(errors.NotLocalUrl,
239
bzrdir.BzrDir.create_standalone_workingtree,
240
self.get_readonly_url('child'))
241
tree = bzrdir.BzrDir.create_standalone_workingtree('child')
242
tree.bzrdir.open_repository()
244
bzrdir.BzrDirFormat.set_default_format(old_format)
396
246
def test_create_branch_convenience(self):
397
247
# outside a repo the default convenience output is a repo+branch_tree
398
format = controldir.format_registry.make_controldir('knit')
399
branch = bzrdir.BzrDir.create_branch_convenience('.', format=format)
400
branch.controldir.open_workingtree()
401
branch.controldir.open_repository()
403
def test_create_branch_convenience_possible_transports(self):
404
"""Check that the optional 'possible_transports' is recognized"""
405
format = controldir.format_registry.make_controldir('knit')
406
t = self.get_transport()
407
branch = bzrdir.BzrDir.create_branch_convenience(
408
'.', format=format, possible_transports=[t])
409
branch.controldir.open_workingtree()
410
branch.controldir.open_repository()
412
def test_create_branch_convenience_root(self):
413
"""Creating a branch at the root of a fs should work."""
414
self.vfs_transport_factory = memory.MemoryServer
415
# outside a repo the default convenience output is a repo+branch_tree
416
format = controldir.format_registry.make_controldir('knit')
417
branch = bzrdir.BzrDir.create_branch_convenience(self.get_url(),
419
self.assertRaises(errors.NoWorkingTree,
420
branch.controldir.open_workingtree)
421
branch.controldir.open_repository()
248
old_format = bzrdir.BzrDirFormat.get_default_format()
249
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
251
branch = bzrdir.BzrDir.create_branch_convenience('.')
252
branch.bzrdir.open_workingtree()
253
branch.bzrdir.open_repository()
255
bzrdir.BzrDirFormat.set_default_format(old_format)
423
257
def test_create_branch_convenience_under_shared_repo(self):
424
258
# inside a repo the default convenience output is a branch+ follow the
425
259
# repo tree policy
426
format = controldir.format_registry.make_controldir('knit')
427
self.make_repository('.', shared=True, format=format)
428
branch = bzrdir.BzrDir.create_branch_convenience('child',
430
branch.controldir.open_workingtree()
431
self.assertRaises(errors.NoRepositoryPresent,
432
branch.controldir.open_repository)
260
old_format = bzrdir.BzrDirFormat.get_default_format()
261
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
263
self.make_repository('.', shared=True)
264
branch = bzrdir.BzrDir.create_branch_convenience('child')
265
branch.bzrdir.open_workingtree()
266
self.assertRaises(errors.NoRepositoryPresent,
267
branch.bzrdir.open_repository)
269
bzrdir.BzrDirFormat.set_default_format(old_format)
434
271
def test_create_branch_convenience_under_shared_repo_force_no_tree(self):
435
272
# inside a repo the default convenience output is a branch+ follow the
436
273
# repo tree policy but we can override that
437
format = controldir.format_registry.make_controldir('knit')
438
self.make_repository('.', shared=True, format=format)
439
branch = bzrdir.BzrDir.create_branch_convenience('child',
440
force_new_tree=False, format=format)
441
self.assertRaises(errors.NoWorkingTree,
442
branch.controldir.open_workingtree)
443
self.assertRaises(errors.NoRepositoryPresent,
444
branch.controldir.open_repository)
274
old_format = bzrdir.BzrDirFormat.get_default_format()
275
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
277
self.make_repository('.', shared=True)
278
branch = bzrdir.BzrDir.create_branch_convenience('child',
279
force_new_tree=False)
280
self.assertRaises(errors.NoWorkingTree,
281
branch.bzrdir.open_workingtree)
282
self.assertRaises(errors.NoRepositoryPresent,
283
branch.bzrdir.open_repository)
285
bzrdir.BzrDirFormat.set_default_format(old_format)
446
287
def test_create_branch_convenience_under_shared_repo_no_tree_policy(self):
447
288
# inside a repo the default convenience output is a branch+ follow the
448
289
# repo tree policy
449
format = controldir.format_registry.make_controldir('knit')
450
repo = self.make_repository('.', shared=True, format=format)
451
repo.set_make_working_trees(False)
452
branch = bzrdir.BzrDir.create_branch_convenience('child',
454
self.assertRaises(errors.NoWorkingTree,
455
branch.controldir.open_workingtree)
456
self.assertRaises(errors.NoRepositoryPresent,
457
branch.controldir.open_repository)
290
old_format = bzrdir.BzrDirFormat.get_default_format()
291
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
293
repo = self.make_repository('.', shared=True)
294
repo.set_make_working_trees(False)
295
branch = bzrdir.BzrDir.create_branch_convenience('child')
296
self.assertRaises(errors.NoWorkingTree,
297
branch.bzrdir.open_workingtree)
298
self.assertRaises(errors.NoRepositoryPresent,
299
branch.bzrdir.open_repository)
301
bzrdir.BzrDirFormat.set_default_format(old_format)
459
303
def test_create_branch_convenience_under_shared_repo_no_tree_policy_force_tree(self):
460
304
# inside a repo the default convenience output is a branch+ follow the
461
305
# repo tree policy but we can override that
462
format = controldir.format_registry.make_controldir('knit')
463
repo = self.make_repository('.', shared=True, format=format)
464
repo.set_make_working_trees(False)
465
branch = bzrdir.BzrDir.create_branch_convenience('child',
466
force_new_tree=True, format=format)
467
branch.controldir.open_workingtree()
468
self.assertRaises(errors.NoRepositoryPresent,
469
branch.controldir.open_repository)
306
old_format = bzrdir.BzrDirFormat.get_default_format()
307
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
309
repo = self.make_repository('.', shared=True)
310
repo.set_make_working_trees(False)
311
branch = bzrdir.BzrDir.create_branch_convenience('child',
313
branch.bzrdir.open_workingtree()
314
self.assertRaises(errors.NoRepositoryPresent,
315
branch.bzrdir.open_repository)
317
bzrdir.BzrDirFormat.set_default_format(old_format)
471
319
def test_create_branch_convenience_under_shared_repo_force_new_repo(self):
472
320
# inside a repo the default convenience output is overridable to give
473
321
# repo+branch+tree
474
format = controldir.format_registry.make_controldir('knit')
475
self.make_repository('.', shared=True, format=format)
476
branch = bzrdir.BzrDir.create_branch_convenience('child',
477
force_new_repo=True, format=format)
478
branch.controldir.open_repository()
479
branch.controldir.open_workingtree()
482
class TestRepositoryAcquisitionPolicy(TestCaseWithTransport):
484
def test_acquire_repository_standalone(self):
485
"""The default acquisition policy should create a standalone branch."""
486
my_bzrdir = self.make_controldir('.')
487
repo_policy = my_bzrdir.determine_repository_policy()
488
repo, is_new = repo_policy.acquire_repository()
489
self.assertEqual(repo.controldir.root_transport.base,
490
my_bzrdir.root_transport.base)
491
self.assertFalse(repo.is_shared())
493
def test_determine_stacking_policy(self):
494
parent_bzrdir = self.make_controldir('.')
495
child_bzrdir = self.make_controldir('child')
496
parent_bzrdir.get_config().set_default_stack_on('http://example.org')
497
repo_policy = child_bzrdir.determine_repository_policy()
498
self.assertEqual('http://example.org', repo_policy._stack_on)
500
def test_determine_stacking_policy_relative(self):
501
parent_bzrdir = self.make_controldir('.')
502
child_bzrdir = self.make_controldir('child')
503
parent_bzrdir.get_config().set_default_stack_on('child2')
504
repo_policy = child_bzrdir.determine_repository_policy()
505
self.assertEqual('child2', repo_policy._stack_on)
506
self.assertEqual(parent_bzrdir.root_transport.base,
507
repo_policy._stack_on_pwd)
509
def prepare_default_stacking(self, child_format='1.6'):
510
parent_bzrdir = self.make_controldir('.')
511
child_branch = self.make_branch('child', format=child_format)
512
parent_bzrdir.get_config().set_default_stack_on(child_branch.base)
513
new_child_transport = parent_bzrdir.transport.clone('child2')
514
return child_branch, new_child_transport
516
def test_clone_on_transport_obeys_stacking_policy(self):
517
child_branch, new_child_transport = self.prepare_default_stacking()
518
new_child = child_branch.controldir.clone_on_transport(
520
self.assertEqual(child_branch.base,
521
new_child.open_branch().get_stacked_on_url())
523
def test_default_stacking_with_stackable_branch_unstackable_repo(self):
524
# Make stackable source branch with an unstackable repo format.
525
source_bzrdir = self.make_controldir('source')
526
knitpack_repo.RepositoryFormatKnitPack1().initialize(source_bzrdir)
527
source_branch = breezy.bzr.branch.BzrBranchFormat7().initialize(
529
# Make a directory with a default stacking policy
530
parent_bzrdir = self.make_controldir('parent')
531
stacked_on = self.make_branch('parent/stacked-on', format='pack-0.92')
532
parent_bzrdir.get_config().set_default_stack_on(stacked_on.base)
533
# Clone source into directory
534
target = source_bzrdir.clone(self.get_url('parent/target'))
536
def test_format_initialize_on_transport_ex_stacked_on(self):
537
# trunk is a stackable format. Note that its in the same server area
538
# which is what launchpad does, but not sufficient to exercise the
540
trunk = self.make_branch('trunk', format='1.9')
541
t = self.get_transport('stacked')
542
old_fmt = controldir.format_registry.make_controldir('pack-0.92')
543
repo_name = old_fmt.repository_format.network_name()
544
# Should end up with a 1.9 format (stackable)
545
repo, control, require_stacking, repo_policy = \
546
old_fmt.initialize_on_transport_ex(t,
547
repo_format_name=repo_name, stacked_on='../trunk',
550
# Repositories are open write-locked
551
self.assertTrue(repo.is_write_locked())
552
self.addCleanup(repo.unlock)
554
repo = control.open_repository()
555
self.assertIsInstance(control, bzrdir.BzrDir)
556
opened = bzrdir.BzrDir.open(t.base)
557
if not isinstance(old_fmt, remote.RemoteBzrDirFormat):
558
self.assertEqual(control._format.network_name(),
559
old_fmt.network_name())
560
self.assertEqual(control._format.network_name(),
561
opened._format.network_name())
562
self.assertEqual(control.__class__, opened.__class__)
563
self.assertLength(1, repo._fallback_repositories)
565
def test_sprout_obeys_stacking_policy(self):
566
child_branch, new_child_transport = self.prepare_default_stacking()
567
new_child = child_branch.controldir.sprout(new_child_transport.base)
568
self.assertEqual(child_branch.base,
569
new_child.open_branch().get_stacked_on_url())
571
def test_clone_ignores_policy_for_unsupported_formats(self):
572
child_branch, new_child_transport = self.prepare_default_stacking(
573
child_format='pack-0.92')
574
new_child = child_branch.controldir.clone_on_transport(
576
self.assertRaises(branch.UnstackableBranchFormat,
577
new_child.open_branch().get_stacked_on_url)
579
def test_sprout_ignores_policy_for_unsupported_formats(self):
580
child_branch, new_child_transport = self.prepare_default_stacking(
581
child_format='pack-0.92')
582
new_child = child_branch.controldir.sprout(new_child_transport.base)
583
self.assertRaises(branch.UnstackableBranchFormat,
584
new_child.open_branch().get_stacked_on_url)
586
def test_sprout_upgrades_format_if_stacked_specified(self):
587
child_branch, new_child_transport = self.prepare_default_stacking(
588
child_format='pack-0.92')
589
new_child = child_branch.controldir.sprout(new_child_transport.base,
591
self.assertEqual(child_branch.controldir.root_transport.base,
592
new_child.open_branch().get_stacked_on_url())
593
repo = new_child.open_repository()
594
self.assertTrue(repo._format.supports_external_lookups)
595
self.assertFalse(repo.supports_rich_root())
597
def test_clone_on_transport_upgrades_format_if_stacked_on_specified(self):
598
child_branch, new_child_transport = self.prepare_default_stacking(
599
child_format='pack-0.92')
600
new_child = child_branch.controldir.clone_on_transport(new_child_transport,
601
stacked_on=child_branch.controldir.root_transport.base)
602
self.assertEqual(child_branch.controldir.root_transport.base,
603
new_child.open_branch().get_stacked_on_url())
604
repo = new_child.open_repository()
605
self.assertTrue(repo._format.supports_external_lookups)
606
self.assertFalse(repo.supports_rich_root())
608
def test_sprout_upgrades_to_rich_root_format_if_needed(self):
609
child_branch, new_child_transport = self.prepare_default_stacking(
610
child_format='rich-root-pack')
611
new_child = child_branch.controldir.sprout(new_child_transport.base,
613
repo = new_child.open_repository()
614
self.assertTrue(repo._format.supports_external_lookups)
615
self.assertTrue(repo.supports_rich_root())
617
def test_add_fallback_repo_handles_absolute_urls(self):
618
stack_on = self.make_branch('stack_on', format='1.6')
619
repo = self.make_repository('repo', format='1.6')
620
policy = bzrdir.UseExistingRepository(repo, stack_on.base)
621
policy._add_fallback(repo)
623
def test_add_fallback_repo_handles_relative_urls(self):
624
stack_on = self.make_branch('stack_on', format='1.6')
625
repo = self.make_repository('repo', format='1.6')
626
policy = bzrdir.UseExistingRepository(repo, '.', stack_on.base)
627
policy._add_fallback(repo)
629
def test_configure_relative_branch_stacking_url(self):
630
stack_on = self.make_branch('stack_on', format='1.6')
631
stacked = self.make_branch('stack_on/stacked', format='1.6')
632
policy = bzrdir.UseExistingRepository(stacked.repository,
634
policy.configure_branch(stacked)
635
self.assertEqual('..', stacked.get_stacked_on_url())
637
def test_relative_branch_stacking_to_absolute(self):
638
stack_on = self.make_branch('stack_on', format='1.6')
639
stacked = self.make_branch('stack_on/stacked', format='1.6')
640
policy = bzrdir.UseExistingRepository(stacked.repository,
641
'.', self.get_readonly_url('stack_on'))
642
policy.configure_branch(stacked)
643
self.assertEqual(self.get_readonly_url('stack_on'),
644
stacked.get_stacked_on_url())
322
old_format = bzrdir.BzrDirFormat.get_default_format()
323
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
325
self.make_repository('.', shared=True)
326
branch = bzrdir.BzrDir.create_branch_convenience('child',
328
branch.bzrdir.open_repository()
329
branch.bzrdir.open_workingtree()
331
bzrdir.BzrDirFormat.set_default_format(old_format)
647
334
class ChrootedTests(TestCaseWithTransport):
666
350
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing,
667
351
self.get_readonly_url('g/p/q'))
668
352
control = bzrdir.BzrDir.create(self.get_url())
669
branch, relpath = bzrdir.BzrDir.open_containing(
670
self.get_readonly_url(''))
353
branch, relpath = bzrdir.BzrDir.open_containing(self.get_readonly_url(''))
671
354
self.assertEqual('', relpath)
672
branch, relpath = bzrdir.BzrDir.open_containing(
673
self.get_readonly_url('g/p/q'))
355
branch, relpath = bzrdir.BzrDir.open_containing(self.get_readonly_url('g/p/q'))
674
356
self.assertEqual('g/p/q', relpath)
676
def test_open_containing_tree_branch_or_repository_empty(self):
677
self.assertRaises(errors.NotBranchError,
678
bzrdir.BzrDir.open_containing_tree_branch_or_repository,
679
self.get_readonly_url(''))
681
def test_open_containing_tree_branch_or_repository_all(self):
682
self.make_branch_and_tree('topdir')
683
tree, branch, repo, relpath = \
684
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
686
self.assertEqual(os.path.realpath('topdir'),
687
os.path.realpath(tree.basedir))
688
self.assertEqual(os.path.realpath('topdir'),
689
self.local_branch_path(branch))
691
osutils.realpath(os.path.join('topdir', '.bzr', 'repository')),
692
repo.controldir.transport.local_abspath('repository'))
693
self.assertEqual(relpath, 'foo')
695
def test_open_containing_tree_branch_or_repository_no_tree(self):
696
self.make_branch('branch')
697
tree, branch, repo, relpath = \
698
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
700
self.assertEqual(tree, None)
701
self.assertEqual(os.path.realpath('branch'),
702
self.local_branch_path(branch))
704
osutils.realpath(os.path.join('branch', '.bzr', 'repository')),
705
repo.controldir.transport.local_abspath('repository'))
706
self.assertEqual(relpath, 'foo')
708
def test_open_containing_tree_branch_or_repository_repo(self):
709
self.make_repository('repo')
710
tree, branch, repo, relpath = \
711
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
713
self.assertEqual(tree, None)
714
self.assertEqual(branch, None)
716
osutils.realpath(os.path.join('repo', '.bzr', 'repository')),
717
repo.controldir.transport.local_abspath('repository'))
718
self.assertEqual(relpath, '')
720
def test_open_containing_tree_branch_or_repository_shared_repo(self):
721
self.make_repository('shared', shared=True)
722
bzrdir.BzrDir.create_branch_convenience('shared/branch',
723
force_new_tree=False)
724
tree, branch, repo, relpath = \
725
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
727
self.assertEqual(tree, None)
728
self.assertEqual(os.path.realpath('shared/branch'),
729
self.local_branch_path(branch))
731
osutils.realpath(os.path.join('shared', '.bzr', 'repository')),
732
repo.controldir.transport.local_abspath('repository'))
733
self.assertEqual(relpath, '')
735
def test_open_containing_tree_branch_or_repository_branch_subdir(self):
736
self.make_branch_and_tree('foo')
737
self.build_tree(['foo/bar/'])
738
tree, branch, repo, relpath = \
739
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
741
self.assertEqual(os.path.realpath('foo'),
742
os.path.realpath(tree.basedir))
743
self.assertEqual(os.path.realpath('foo'),
744
self.local_branch_path(branch))
746
osutils.realpath(os.path.join('foo', '.bzr', 'repository')),
747
repo.controldir.transport.local_abspath('repository'))
748
self.assertEqual(relpath, 'bar')
750
def test_open_containing_tree_branch_or_repository_repo_subdir(self):
751
self.make_repository('bar')
752
self.build_tree(['bar/baz/'])
753
tree, branch, repo, relpath = \
754
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
756
self.assertEqual(tree, None)
757
self.assertEqual(branch, None)
759
osutils.realpath(os.path.join('bar', '.bzr', 'repository')),
760
repo.controldir.transport.local_abspath('repository'))
761
self.assertEqual(relpath, 'baz')
763
358
def test_open_containing_from_transport(self):
764
self.assertRaises(NotBranchError,
765
bzrdir.BzrDir.open_containing_from_transport,
766
_mod_transport.get_transport_from_url(self.get_readonly_url('')))
767
self.assertRaises(NotBranchError,
768
bzrdir.BzrDir.open_containing_from_transport,
769
_mod_transport.get_transport_from_url(
770
self.get_readonly_url('g/p/q')))
359
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing_from_transport,
360
get_transport(self.get_readonly_url('')))
361
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing_from_transport,
362
get_transport(self.get_readonly_url('g/p/q')))
771
363
control = bzrdir.BzrDir.create(self.get_url())
772
364
branch, relpath = bzrdir.BzrDir.open_containing_from_transport(
773
_mod_transport.get_transport_from_url(
774
self.get_readonly_url('')))
365
get_transport(self.get_readonly_url('')))
775
366
self.assertEqual('', relpath)
776
367
branch, relpath = bzrdir.BzrDir.open_containing_from_transport(
777
_mod_transport.get_transport_from_url(
778
self.get_readonly_url('g/p/q')))
368
get_transport(self.get_readonly_url('g/p/q')))
779
369
self.assertEqual('g/p/q', relpath)
781
def test_open_containing_tree_or_branch(self):
782
self.make_branch_and_tree('topdir')
783
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
785
self.assertEqual(os.path.realpath('topdir'),
786
os.path.realpath(tree.basedir))
787
self.assertEqual(os.path.realpath('topdir'),
788
self.local_branch_path(branch))
789
self.assertIs(tree.controldir, branch.controldir)
790
self.assertEqual('foo', relpath)
791
# opening from non-local should not return the tree
792
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
793
self.get_readonly_url('topdir/foo'))
794
self.assertEqual(None, tree)
795
self.assertEqual('foo', relpath)
797
self.make_branch('topdir/foo')
798
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
800
self.assertIs(tree, None)
801
self.assertEqual(os.path.realpath('topdir/foo'),
802
self.local_branch_path(branch))
803
self.assertEqual('', relpath)
805
def test_open_tree_or_branch(self):
806
self.make_branch_and_tree('topdir')
807
tree, branch = bzrdir.BzrDir.open_tree_or_branch('topdir')
808
self.assertEqual(os.path.realpath('topdir'),
809
os.path.realpath(tree.basedir))
810
self.assertEqual(os.path.realpath('topdir'),
811
self.local_branch_path(branch))
812
self.assertIs(tree.controldir, branch.controldir)
813
# opening from non-local should not return the tree
814
tree, branch = bzrdir.BzrDir.open_tree_or_branch(
815
self.get_readonly_url('topdir'))
816
self.assertEqual(None, tree)
818
self.make_branch('topdir/foo')
819
tree, branch = bzrdir.BzrDir.open_tree_or_branch('topdir/foo')
820
self.assertIs(tree, None)
821
self.assertEqual(os.path.realpath('topdir/foo'),
822
self.local_branch_path(branch))
824
def test_open_tree_or_branch_named(self):
825
tree = self.make_branch_and_tree('topdir')
828
bzrdir.BzrDir.open_tree_or_branch, 'topdir', name='missing')
829
tree.branch.controldir.create_branch('named')
830
tree, branch = bzrdir.BzrDir.open_tree_or_branch('topdir', name='named')
831
self.assertEqual(os.path.realpath('topdir'),
832
os.path.realpath(tree.basedir))
833
self.assertEqual(os.path.realpath('topdir'),
834
self.local_branch_path(branch))
835
self.assertEqual(branch.name, 'named')
836
self.assertIs(tree.controldir, branch.controldir)
838
def test_open_from_transport(self):
839
# transport pointing at bzrdir should give a bzrdir with root transport
840
# set to the given transport
841
control = bzrdir.BzrDir.create(self.get_url())
842
t = self.get_transport()
843
opened_bzrdir = bzrdir.BzrDir.open_from_transport(t)
844
self.assertEqual(t.base, opened_bzrdir.root_transport.base)
845
self.assertIsInstance(opened_bzrdir, bzrdir.BzrDir)
847
def test_open_from_transport_no_bzrdir(self):
848
t = self.get_transport()
849
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport, t)
851
def test_open_from_transport_bzrdir_in_parent(self):
852
control = bzrdir.BzrDir.create(self.get_url())
853
t = self.get_transport()
855
t = t.clone('subdir')
856
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport, t)
858
def test_sprout_recursive(self):
859
tree = self.make_branch_and_tree('tree1')
860
sub_tree = self.make_branch_and_tree('tree1/subtree')
861
sub_tree.set_root_id(b'subtree-root')
862
tree.add_reference(sub_tree)
863
tree.set_reference_info('subtree', sub_tree.branch.user_url)
864
self.build_tree(['tree1/subtree/file'])
866
tree.commit('Initial commit')
867
tree2 = tree.controldir.sprout('tree2').open_workingtree()
869
self.addCleanup(tree2.unlock)
870
self.assertPathExists('tree2/subtree/file')
871
self.assertEqual('tree-reference', tree2.kind('subtree'))
873
def test_cloning_metadir(self):
874
"""Ensure that cloning metadir is suitable"""
875
bzrdir = self.make_controldir('bzrdir')
876
bzrdir.cloning_metadir()
877
branch = self.make_branch('branch', format='knit')
878
format = branch.controldir.cloning_metadir()
879
self.assertIsInstance(format.workingtree_format,
880
workingtree_4.WorkingTreeFormat6)
882
def test_sprout_recursive_treeless(self):
883
tree = self.make_branch_and_tree('tree1',
884
format='development-subtree')
885
sub_tree = self.make_branch_and_tree('tree1/subtree',
886
format='development-subtree')
887
tree.add_reference(sub_tree)
888
tree.set_reference_info('subtree', sub_tree.branch.user_url)
889
self.build_tree(['tree1/subtree/file'])
891
tree.commit('Initial commit')
892
# The following line force the orhaning to reveal bug #634470
893
tree.branch.get_config_stack().set('transform.orphan_policy', 'move')
894
tree.controldir.destroy_workingtree()
895
# FIXME: subtree/.bzr is left here which allows the test to pass (or
896
# fail :-( ) -- vila 20100909
897
repo = self.make_repository('repo', shared=True,
898
format='development-subtree')
899
repo.set_make_working_trees(False)
900
# FIXME: we just deleted the workingtree and now we want to use it ????
901
# At a minimum, we should use tree.branch below (but this fails too
902
# currently) or stop calling this test 'treeless'. Specifically, I've
903
# turn the line below into an assertRaises when 'subtree/.bzr' is
904
# orphaned and sprout tries to access the branch there (which is left
905
# by bzrdir.BzrDirMeta1.destroy_workingtree when it ignores the
906
# [DeletingParent('Not deleting', u'subtree', None)] conflict). See bug
907
# #634470. -- vila 20100909
908
tree.controldir.sprout('repo/tree2')
909
self.assertPathExists('repo/tree2/subtree')
910
self.assertPathDoesNotExist('repo/tree2/subtree/file')
912
def make_foo_bar_baz(self):
913
foo = bzrdir.BzrDir.create_branch_convenience('foo').controldir
914
bar = self.make_branch('foo/bar').controldir
915
baz = self.make_branch('baz').controldir
918
def test_find_controldirs(self):
919
foo, bar, baz = self.make_foo_bar_baz()
920
t = self.get_transport()
921
self.assertEqualBzrdirs(
922
[baz, foo, bar], bzrdir.BzrDir.find_controldirs(t))
924
def make_fake_permission_denied_transport(self, transport, paths):
925
"""Create a transport that raises PermissionDenied for some paths."""
928
raise errors.PermissionDenied(path)
930
path_filter_server = pathfilter.PathFilteringServer(transport, filter)
931
path_filter_server.start_server()
932
self.addCleanup(path_filter_server.stop_server)
933
path_filter_transport = pathfilter.PathFilteringTransport(
934
path_filter_server, '.')
935
return (path_filter_server, path_filter_transport)
937
def assertBranchUrlsEndWith(self, expect_url_suffix, actual_bzrdirs):
938
"""Check that each branch url ends with the given suffix."""
939
for actual_bzrdir in actual_bzrdirs:
940
self.assertEndsWith(actual_bzrdir.user_url, expect_url_suffix)
942
def test_find_controldirs_permission_denied(self):
943
foo, bar, baz = self.make_foo_bar_baz()
944
t = self.get_transport()
945
path_filter_server, path_filter_transport = \
946
self.make_fake_permission_denied_transport(t, ['foo'])
948
self.assertBranchUrlsEndWith('/baz/',
949
bzrdir.BzrDir.find_controldirs(path_filter_transport))
951
smart_transport = self.make_smart_server('.',
952
backing_server=path_filter_server)
953
self.assertBranchUrlsEndWith('/baz/',
954
bzrdir.BzrDir.find_controldirs(smart_transport))
956
def test_find_controldirs_list_current(self):
957
def list_current(transport):
958
return [s for s in transport.list_dir('') if s != 'baz']
960
foo, bar, baz = self.make_foo_bar_baz()
961
t = self.get_transport()
962
self.assertEqualBzrdirs(
964
bzrdir.BzrDir.find_controldirs(t, list_current=list_current))
966
def test_find_controldirs_evaluate(self):
967
def evaluate(bzrdir):
969
repo = bzrdir.open_repository()
970
except errors.NoRepositoryPresent:
971
return True, bzrdir.root_transport.base
973
return False, bzrdir.root_transport.base
975
foo, bar, baz = self.make_foo_bar_baz()
976
t = self.get_transport()
977
self.assertEqual([baz.root_transport.base, foo.root_transport.base],
978
list(bzrdir.BzrDir.find_controldirs(t, evaluate=evaluate)))
980
def assertEqualBzrdirs(self, first, second):
982
second = list(second)
983
self.assertEqual(len(first), len(second))
984
for x, y in zip(first, second):
985
self.assertEqual(x.root_transport.base, y.root_transport.base)
987
def test_find_branches(self):
988
root = self.make_repository('', shared=True)
989
foo, bar, baz = self.make_foo_bar_baz()
990
qux = self.make_controldir('foo/qux')
991
t = self.get_transport()
992
branches = bzrdir.BzrDir.find_branches(t)
993
self.assertEqual(baz.root_transport.base, branches[0].base)
994
self.assertEqual(foo.root_transport.base, branches[1].base)
995
self.assertEqual(bar.root_transport.base, branches[2].base)
997
# ensure this works without a top-level repo
998
branches = bzrdir.BzrDir.find_branches(t.clone('foo'))
999
self.assertEqual(foo.root_transport.base, branches[0].base)
1000
self.assertEqual(bar.root_transport.base, branches[1].base)
1003
class TestMissingRepoBranchesSkipped(TestCaseWithMemoryTransport):
1005
def test_find_controldirs_missing_repo(self):
1006
t = self.get_transport()
1007
arepo = self.make_repository('arepo', shared=True)
1008
abranch_url = arepo.user_url + '/abranch'
1009
abranch = bzrdir.BzrDir.create(abranch_url).create_branch()
1010
t.delete_tree('arepo/.bzr')
1011
self.assertRaises(errors.NoRepositoryPresent,
1012
branch.Branch.open, abranch_url)
1013
self.make_branch('baz')
1014
for actual_bzrdir in bzrdir.BzrDir.find_branches(t):
1015
self.assertEndsWith(actual_bzrdir.user_url, '/baz/')
1018
372
class TestMeta1DirFormat(TestCaseWithTransport):
1019
373
"""Tests specific to the meta1 dir format."""
1043
394
t = dir.transport
1044
395
self.assertIsDirectory('branch-lock', t)
1046
def test_comparison(self):
1047
"""Equality and inequality behave properly.
1049
Metadirs should compare equal iff they have the same repo, branch and
1052
mydir = controldir.format_registry.make_controldir('knit')
1053
self.assertEqual(mydir, mydir)
1054
self.assertFalse(mydir != mydir)
1055
otherdir = controldir.format_registry.make_controldir('knit')
1056
self.assertEqual(otherdir, mydir)
1057
self.assertFalse(otherdir != mydir)
1058
otherdir2 = controldir.format_registry.make_controldir(
1059
'development-subtree')
1060
self.assertNotEqual(otherdir2, mydir)
1061
self.assertFalse(otherdir2 == mydir)
1063
def test_with_features(self):
1064
tree = self.make_branch_and_tree('tree', format='2a')
1065
tree.controldir.update_feature_flags({b"bar": b"required"})
1066
self.assertRaises(bzrdir.MissingFeature, bzrdir.BzrDir.open, 'tree')
1067
bzrdir.BzrDirMetaFormat1.register_feature(b'bar')
1068
self.addCleanup(bzrdir.BzrDirMetaFormat1.unregister_feature, b'bar')
1069
dir = bzrdir.BzrDir.open('tree')
1070
self.assertEqual(b"required", dir._format.features.get(b"bar"))
1071
tree.controldir.update_feature_flags({
1073
b"nonexistant": None})
1074
dir = bzrdir.BzrDir.open('tree')
1075
self.assertEqual({}, dir._format.features)
1077
def test_needs_conversion_different_working_tree(self):
1078
# meta1dirs need an conversion if any element is not the default.
1079
new_format = controldir.format_registry.make_controldir('dirstate')
1080
tree = self.make_branch_and_tree('tree', format='knit')
1081
self.assertTrue(tree.controldir.needs_format_conversion(
1084
def test_initialize_on_format_uses_smart_transport(self):
1085
self.setup_smart_server_with_call_log()
1086
new_format = controldir.format_registry.make_controldir('dirstate')
1087
transport = self.get_transport('target')
1088
transport.ensure_base()
1089
self.reset_smart_call_log()
1090
instance = new_format.initialize_on_transport(transport)
1091
self.assertIsInstance(instance, remote.RemoteBzrDir)
1092
rpc_count = len(self.hpss_calls)
1093
# This figure represent the amount of work to perform this use case. It
1094
# is entirely ok to reduce this number if a test fails due to rpc_count
1095
# being too low. If rpc_count increases, more network roundtrips have
1096
# become necessary for this use case. Please do not adjust this number
1097
# upwards without agreement from bzr's network support maintainers.
1098
self.assertEqual(2, rpc_count)
398
class TestFormat5(TestCaseWithTransport):
399
"""Tests specific to the version 5 bzrdir format."""
401
def test_same_lockfiles_between_tree_repo_branch(self):
402
# this checks that only a single lockfiles instance is created
403
# for format 5 objects
404
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
405
def check_dir_components_use_same_lock(dir):
406
ctrl_1 = dir.open_repository().control_files
407
ctrl_2 = dir.open_branch().control_files
408
ctrl_3 = dir.open_workingtree()._control_files
409
self.assertTrue(ctrl_1 is ctrl_2)
410
self.assertTrue(ctrl_2 is ctrl_3)
411
check_dir_components_use_same_lock(dir)
412
# and if we open it normally.
413
dir = bzrdir.BzrDir.open(self.get_url())
414
check_dir_components_use_same_lock(dir)
416
def test_can_convert(self):
417
# format 5 dirs are convertable
418
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
419
self.assertTrue(dir.can_convert_format())
421
def test_needs_conversion(self):
422
# format 5 dirs need a conversion if they are not the default.
423
# and they start of not the default.
424
old_format = bzrdir.BzrDirFormat.get_default_format()
425
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirFormat5())
427
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
428
self.assertFalse(dir.needs_format_conversion())
430
bzrdir.BzrDirFormat.set_default_format(old_format)
431
self.assertTrue(dir.needs_format_conversion())
434
class TestFormat6(TestCaseWithTransport):
435
"""Tests specific to the version 6 bzrdir format."""
437
def test_same_lockfiles_between_tree_repo_branch(self):
438
# this checks that only a single lockfiles instance is created
439
# for format 6 objects
440
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
441
def check_dir_components_use_same_lock(dir):
442
ctrl_1 = dir.open_repository().control_files
443
ctrl_2 = dir.open_branch().control_files
444
ctrl_3 = dir.open_workingtree()._control_files
445
self.assertTrue(ctrl_1 is ctrl_2)
446
self.assertTrue(ctrl_2 is ctrl_3)
447
check_dir_components_use_same_lock(dir)
448
# and if we open it normally.
449
dir = bzrdir.BzrDir.open(self.get_url())
450
check_dir_components_use_same_lock(dir)
452
def test_can_convert(self):
453
# format 6 dirs are convertable
454
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
455
self.assertTrue(dir.can_convert_format())
457
def test_needs_conversion(self):
458
# format 6 dirs need an conversion if they are not the default.
459
old_format = bzrdir.BzrDirFormat.get_default_format()
460
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
462
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
463
self.assertTrue(dir.needs_format_conversion())
465
bzrdir.BzrDirFormat.set_default_format(old_format)
1101
468
class NonLocalTests(TestCaseWithTransport):
1104
471
def setUp(self):
1105
472
super(NonLocalTests, self).setUp()
1106
self.vfs_transport_factory = memory.MemoryServer
473
self.transport_server = MemoryServer
1108
475
def test_create_branch_convenience(self):
1109
476
# outside a repo the default convenience output is a repo+branch_tree
1110
format = controldir.format_registry.make_controldir('knit')
1111
branch = bzrdir.BzrDir.create_branch_convenience(
1112
self.get_url('foo'), format=format)
1113
self.assertRaises(errors.NoWorkingTree,
1114
branch.controldir.open_workingtree)
1115
branch.controldir.open_repository()
477
old_format = bzrdir.BzrDirFormat.get_default_format()
478
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
480
branch = bzrdir.BzrDir.create_branch_convenience(self.get_url('foo'))
481
self.assertRaises(errors.NoWorkingTree,
482
branch.bzrdir.open_workingtree)
483
branch.bzrdir.open_repository()
485
bzrdir.BzrDirFormat.set_default_format(old_format)
1117
487
def test_create_branch_convenience_force_tree_not_local_fails(self):
1118
488
# outside a repo the default convenience output is a repo+branch_tree
1119
format = controldir.format_registry.make_controldir('knit')
1120
self.assertRaises(errors.NotLocalUrl,
1121
bzrdir.BzrDir.create_branch_convenience,
1122
self.get_url('foo'),
1123
force_new_tree=True,
1125
t = self.get_transport()
1126
self.assertFalse(t.has('foo'))
489
old_format = bzrdir.BzrDirFormat.get_default_format()
490
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
492
self.assertRaises(errors.NotLocalUrl,
493
bzrdir.BzrDir.create_branch_convenience,
496
t = get_transport(self.get_url('.'))
497
self.assertFalse(t.has('foo'))
499
bzrdir.BzrDirFormat.set_default_format(old_format)
1128
501
def test_clone(self):
1129
502
# clone into a nonlocal path works
1130
format = controldir.format_registry.make_controldir('knit')
1131
branch = bzrdir.BzrDir.create_branch_convenience('local',
1133
branch.controldir.open_workingtree()
1134
result = branch.controldir.clone(self.get_url('remote'))
503
old_format = bzrdir.BzrDirFormat.get_default_format()
504
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
506
branch = bzrdir.BzrDir.create_branch_convenience('local')
508
bzrdir.BzrDirFormat.set_default_format(old_format)
509
branch.bzrdir.open_workingtree()
510
result = branch.bzrdir.clone(self.get_url('remote'))
1135
511
self.assertRaises(errors.NoWorkingTree,
1136
512
result.open_workingtree)
1137
513
result.open_branch()
1138
514
result.open_repository()
1140
def test_checkout_metadir(self):
1141
# checkout_metadir has reasonable working tree format even when no
1142
# working tree is present
1143
self.make_branch('branch-knit2', format='dirstate-with-subtree')
1144
my_bzrdir = bzrdir.BzrDir.open(self.get_url('branch-knit2'))
1145
checkout_format = my_bzrdir.checkout_metadir()
1146
self.assertIsInstance(checkout_format.workingtree_format,
1147
workingtree_4.WorkingTreeFormat4)
1150
class TestHTTPRedirectionsBase(object):
1151
"""Test redirection between two http servers.
1153
This MUST be used by daughter classes that also inherit from
1154
TestCaseWithTwoWebservers.
1156
We can't inherit directly from TestCaseWithTwoWebservers or the
1157
test framework will try to create an instance which cannot
1158
run, its implementation being incomplete.
1161
def create_transport_readonly_server(self):
1162
# We don't set the http protocol version, relying on the default
1163
return http_utils.HTTPServerRedirecting()
1165
def create_transport_secondary_server(self):
1166
# We don't set the http protocol version, relying on the default
1167
return http_utils.HTTPServerRedirecting()
1170
super(TestHTTPRedirectionsBase, self).setUp()
1171
# The redirections will point to the new server
1172
self.new_server = self.get_readonly_server()
1173
# The requests to the old server will be redirected
1174
self.old_server = self.get_secondary_server()
1175
# Configure the redirections
1176
self.old_server.redirect_to(self.new_server.host, self.new_server.port)
1178
def test_loop(self):
1179
# Both servers redirect to each other creating a loop
1180
self.new_server.redirect_to(self.old_server.host, self.old_server.port)
1181
# Starting from either server should loop
1182
old_url = self._qualified_url(self.old_server.host,
1183
self.old_server.port)
1184
oldt = self._transport(old_url)
1185
self.assertRaises(errors.NotBranchError,
1186
bzrdir.BzrDir.open_from_transport, oldt)
1187
new_url = self._qualified_url(self.new_server.host,
1188
self.new_server.port)
1189
newt = self._transport(new_url)
1190
self.assertRaises(errors.NotBranchError,
1191
bzrdir.BzrDir.open_from_transport, newt)
1193
def test_qualifier_preserved(self):
1194
wt = self.make_branch_and_tree('branch')
1195
old_url = self._qualified_url(self.old_server.host,
1196
self.old_server.port)
1197
start = self._transport(old_url).clone('branch')
1198
bdir = bzrdir.BzrDir.open_from_transport(start)
1199
# Redirection should preserve the qualifier, hence the transport class
1201
self.assertIsInstance(bdir.root_transport, type(start))
1204
class TestHTTPRedirections(TestHTTPRedirectionsBase,
1205
http_utils.TestCaseWithTwoWebservers):
1206
"""Tests redirections for urllib implementation"""
1208
_transport = HttpTransport
1210
def _qualified_url(self, host, port):
1211
result = 'http://%s:%s' % (host, port)
1212
self.permit_url(result)
1216
class TestHTTPRedirections_nosmart(TestHTTPRedirectionsBase,
1217
http_utils.TestCaseWithTwoWebservers):
1218
"""Tests redirections for the nosmart decorator"""
1220
_transport = NoSmartTransportDecorator
1222
def _qualified_url(self, host, port):
1223
result = 'nosmart+http://%s:%s' % (host, port)
1224
self.permit_url(result)
1228
class TestHTTPRedirections_readonly(TestHTTPRedirectionsBase,
1229
http_utils.TestCaseWithTwoWebservers):
1230
"""Tests redirections for readonly decoratror"""
1232
_transport = ReadonlyTransportDecorator
1234
def _qualified_url(self, host, port):
1235
result = 'readonly+http://%s:%s' % (host, port)
1236
self.permit_url(result)
1240
class TestDotBzrHidden(TestCaseWithTransport):
1243
if sys.platform == 'win32':
1244
ls = [os.environ['COMSPEC'], '/C', 'dir', '/B']
1247
f = subprocess.Popen(self.ls, stdout=subprocess.PIPE,
1248
stderr=subprocess.PIPE)
1249
out, err = f.communicate()
1250
self.assertEqual(0, f.returncode, 'Calling %s failed: %s'
1252
return out.splitlines()
1254
def test_dot_bzr_hidden(self):
1255
b = bzrdir.BzrDir.create('.')
1256
self.build_tree(['a'])
1257
self.assertEqual([b'a'], self.get_ls())
1259
def test_dot_bzr_hidden_with_url(self):
1260
b = bzrdir.BzrDir.create(urlutils.local_path_to_url('.'))
1261
self.build_tree(['a'])
1262
self.assertEqual([b'a'], self.get_ls())
1265
class _TestBzrDirFormat(bzrdir.BzrDirMetaFormat1):
1266
"""Test BzrDirFormat implementation for TestBzrDirSprout."""
1268
def _open(self, transport):
1269
return _TestBzrDir(transport, self)
1272
class _TestBzrDir(bzrdir.BzrDirMeta1):
1273
"""Test BzrDir implementation for TestBzrDirSprout.
1275
When created a _TestBzrDir already has repository and a branch. The branch
1276
is a test double as well.
1279
def __init__(self, *args, **kwargs):
1280
super(_TestBzrDir, self).__init__(*args, **kwargs)
1281
self.test_branch = _TestBranch(self.transport)
1282
self.test_branch.repository = self.create_repository()
1284
def open_branch(self, unsupported=False, possible_transports=None):
1285
return self.test_branch
1287
def cloning_metadir(self, require_stacking=False):
1288
return _TestBzrDirFormat()
1291
class _TestBranchFormat(breezy.branch.BranchFormat):
1292
"""Test Branch format for TestBzrDirSprout."""
1295
class _TestBranch(breezy.branch.Branch):
1296
"""Test Branch implementation for TestBzrDirSprout."""
1298
def __init__(self, transport, *args, **kwargs):
1299
self._format = _TestBranchFormat()
1300
self._transport = transport
1301
self.base = transport.base
1302
super(_TestBranch, self).__init__(*args, **kwargs)
1306
def sprout(self, *args, **kwargs):
1307
self.calls.append('sprout')
1308
return _TestBranch(self._transport)
1310
def copy_content_into(self, destination, revision_id=None):
1311
self.calls.append('copy_content_into')
1313
def last_revision(self):
1314
return _mod_revision.NULL_REVISION
1316
def get_parent(self):
1319
def _get_config(self):
1320
return config.TransportConfig(self._transport, 'branch.conf')
1322
def _get_config_store(self):
1323
return config.BranchStore(self)
1325
def set_parent(self, parent):
1326
self._parent = parent
1328
def lock_read(self):
1329
return lock.LogicalLockResult(self.unlock)
1335
class TestBzrDirSprout(TestCaseWithMemoryTransport):
1337
def test_sprout_uses_branch_sprout(self):
1338
"""BzrDir.sprout calls Branch.sprout.
1340
Usually, BzrDir.sprout should delegate to the branch's sprout method
1341
for part of the work. This allows the source branch to control the
1342
choice of format for the new branch.
1344
There are exceptions, but this tests avoids them:
1345
- if there's no branch in the source bzrdir,
1346
- or if the stacking has been requested and the format needs to be
1347
overridden to satisfy that.
1349
# Make an instrumented bzrdir.
1350
t = self.get_transport('source')
1352
source_bzrdir = _TestBzrDirFormat().initialize_on_transport(t)
1353
# The instrumented bzrdir has a test_branch attribute that logs calls
1354
# made to the branch contained in that bzrdir. Initially the test
1355
# branch exists but no calls have been made to it.
1356
self.assertEqual([], source_bzrdir.test_branch.calls)
1359
target_url = self.get_url('target')
1360
result = source_bzrdir.sprout(target_url, recurse='no')
1362
# The bzrdir called the branch's sprout method.
1363
self.assertSubset(['sprout'], source_bzrdir.test_branch.calls)
1365
def test_sprout_parent(self):
1366
grandparent_tree = self.make_branch('grandparent')
1367
parent = grandparent_tree.controldir.sprout('parent').open_branch()
1368
branch_tree = parent.controldir.sprout('branch').open_branch()
1369
self.assertContainsRe(branch_tree.get_parent(), '/parent/$')
1372
class TestBzrDirHooks(TestCaseWithMemoryTransport):
1374
def test_pre_open_called(self):
1376
bzrdir.BzrDir.hooks.install_named_hook('pre_open', calls.append, None)
1377
transport = self.get_transport('foo')
1378
url = transport.base
1379
self.assertRaises(errors.NotBranchError, bzrdir.BzrDir.open, url)
1380
self.assertEqual([transport.base], [t.base for t in calls])
1382
def test_pre_open_actual_exceptions_raised(self):
1385
def fail_once(transport):
1388
raise errors.BzrError("fail")
1389
bzrdir.BzrDir.hooks.install_named_hook('pre_open', fail_once, None)
1390
transport = self.get_transport('foo')
1391
url = transport.base
1392
err = self.assertRaises(errors.BzrError, bzrdir.BzrDir.open, url)
1393
self.assertEqual('fail', err._preformatted_string)
1395
def test_post_repo_init(self):
1396
from ..controldir import RepoInitHookParams
1398
bzrdir.BzrDir.hooks.install_named_hook('post_repo_init',
1400
self.make_repository('foo')
1401
self.assertLength(1, calls)
1403
self.assertIsInstance(params, RepoInitHookParams)
1404
self.assertTrue(hasattr(params, 'controldir'))
1405
self.assertTrue(hasattr(params, 'repository'))
1407
def test_post_repo_init_hook_repr(self):
1409
bzrdir.BzrDir.hooks.install_named_hook('post_repo_init',
1410
lambda params: param_reprs.append(repr(params)), None)
1411
self.make_repository('foo')
1412
self.assertLength(1, param_reprs)
1413
param_repr = param_reprs[0]
1414
self.assertStartsWith(param_repr, '<RepoInitHookParams for ')
1417
class TestGenerateBackupName(TestCaseWithMemoryTransport):
1418
# FIXME: This may need to be unified with test_osutils.TestBackupNames or
1419
# moved to per_bzrdir or per_transport for better coverage ?
1423
super(TestGenerateBackupName, self).setUp()
1424
self._transport = self.get_transport()
1425
bzrdir.BzrDir.create(self.get_url(),
1426
possible_transports=[self._transport])
1427
self._bzrdir = bzrdir.BzrDir.open_from_transport(self._transport)
1430
self.assertEqual("a.~1~", self._bzrdir._available_backup_name("a"))
1432
def test_exiting(self):
1433
self._transport.put_bytes("a.~1~", b"some content")
1434
self.assertEqual("a.~2~", self._bzrdir._available_backup_name("a"))
1437
class TestMeta1DirColoFormat(TestCaseWithTransport):
1438
"""Tests specific to the meta1 dir with colocated branches format."""
1440
def test_supports_colo(self):
1441
format = bzrdir.BzrDirMetaFormat1Colo()
1442
self.assertTrue(format.colocated_branches)
1444
def test_upgrade_from_2a(self):
1445
tree = self.make_branch_and_tree('.', format='2a')
1446
format = bzrdir.BzrDirMetaFormat1Colo()
1447
self.assertTrue(tree.controldir.needs_format_conversion(format))
1448
converter = tree.controldir._format.get_converter(format)
1449
result = converter.convert(tree.controldir, None)
1450
self.assertIsInstance(result._format, bzrdir.BzrDirMetaFormat1Colo)
1451
self.assertFalse(result.needs_format_conversion(format))
1453
def test_downgrade_to_2a(self):
1454
tree = self.make_branch_and_tree('.', format='development-colo')
1455
format = bzrdir.BzrDirMetaFormat1()
1456
self.assertTrue(tree.controldir.needs_format_conversion(format))
1457
converter = tree.controldir._format.get_converter(format)
1458
result = converter.convert(tree.controldir, None)
1459
self.assertIsInstance(result._format, bzrdir.BzrDirMetaFormat1)
1460
self.assertFalse(result.needs_format_conversion(format))
1462
def test_downgrade_to_2a_too_many_branches(self):
1463
tree = self.make_branch_and_tree('.', format='development-colo')
1464
tree.controldir.create_branch(name="another-colocated-branch")
1465
converter = tree.controldir._format.get_converter(
1466
bzrdir.BzrDirMetaFormat1())
1467
result = converter.convert(tree.controldir, bzrdir.BzrDirMetaFormat1())
1468
self.assertIsInstance(result._format, bzrdir.BzrDirMetaFormat1)
1470
def test_nested(self):
1471
tree = self.make_branch_and_tree('.', format='development-colo')
1472
tree.controldir.create_branch(name='foo')
1473
tree.controldir.create_branch(name='fool/bla')
1475
errors.ParentBranchExists, tree.controldir.create_branch,
1478
def test_parent(self):
1479
tree = self.make_branch_and_tree('.', format='development-colo')
1480
tree.controldir.create_branch(name='fool/bla')
1481
tree.controldir.create_branch(name='foo/bar')
1483
errors.AlreadyBranchError, tree.controldir.create_branch,
1486
def test_supports_relative_reference(self):
1487
tree = self.make_branch_and_tree('.', format='development-colo')
1488
target1 = tree.controldir.create_branch(name='target1')
1489
target2 = tree.controldir.create_branch(name='target2')
1490
source = tree.controldir.set_branch_reference(target1, name='source')
1492
target1.user_url, tree.controldir.open_branch('source').user_url)
1493
source.controldir.get_branch_transport(None, 'source').put_bytes(
1494
'location', b'file:,branch=target2')
1496
target2.user_url, tree.controldir.open_branch('source').user_url)
1499
class SampleBzrFormat(bzrdir.BzrFormat):
1502
def get_format_string(cls):
1503
return b"First line\n"
1506
class TestBzrFormat(TestCase):
1507
"""Tests for BzrFormat."""
1509
def test_as_string(self):
1510
format = SampleBzrFormat()
1511
format.features = {b"foo": b"required"}
1512
self.assertEqual(format.as_string(),
1515
format.features[b"another"] = b"optional"
1516
self.assertEqual(format.as_string(),
1518
b"optional another\n"
1521
def test_network_name(self):
1522
# The network string should include the feature info
1523
format = SampleBzrFormat()
1524
format.features = {b"foo": b"required"}
1526
b"First line\nrequired foo\n",
1527
format.network_name())
1529
def test_from_string_no_features(self):
1531
format = SampleBzrFormat.from_string(
1533
self.assertEqual({}, format.features)
1535
def test_from_string_with_feature(self):
1537
format = SampleBzrFormat.from_string(
1538
b"First line\nrequired foo\n")
1539
self.assertEqual(b"required", format.features.get(b"foo"))
1541
def test_from_string_format_string_mismatch(self):
1542
# The first line has to match the format string
1543
self.assertRaises(AssertionError, SampleBzrFormat.from_string,
1544
b"Second line\nrequired foo\n")
1546
def test_from_string_missing_space(self):
1547
# At least one space is required in the feature lines
1548
self.assertRaises(errors.ParseFormatError, SampleBzrFormat.from_string,
1549
b"First line\nfoo\n")
1551
def test_from_string_with_spaces(self):
1552
# Feature with spaces (in case we add stuff like this in the future)
1553
format = SampleBzrFormat.from_string(
1554
b"First line\nrequired foo with spaces\n")
1555
self.assertEqual(b"required", format.features.get(b"foo with spaces"))
1558
format1 = SampleBzrFormat()
1559
format1.features = {b"nested-trees": b"optional"}
1560
format2 = SampleBzrFormat()
1561
format2.features = {b"nested-trees": b"optional"}
1562
self.assertEqual(format1, format1)
1563
self.assertEqual(format1, format2)
1564
format3 = SampleBzrFormat()
1565
self.assertNotEqual(format1, format3)
1567
def test_check_support_status_optional(self):
1568
# Optional, so silently ignore
1569
format = SampleBzrFormat()
1570
format.features = {b"nested-trees": b"optional"}
1571
format.check_support_status(True)
1572
self.addCleanup(SampleBzrFormat.unregister_feature, b"nested-trees")
1573
SampleBzrFormat.register_feature(b"nested-trees")
1574
format.check_support_status(True)
1576
def test_check_support_status_required(self):
1577
# Optional, so trigger an exception
1578
format = SampleBzrFormat()
1579
format.features = {b"nested-trees": b"required"}
1580
self.assertRaises(bzrdir.MissingFeature, format.check_support_status,
1582
self.addCleanup(SampleBzrFormat.unregister_feature, b"nested-trees")
1583
SampleBzrFormat.register_feature(b"nested-trees")
1584
format.check_support_status(True)
1586
def test_check_support_status_unknown(self):
1587
# treat unknown necessity as required
1588
format = SampleBzrFormat()
1589
format.features = {b"nested-trees": b"unknown"}
1590
self.assertRaises(bzrdir.MissingFeature, format.check_support_status,
1592
self.addCleanup(SampleBzrFormat.unregister_feature, b"nested-trees")
1593
SampleBzrFormat.register_feature(b"nested-trees")
1594
format.check_support_status(True)
1596
def test_feature_already_registered(self):
1597
# a feature can only be registered once
1598
self.addCleanup(SampleBzrFormat.unregister_feature, b"nested-trees")
1599
SampleBzrFormat.register_feature(b"nested-trees")
1600
self.assertRaises(bzrdir.FeatureAlreadyRegistered,
1601
SampleBzrFormat.register_feature, b"nested-trees")
1603
def test_feature_with_space(self):
1604
# spaces are not allowed in feature names
1605
self.assertRaises(ValueError, SampleBzrFormat.register_feature,