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