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