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
topics.register('formats', self.make_format_registry().help_topic,
145
topic = topics.get_detail('formats')
146
new, rest = topic.split('Experimental formats')
147
experimental, deprecated = rest.split('Deprecated formats')
148
self.assertContainsRe(new, 'These formats can be used')
149
self.assertContainsRe(new,
150
':knit:\n \(native\) \(default\) Format using knits\n')
151
self.assertContainsRe(experimental,
152
':branch6:\n \(native\) Experimental successor to knit')
153
self.assertContainsRe(deprecated,
154
':lazy:\n \(native\) Format registered lazily\n')
155
self.assertNotContainsRe(new, 'hidden')
157
def test_set_default_repository(self):
158
default_factory = bzrdir.format_registry.get('default')
159
old_default = [k for k, v in bzrdir.format_registry.iteritems()
160
if v == default_factory and k != 'default'][0]
161
bzrdir.format_registry.set_default_repository('dirstate-with-subtree')
163
self.assertIs(bzrdir.format_registry.get('dirstate-with-subtree'),
164
bzrdir.format_registry.get('default'))
166
repository.RepositoryFormat.get_default_format().__class__,
167
knitrepo.RepositoryFormatKnit3)
169
bzrdir.format_registry.set_default_repository(old_default)
171
def test_aliases(self):
172
a_registry = bzrdir.BzrDirFormatRegistry()
173
a_registry.register('weave', bzrdir.BzrDirFormat6,
174
'Pre-0.8 format. Slower and does not support checkouts or shared'
175
' repositories', deprecated=True)
176
a_registry.register('weavealias', bzrdir.BzrDirFormat6,
177
'Pre-0.8 format. Slower and does not support checkouts or shared'
178
' repositories', deprecated=True, alias=True)
179
self.assertEqual(frozenset(['weavealias']), a_registry.aliases())
182
class SampleBranch(bzrlib.branch.Branch):
183
"""A dummy branch for guess what, dummy use."""
185
def __init__(self, dir):
189
class SampleBzrDir(bzrdir.BzrDir):
190
"""A sample BzrDir implementation to allow testing static methods."""
192
def create_repository(self, shared=False):
193
"""See BzrDir.create_repository."""
194
return "A repository"
196
def open_repository(self):
197
"""See BzrDir.open_repository."""
198
return "A repository"
200
def create_branch(self):
201
"""See BzrDir.create_branch."""
202
return SampleBranch(self)
204
def create_workingtree(self):
205
"""See BzrDir.create_workingtree."""
209
class SampleBzrDirFormat(bzrdir.BzrDirFormat):
212
this format is initializable, unsupported to aid in testing the
213
open and open_downlevel routines.
216
def get_format_string(self):
217
"""See BzrDirFormat.get_format_string()."""
218
return "Sample .bzr dir format."
220
def initialize_on_transport(self, t):
221
"""Create a bzr dir."""
223
t.put_bytes('.bzr/branch-format', self.get_format_string())
224
return SampleBzrDir(t, self)
226
def is_supported(self):
229
def open(self, transport, _found=None):
230
return "opened branch."
233
class TestBzrDirFormat(TestCaseWithTransport):
234
"""Tests for the BzrDirFormat facility."""
236
def test_find_format(self):
237
# is the right format object found for a branch?
238
# create a branch with a few known format objects.
239
# this is not quite the same as
240
t = get_transport(self.get_url())
241
self.build_tree(["foo/", "bar/"], transport=t)
242
def check_format(format, url):
243
format.initialize(url)
244
t = get_transport(url)
245
found_format = bzrdir.BzrDirFormat.find_format(t)
246
self.failUnless(isinstance(found_format, format.__class__))
247
check_format(bzrdir.BzrDirFormat5(), "foo")
248
check_format(bzrdir.BzrDirFormat6(), "bar")
250
def test_find_format_nothing_there(self):
251
self.assertRaises(NotBranchError,
252
bzrdir.BzrDirFormat.find_format,
255
def test_find_format_unknown_format(self):
256
t = get_transport(self.get_url())
258
t.put_bytes('.bzr/branch-format', '')
259
self.assertRaises(UnknownFormatError,
260
bzrdir.BzrDirFormat.find_format,
263
def test_register_unregister_format(self):
264
format = SampleBzrDirFormat()
267
format.initialize(url)
268
# register a format for it.
269
bzrdir.BzrDirFormat.register_format(format)
270
# which bzrdir.Open will refuse (not supported)
271
self.assertRaises(UnsupportedFormatError, bzrdir.BzrDir.open, url)
272
# which bzrdir.open_containing will refuse (not supported)
273
self.assertRaises(UnsupportedFormatError, bzrdir.BzrDir.open_containing, url)
274
# but open_downlevel will work
275
t = get_transport(url)
276
self.assertEqual(format.open(t), bzrdir.BzrDir.open_unsupported(url))
277
# unregister the format
278
bzrdir.BzrDirFormat.unregister_format(format)
279
# now open_downlevel should fail too.
280
self.assertRaises(UnknownFormatError, bzrdir.BzrDir.open_unsupported, url)
282
def test_create_branch_and_repo_uses_default(self):
283
format = SampleBzrDirFormat()
284
branch = bzrdir.BzrDir.create_branch_and_repo(self.get_url(),
286
self.assertTrue(isinstance(branch, SampleBranch))
288
def test_create_branch_and_repo_under_shared(self):
289
# creating a branch and repo in a shared repo uses the
291
format = bzrdir.format_registry.make_bzrdir('knit')
292
self.make_repository('.', shared=True, format=format)
293
branch = bzrdir.BzrDir.create_branch_and_repo(
294
self.get_url('child'), format=format)
295
self.assertRaises(errors.NoRepositoryPresent,
296
branch.bzrdir.open_repository)
298
def test_create_branch_and_repo_under_shared_force_new(self):
299
# creating a branch and repo in a shared repo can be forced to
301
format = bzrdir.format_registry.make_bzrdir('knit')
302
self.make_repository('.', shared=True, format=format)
303
branch = bzrdir.BzrDir.create_branch_and_repo(self.get_url('child'),
306
branch.bzrdir.open_repository()
308
def test_create_standalone_working_tree(self):
309
format = SampleBzrDirFormat()
310
# note this is deliberately readonly, as this failure should
311
# occur before any writes.
312
self.assertRaises(errors.NotLocalUrl,
313
bzrdir.BzrDir.create_standalone_workingtree,
314
self.get_readonly_url(), format=format)
315
tree = bzrdir.BzrDir.create_standalone_workingtree('.',
317
self.assertEqual('A tree', tree)
319
def test_create_standalone_working_tree_under_shared_repo(self):
320
# create standalone working tree always makes a repo.
321
format = bzrdir.format_registry.make_bzrdir('knit')
322
self.make_repository('.', shared=True, format=format)
323
# note this is deliberately readonly, as this failure should
324
# occur before any writes.
325
self.assertRaises(errors.NotLocalUrl,
326
bzrdir.BzrDir.create_standalone_workingtree,
327
self.get_readonly_url('child'), format=format)
328
tree = bzrdir.BzrDir.create_standalone_workingtree('child',
330
tree.bzrdir.open_repository()
332
def test_create_branch_convenience(self):
333
# outside a repo the default convenience output is a repo+branch_tree
334
format = bzrdir.format_registry.make_bzrdir('knit')
335
branch = bzrdir.BzrDir.create_branch_convenience('.', format=format)
336
branch.bzrdir.open_workingtree()
337
branch.bzrdir.open_repository()
339
def test_create_branch_convenience_possible_transports(self):
340
"""Check that the optional 'possible_transports' is recognized"""
341
format = bzrdir.format_registry.make_bzrdir('knit')
342
t = self.get_transport()
343
branch = bzrdir.BzrDir.create_branch_convenience(
344
'.', format=format, possible_transports=[t])
345
branch.bzrdir.open_workingtree()
346
branch.bzrdir.open_repository()
348
def test_create_branch_convenience_root(self):
349
"""Creating a branch at the root of a fs should work."""
350
self.vfs_transport_factory = MemoryServer
351
# outside a repo the default convenience output is a repo+branch_tree
352
format = bzrdir.format_registry.make_bzrdir('knit')
353
branch = bzrdir.BzrDir.create_branch_convenience(self.get_url(),
355
self.assertRaises(errors.NoWorkingTree,
356
branch.bzrdir.open_workingtree)
357
branch.bzrdir.open_repository()
359
def test_create_branch_convenience_under_shared_repo(self):
360
# inside a repo the default convenience output is a branch+ follow the
362
format = bzrdir.format_registry.make_bzrdir('knit')
363
self.make_repository('.', shared=True, format=format)
364
branch = bzrdir.BzrDir.create_branch_convenience('child',
366
branch.bzrdir.open_workingtree()
367
self.assertRaises(errors.NoRepositoryPresent,
368
branch.bzrdir.open_repository)
370
def test_create_branch_convenience_under_shared_repo_force_no_tree(self):
371
# inside a repo the default convenience output is a branch+ follow the
372
# repo tree policy but we can override that
373
format = bzrdir.format_registry.make_bzrdir('knit')
374
self.make_repository('.', shared=True, format=format)
375
branch = bzrdir.BzrDir.create_branch_convenience('child',
376
force_new_tree=False, format=format)
377
self.assertRaises(errors.NoWorkingTree,
378
branch.bzrdir.open_workingtree)
379
self.assertRaises(errors.NoRepositoryPresent,
380
branch.bzrdir.open_repository)
382
def test_create_branch_convenience_under_shared_repo_no_tree_policy(self):
383
# inside a repo the default convenience output is a branch+ follow the
385
format = bzrdir.format_registry.make_bzrdir('knit')
386
repo = self.make_repository('.', shared=True, format=format)
387
repo.set_make_working_trees(False)
388
branch = bzrdir.BzrDir.create_branch_convenience('child',
390
self.assertRaises(errors.NoWorkingTree,
391
branch.bzrdir.open_workingtree)
392
self.assertRaises(errors.NoRepositoryPresent,
393
branch.bzrdir.open_repository)
395
def test_create_branch_convenience_under_shared_repo_no_tree_policy_force_tree(self):
396
# inside a repo the default convenience output is a branch+ follow the
397
# repo tree policy but we can override that
398
format = bzrdir.format_registry.make_bzrdir('knit')
399
repo = self.make_repository('.', shared=True, format=format)
400
repo.set_make_working_trees(False)
401
branch = bzrdir.BzrDir.create_branch_convenience('child',
402
force_new_tree=True, format=format)
403
branch.bzrdir.open_workingtree()
404
self.assertRaises(errors.NoRepositoryPresent,
405
branch.bzrdir.open_repository)
407
def test_create_branch_convenience_under_shared_repo_force_new_repo(self):
408
# inside a repo the default convenience output is overridable to give
410
format = bzrdir.format_registry.make_bzrdir('knit')
411
self.make_repository('.', shared=True, format=format)
412
branch = bzrdir.BzrDir.create_branch_convenience('child',
413
force_new_repo=True, format=format)
414
branch.bzrdir.open_repository()
415
branch.bzrdir.open_workingtree()
418
class TestRepositoryAcquisitionPolicy(TestCaseWithTransport):
420
def test_acquire_repository_standalone(self):
421
"""The default acquisition policy should create a standalone branch."""
422
my_bzrdir = self.make_bzrdir('.')
423
repo_policy = my_bzrdir.determine_repository_policy()
424
repo = repo_policy.acquire_repository()
425
self.assertEqual(repo.bzrdir.root_transport.base,
426
my_bzrdir.root_transport.base)
427
self.assertFalse(repo.is_shared())
430
def test_determine_stacking_policy(self):
431
parent_bzrdir = self.make_bzrdir('.')
432
child_bzrdir = self.make_bzrdir('child')
433
parent_bzrdir.get_config().set_default_stack_on('http://example.org')
434
repo_policy = child_bzrdir.determine_repository_policy()
435
self.assertEqual('http://example.org', repo_policy._stack_on)
437
def test_determine_stacking_policy_relative(self):
438
parent_bzrdir = self.make_bzrdir('.')
439
child_bzrdir = self.make_bzrdir('child')
440
parent_bzrdir.get_config().set_default_stack_on('child2')
441
repo_policy = child_bzrdir.determine_repository_policy()
442
self.assertEqual('child2', repo_policy._stack_on)
443
self.assertEqual(parent_bzrdir.root_transport.base,
444
repo_policy._stack_on_pwd)
446
def prepare_default_stacking(self, child_format='1.6'):
447
parent_bzrdir = self.make_bzrdir('.')
448
child_branch = self.make_branch('child', format=child_format)
449
parent_bzrdir.get_config().set_default_stack_on(child_branch.base)
450
new_child_transport = parent_bzrdir.transport.clone('child2')
451
return child_branch, new_child_transport
453
def test_clone_on_transport_obeys_stacking_policy(self):
454
child_branch, new_child_transport = self.prepare_default_stacking()
455
new_child = child_branch.bzrdir.clone_on_transport(new_child_transport)
456
self.assertEqual(child_branch.base,
457
new_child.open_branch().get_stacked_on_url())
459
def test_sprout_obeys_stacking_policy(self):
460
child_branch, new_child_transport = self.prepare_default_stacking()
461
new_child = child_branch.bzrdir.sprout(new_child_transport.base)
462
self.assertEqual(child_branch.base,
463
new_child.open_branch().get_stacked_on_url())
465
def test_clone_ignores_policy_for_unsupported_formats(self):
466
child_branch, new_child_transport = self.prepare_default_stacking(
467
child_format='pack-0.92')
468
new_child = child_branch.bzrdir.clone_on_transport(new_child_transport)
469
self.assertRaises(errors.UnstackableBranchFormat,
470
new_child.open_branch().get_stacked_on_url)
472
def test_sprout_ignores_policy_for_unsupported_formats(self):
473
child_branch, new_child_transport = self.prepare_default_stacking(
474
child_format='pack-0.92')
475
new_child = child_branch.bzrdir.sprout(new_child_transport.base)
476
self.assertRaises(errors.UnstackableBranchFormat,
477
new_child.open_branch().get_stacked_on_url)
479
def test_sprout_upgrades_format_if_stacked_specified(self):
480
child_branch, new_child_transport = self.prepare_default_stacking(
481
child_format='pack-0.92')
482
new_child = child_branch.bzrdir.sprout(new_child_transport.base,
484
self.assertEqual(child_branch.bzrdir.root_transport.base,
485
new_child.open_branch().get_stacked_on_url())
486
repo = new_child.open_repository()
487
self.assertTrue(repo._format.supports_external_lookups)
488
self.assertFalse(repo.supports_rich_root())
490
def test_clone_on_transport_upgrades_format_if_stacked_on_specified(self):
491
child_branch, new_child_transport = self.prepare_default_stacking(
492
child_format='pack-0.92')
493
new_child = child_branch.bzrdir.clone_on_transport(new_child_transport,
494
stacked_on=child_branch.bzrdir.root_transport.base)
495
self.assertEqual(child_branch.bzrdir.root_transport.base,
496
new_child.open_branch().get_stacked_on_url())
497
repo = new_child.open_repository()
498
self.assertTrue(repo._format.supports_external_lookups)
499
self.assertFalse(repo.supports_rich_root())
501
def test_sprout_upgrades_to_rich_root_format_if_needed(self):
502
child_branch, new_child_transport = self.prepare_default_stacking(
503
child_format='rich-root-pack')
504
new_child = child_branch.bzrdir.sprout(new_child_transport.base,
506
repo = new_child.open_repository()
507
self.assertTrue(repo._format.supports_external_lookups)
508
self.assertTrue(repo.supports_rich_root())
510
def test_add_fallback_repo_handles_absolute_urls(self):
511
stack_on = self.make_branch('stack_on', format='1.6')
512
repo = self.make_repository('repo', format='1.6')
513
policy = bzrdir.UseExistingRepository(repo, stack_on.base)
514
policy._add_fallback(repo)
516
def test_add_fallback_repo_handles_relative_urls(self):
517
stack_on = self.make_branch('stack_on', format='1.6')
518
repo = self.make_repository('repo', format='1.6')
519
policy = bzrdir.UseExistingRepository(repo, '.', stack_on.base)
520
policy._add_fallback(repo)
522
def test_configure_relative_branch_stacking_url(self):
523
stack_on = self.make_branch('stack_on', format='1.6')
524
stacked = self.make_branch('stack_on/stacked', format='1.6')
525
policy = bzrdir.UseExistingRepository(stacked.repository,
527
policy.configure_branch(stacked)
528
self.assertEqual('..', stacked.get_stacked_on_url())
530
def test_relative_branch_stacking_to_absolute(self):
531
stack_on = self.make_branch('stack_on', format='1.6')
532
stacked = self.make_branch('stack_on/stacked', format='1.6')
533
policy = bzrdir.UseExistingRepository(stacked.repository,
534
'.', self.get_readonly_url('stack_on'))
535
policy.configure_branch(stacked)
536
self.assertEqual(self.get_readonly_url('stack_on'),
537
stacked.get_stacked_on_url())
540
class ChrootedTests(TestCaseWithTransport):
541
"""A support class that provides readonly urls outside the local namespace.
543
This is done by checking if self.transport_server is a MemoryServer. if it
544
is then we are chrooted already, if it is not then an HttpServer is used
549
super(ChrootedTests, self).setUp()
550
if not self.vfs_transport_factory == MemoryServer:
551
self.transport_readonly_server = http_server.HttpServer
553
def local_branch_path(self, branch):
554
return os.path.realpath(urlutils.local_path_from_url(branch.base))
556
def test_open_containing(self):
557
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing,
558
self.get_readonly_url(''))
559
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing,
560
self.get_readonly_url('g/p/q'))
561
control = bzrdir.BzrDir.create(self.get_url())
562
branch, relpath = bzrdir.BzrDir.open_containing(self.get_readonly_url(''))
563
self.assertEqual('', relpath)
564
branch, relpath = bzrdir.BzrDir.open_containing(self.get_readonly_url('g/p/q'))
565
self.assertEqual('g/p/q', relpath)
567
def test_open_containing_tree_branch_or_repository_empty(self):
568
self.assertRaises(errors.NotBranchError,
569
bzrdir.BzrDir.open_containing_tree_branch_or_repository,
570
self.get_readonly_url(''))
572
def test_open_containing_tree_branch_or_repository_all(self):
573
self.make_branch_and_tree('topdir')
574
tree, branch, repo, relpath = \
575
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
577
self.assertEqual(os.path.realpath('topdir'),
578
os.path.realpath(tree.basedir))
579
self.assertEqual(os.path.realpath('topdir'),
580
self.local_branch_path(branch))
582
osutils.realpath(os.path.join('topdir', '.bzr', 'repository')),
583
repo.bzrdir.transport.local_abspath('repository'))
584
self.assertEqual(relpath, 'foo')
586
def test_open_containing_tree_branch_or_repository_no_tree(self):
587
self.make_branch('branch')
588
tree, branch, repo, relpath = \
589
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
591
self.assertEqual(tree, None)
592
self.assertEqual(os.path.realpath('branch'),
593
self.local_branch_path(branch))
595
osutils.realpath(os.path.join('branch', '.bzr', 'repository')),
596
repo.bzrdir.transport.local_abspath('repository'))
597
self.assertEqual(relpath, 'foo')
599
def test_open_containing_tree_branch_or_repository_repo(self):
600
self.make_repository('repo')
601
tree, branch, repo, relpath = \
602
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
604
self.assertEqual(tree, None)
605
self.assertEqual(branch, None)
607
osutils.realpath(os.path.join('repo', '.bzr', 'repository')),
608
repo.bzrdir.transport.local_abspath('repository'))
609
self.assertEqual(relpath, '')
611
def test_open_containing_tree_branch_or_repository_shared_repo(self):
612
self.make_repository('shared', shared=True)
613
bzrdir.BzrDir.create_branch_convenience('shared/branch',
614
force_new_tree=False)
615
tree, branch, repo, relpath = \
616
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
618
self.assertEqual(tree, None)
619
self.assertEqual(os.path.realpath('shared/branch'),
620
self.local_branch_path(branch))
622
osutils.realpath(os.path.join('shared', '.bzr', 'repository')),
623
repo.bzrdir.transport.local_abspath('repository'))
624
self.assertEqual(relpath, '')
626
def test_open_containing_tree_branch_or_repository_branch_subdir(self):
627
self.make_branch_and_tree('foo')
628
self.build_tree(['foo/bar/'])
629
tree, branch, repo, relpath = \
630
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
632
self.assertEqual(os.path.realpath('foo'),
633
os.path.realpath(tree.basedir))
634
self.assertEqual(os.path.realpath('foo'),
635
self.local_branch_path(branch))
637
osutils.realpath(os.path.join('foo', '.bzr', 'repository')),
638
repo.bzrdir.transport.local_abspath('repository'))
639
self.assertEqual(relpath, 'bar')
641
def test_open_containing_tree_branch_or_repository_repo_subdir(self):
642
self.make_repository('bar')
643
self.build_tree(['bar/baz/'])
644
tree, branch, repo, relpath = \
645
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
647
self.assertEqual(tree, None)
648
self.assertEqual(branch, None)
650
osutils.realpath(os.path.join('bar', '.bzr', 'repository')),
651
repo.bzrdir.transport.local_abspath('repository'))
652
self.assertEqual(relpath, 'baz')
654
def test_open_containing_from_transport(self):
655
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing_from_transport,
656
get_transport(self.get_readonly_url('')))
657
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing_from_transport,
658
get_transport(self.get_readonly_url('g/p/q')))
659
control = bzrdir.BzrDir.create(self.get_url())
660
branch, relpath = bzrdir.BzrDir.open_containing_from_transport(
661
get_transport(self.get_readonly_url('')))
662
self.assertEqual('', relpath)
663
branch, relpath = bzrdir.BzrDir.open_containing_from_transport(
664
get_transport(self.get_readonly_url('g/p/q')))
665
self.assertEqual('g/p/q', relpath)
667
def test_open_containing_tree_or_branch(self):
668
self.make_branch_and_tree('topdir')
669
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
671
self.assertEqual(os.path.realpath('topdir'),
672
os.path.realpath(tree.basedir))
673
self.assertEqual(os.path.realpath('topdir'),
674
self.local_branch_path(branch))
675
self.assertIs(tree.bzrdir, branch.bzrdir)
676
self.assertEqual('foo', relpath)
677
# opening from non-local should not return the tree
678
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
679
self.get_readonly_url('topdir/foo'))
680
self.assertEqual(None, tree)
681
self.assertEqual('foo', relpath)
683
self.make_branch('topdir/foo')
684
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
686
self.assertIs(tree, None)
687
self.assertEqual(os.path.realpath('topdir/foo'),
688
self.local_branch_path(branch))
689
self.assertEqual('', relpath)
691
def test_open_tree_or_branch(self):
692
self.make_branch_and_tree('topdir')
693
tree, branch = bzrdir.BzrDir.open_tree_or_branch('topdir')
694
self.assertEqual(os.path.realpath('topdir'),
695
os.path.realpath(tree.basedir))
696
self.assertEqual(os.path.realpath('topdir'),
697
self.local_branch_path(branch))
698
self.assertIs(tree.bzrdir, branch.bzrdir)
699
# opening from non-local should not return the tree
700
tree, branch = bzrdir.BzrDir.open_tree_or_branch(
701
self.get_readonly_url('topdir'))
702
self.assertEqual(None, tree)
704
self.make_branch('topdir/foo')
705
tree, branch = bzrdir.BzrDir.open_tree_or_branch('topdir/foo')
706
self.assertIs(tree, None)
707
self.assertEqual(os.path.realpath('topdir/foo'),
708
self.local_branch_path(branch))
710
def test_open_from_transport(self):
711
# transport pointing at bzrdir should give a bzrdir with root transport
712
# set to the given transport
713
control = bzrdir.BzrDir.create(self.get_url())
714
transport = get_transport(self.get_url())
715
opened_bzrdir = bzrdir.BzrDir.open_from_transport(transport)
716
self.assertEqual(transport.base, opened_bzrdir.root_transport.base)
717
self.assertIsInstance(opened_bzrdir, bzrdir.BzrDir)
719
def test_open_from_transport_no_bzrdir(self):
720
transport = get_transport(self.get_url())
721
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport,
724
def test_open_from_transport_bzrdir_in_parent(self):
725
control = bzrdir.BzrDir.create(self.get_url())
726
transport = get_transport(self.get_url())
727
transport.mkdir('subdir')
728
transport = transport.clone('subdir')
729
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport,
732
def test_sprout_recursive(self):
733
tree = self.make_branch_and_tree('tree1', format='dirstate-with-subtree')
734
sub_tree = self.make_branch_and_tree('tree1/subtree',
735
format='dirstate-with-subtree')
736
tree.add_reference(sub_tree)
737
self.build_tree(['tree1/subtree/file'])
739
tree.commit('Initial commit')
740
tree.bzrdir.sprout('tree2')
741
self.failUnlessExists('tree2/subtree/file')
743
def test_cloning_metadir(self):
744
"""Ensure that cloning metadir is suitable"""
745
bzrdir = self.make_bzrdir('bzrdir')
746
bzrdir.cloning_metadir()
747
branch = self.make_branch('branch', format='knit')
748
format = branch.bzrdir.cloning_metadir()
749
self.assertIsInstance(format.workingtree_format,
750
workingtree.WorkingTreeFormat3)
752
def test_sprout_recursive_treeless(self):
753
tree = self.make_branch_and_tree('tree1',
754
format='dirstate-with-subtree')
755
sub_tree = self.make_branch_and_tree('tree1/subtree',
756
format='dirstate-with-subtree')
757
tree.add_reference(sub_tree)
758
self.build_tree(['tree1/subtree/file'])
760
tree.commit('Initial commit')
761
tree.bzrdir.destroy_workingtree()
762
repo = self.make_repository('repo', shared=True,
763
format='dirstate-with-subtree')
764
repo.set_make_working_trees(False)
765
tree.bzrdir.sprout('repo/tree2')
766
self.failUnlessExists('repo/tree2/subtree')
767
self.failIfExists('repo/tree2/subtree/file')
769
def make_foo_bar_baz(self):
770
foo = bzrdir.BzrDir.create_branch_convenience('foo').bzrdir
771
bar = self.make_branch('foo/bar').bzrdir
772
baz = self.make_branch('baz').bzrdir
775
def test_find_bzrdirs(self):
776
foo, bar, baz = self.make_foo_bar_baz()
777
transport = get_transport(self.get_url())
778
self.assertEqualBzrdirs([baz, foo, bar],
779
bzrdir.BzrDir.find_bzrdirs(transport))
781
def test_find_bzrdirs_list_current(self):
782
def list_current(transport):
783
return [s for s in transport.list_dir('') if s != 'baz']
785
foo, bar, baz = self.make_foo_bar_baz()
786
transport = get_transport(self.get_url())
787
self.assertEqualBzrdirs([foo, bar],
788
bzrdir.BzrDir.find_bzrdirs(transport,
789
list_current=list_current))
792
def test_find_bzrdirs_evaluate(self):
793
def evaluate(bzrdir):
795
repo = bzrdir.open_repository()
796
except NoRepositoryPresent:
797
return True, bzrdir.root_transport.base
799
return False, bzrdir.root_transport.base
801
foo, bar, baz = self.make_foo_bar_baz()
802
transport = get_transport(self.get_url())
803
self.assertEqual([baz.root_transport.base, foo.root_transport.base],
804
list(bzrdir.BzrDir.find_bzrdirs(transport,
807
def assertEqualBzrdirs(self, first, second):
809
second = list(second)
810
self.assertEqual(len(first), len(second))
811
for x, y in zip(first, second):
812
self.assertEqual(x.root_transport.base, y.root_transport.base)
814
def test_find_branches(self):
815
root = self.make_repository('', shared=True)
816
foo, bar, baz = self.make_foo_bar_baz()
817
qux = self.make_bzrdir('foo/qux')
818
transport = get_transport(self.get_url())
819
branches = bzrdir.BzrDir.find_branches(transport)
820
self.assertEqual(baz.root_transport.base, branches[0].base)
821
self.assertEqual(foo.root_transport.base, branches[1].base)
822
self.assertEqual(bar.root_transport.base, branches[2].base)
824
# ensure this works without a top-level repo
825
branches = bzrdir.BzrDir.find_branches(transport.clone('foo'))
826
self.assertEqual(foo.root_transport.base, branches[0].base)
827
self.assertEqual(bar.root_transport.base, branches[1].base)
830
class TestMeta1DirFormat(TestCaseWithTransport):
831
"""Tests specific to the meta1 dir format."""
833
def test_right_base_dirs(self):
834
dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
836
branch_base = t.clone('branch').base
837
self.assertEqual(branch_base, dir.get_branch_transport(None).base)
838
self.assertEqual(branch_base,
839
dir.get_branch_transport(bzrlib.branch.BzrBranchFormat5()).base)
840
repository_base = t.clone('repository').base
841
self.assertEqual(repository_base, dir.get_repository_transport(None).base)
842
self.assertEqual(repository_base,
843
dir.get_repository_transport(weaverepo.RepositoryFormat7()).base)
844
checkout_base = t.clone('checkout').base
845
self.assertEqual(checkout_base, dir.get_workingtree_transport(None).base)
846
self.assertEqual(checkout_base,
847
dir.get_workingtree_transport(workingtree.WorkingTreeFormat3()).base)
849
def test_meta1dir_uses_lockdir(self):
850
"""Meta1 format uses a LockDir to guard the whole directory, not a file."""
851
dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
853
self.assertIsDirectory('branch-lock', t)
855
def test_comparison(self):
856
"""Equality and inequality behave properly.
858
Metadirs should compare equal iff they have the same repo, branch and
861
mydir = bzrdir.format_registry.make_bzrdir('knit')
862
self.assertEqual(mydir, mydir)
863
self.assertFalse(mydir != mydir)
864
otherdir = bzrdir.format_registry.make_bzrdir('knit')
865
self.assertEqual(otherdir, mydir)
866
self.assertFalse(otherdir != mydir)
867
otherdir2 = bzrdir.format_registry.make_bzrdir('dirstate-with-subtree')
868
self.assertNotEqual(otherdir2, mydir)
869
self.assertFalse(otherdir2 == mydir)
871
def test_needs_conversion_different_working_tree(self):
872
# meta1dirs need an conversion if any element is not the default.
873
old_format = bzrdir.BzrDirFormat.get_default_format()
875
new_default = bzrdir.format_registry.make_bzrdir('dirstate')
876
bzrdir.BzrDirFormat._set_default_format(new_default)
878
tree = self.make_branch_and_tree('tree', format='knit')
879
self.assertTrue(tree.bzrdir.needs_format_conversion())
881
bzrdir.BzrDirFormat._set_default_format(old_format)
884
class TestFormat5(TestCaseWithTransport):
885
"""Tests specific to the version 5 bzrdir format."""
887
def test_same_lockfiles_between_tree_repo_branch(self):
888
# this checks that only a single lockfiles instance is created
889
# for format 5 objects
890
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
891
def check_dir_components_use_same_lock(dir):
892
ctrl_1 = dir.open_repository().control_files
893
ctrl_2 = dir.open_branch().control_files
894
ctrl_3 = dir.open_workingtree()._control_files
895
self.assertTrue(ctrl_1 is ctrl_2)
896
self.assertTrue(ctrl_2 is ctrl_3)
897
check_dir_components_use_same_lock(dir)
898
# and if we open it normally.
899
dir = bzrdir.BzrDir.open(self.get_url())
900
check_dir_components_use_same_lock(dir)
902
def test_can_convert(self):
903
# format 5 dirs are convertable
904
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
905
self.assertTrue(dir.can_convert_format())
907
def test_needs_conversion(self):
908
# format 5 dirs need a conversion if they are not the default.
909
# and they start of not the default.
910
old_format = bzrdir.BzrDirFormat.get_default_format()
911
bzrdir.BzrDirFormat._set_default_format(bzrdir.BzrDirFormat5())
913
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
914
self.assertFalse(dir.needs_format_conversion())
916
bzrdir.BzrDirFormat._set_default_format(old_format)
917
self.assertTrue(dir.needs_format_conversion())
920
class TestFormat6(TestCaseWithTransport):
921
"""Tests specific to the version 6 bzrdir format."""
923
def test_same_lockfiles_between_tree_repo_branch(self):
924
# this checks that only a single lockfiles instance is created
925
# for format 6 objects
926
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
927
def check_dir_components_use_same_lock(dir):
928
ctrl_1 = dir.open_repository().control_files
929
ctrl_2 = dir.open_branch().control_files
930
ctrl_3 = dir.open_workingtree()._control_files
931
self.assertTrue(ctrl_1 is ctrl_2)
932
self.assertTrue(ctrl_2 is ctrl_3)
933
check_dir_components_use_same_lock(dir)
934
# and if we open it normally.
935
dir = bzrdir.BzrDir.open(self.get_url())
936
check_dir_components_use_same_lock(dir)
938
def test_can_convert(self):
939
# format 6 dirs are convertable
940
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
941
self.assertTrue(dir.can_convert_format())
943
def test_needs_conversion(self):
944
# format 6 dirs need an conversion if they are not the default.
945
old_format = bzrdir.BzrDirFormat.get_default_format()
946
bzrdir.BzrDirFormat._set_default_format(bzrdir.BzrDirMetaFormat1())
948
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
949
self.assertTrue(dir.needs_format_conversion())
951
bzrdir.BzrDirFormat._set_default_format(old_format)
954
class NotBzrDir(bzrlib.bzrdir.BzrDir):
955
"""A non .bzr based control directory."""
957
def __init__(self, transport, format):
958
self._format = format
959
self.root_transport = transport
960
self.transport = transport.clone('.not')
963
class NotBzrDirFormat(bzrlib.bzrdir.BzrDirFormat):
964
"""A test class representing any non-.bzr based disk format."""
966
def initialize_on_transport(self, transport):
967
"""Initialize a new .not dir in the base directory of a Transport."""
968
transport.mkdir('.not')
969
return self.open(transport)
971
def open(self, transport):
972
"""Open this directory."""
973
return NotBzrDir(transport, self)
976
def _known_formats(self):
977
return set([NotBzrDirFormat()])
980
def probe_transport(self, transport):
981
"""Our format is present if the transport ends in '.not/'."""
982
if transport.has('.not'):
983
return NotBzrDirFormat()
986
class TestNotBzrDir(TestCaseWithTransport):
987
"""Tests for using the bzrdir api with a non .bzr based disk format.
989
If/when one of these is in the core, we can let the implementation tests
993
def test_create_and_find_format(self):
994
# create a .notbzr dir
995
format = NotBzrDirFormat()
996
dir = format.initialize(self.get_url())
997
self.assertIsInstance(dir, NotBzrDir)
999
bzrlib.bzrdir.BzrDirFormat.register_control_format(format)
1001
found = bzrlib.bzrdir.BzrDirFormat.find_format(
1002
get_transport(self.get_url()))
1003
self.assertIsInstance(found, NotBzrDirFormat)
1005
bzrlib.bzrdir.BzrDirFormat.unregister_control_format(format)
1007
def test_included_in_known_formats(self):
1008
bzrlib.bzrdir.BzrDirFormat.register_control_format(NotBzrDirFormat)
1010
formats = bzrlib.bzrdir.BzrDirFormat.known_formats()
1011
for format in formats:
1012
if isinstance(format, NotBzrDirFormat):
1014
self.fail("No NotBzrDirFormat in %s" % formats)
1016
bzrlib.bzrdir.BzrDirFormat.unregister_control_format(NotBzrDirFormat)
1019
class NonLocalTests(TestCaseWithTransport):
1020
"""Tests for bzrdir static behaviour on non local paths."""
1023
super(NonLocalTests, self).setUp()
1024
self.vfs_transport_factory = MemoryServer
1026
def test_create_branch_convenience(self):
1027
# outside a repo the default convenience output is a repo+branch_tree
1028
format = bzrdir.format_registry.make_bzrdir('knit')
1029
branch = bzrdir.BzrDir.create_branch_convenience(
1030
self.get_url('foo'), format=format)
1031
self.assertRaises(errors.NoWorkingTree,
1032
branch.bzrdir.open_workingtree)
1033
branch.bzrdir.open_repository()
1035
def test_create_branch_convenience_force_tree_not_local_fails(self):
1036
# outside a repo the default convenience output is a repo+branch_tree
1037
format = bzrdir.format_registry.make_bzrdir('knit')
1038
self.assertRaises(errors.NotLocalUrl,
1039
bzrdir.BzrDir.create_branch_convenience,
1040
self.get_url('foo'),
1041
force_new_tree=True,
1043
t = get_transport(self.get_url('.'))
1044
self.assertFalse(t.has('foo'))
1046
def test_clone(self):
1047
# clone into a nonlocal path works
1048
format = bzrdir.format_registry.make_bzrdir('knit')
1049
branch = bzrdir.BzrDir.create_branch_convenience('local',
1051
branch.bzrdir.open_workingtree()
1052
result = branch.bzrdir.clone(self.get_url('remote'))
1053
self.assertRaises(errors.NoWorkingTree,
1054
result.open_workingtree)
1055
result.open_branch()
1056
result.open_repository()
1058
def test_checkout_metadir(self):
1059
# checkout_metadir has reasonable working tree format even when no
1060
# working tree is present
1061
self.make_branch('branch-knit2', format='dirstate-with-subtree')
1062
my_bzrdir = bzrdir.BzrDir.open(self.get_url('branch-knit2'))
1063
checkout_format = my_bzrdir.checkout_metadir()
1064
self.assertIsInstance(checkout_format.workingtree_format,
1065
workingtree.WorkingTreeFormat3)
1068
class TestHTTPRedirections(object):
1069
"""Test redirection between two http servers.
1071
This MUST be used by daughter classes that also inherit from
1072
TestCaseWithTwoWebservers.
1074
We can't inherit directly from TestCaseWithTwoWebservers or the
1075
test framework will try to create an instance which cannot
1076
run, its implementation being incomplete.
1079
def create_transport_readonly_server(self):
1080
return http_utils.HTTPServerRedirecting()
1082
def create_transport_secondary_server(self):
1083
return http_utils.HTTPServerRedirecting()
1086
super(TestHTTPRedirections, self).setUp()
1087
# The redirections will point to the new server
1088
self.new_server = self.get_readonly_server()
1089
# The requests to the old server will be redirected
1090
self.old_server = self.get_secondary_server()
1091
# Configure the redirections
1092
self.old_server.redirect_to(self.new_server.host, self.new_server.port)
1094
def test_loop(self):
1095
# Both servers redirect to each other creating a loop
1096
self.new_server.redirect_to(self.old_server.host, self.old_server.port)
1097
# Starting from either server should loop
1098
old_url = self._qualified_url(self.old_server.host,
1099
self.old_server.port)
1100
oldt = self._transport(old_url)
1101
self.assertRaises(errors.NotBranchError,
1102
bzrdir.BzrDir.open_from_transport, oldt)
1103
new_url = self._qualified_url(self.new_server.host,
1104
self.new_server.port)
1105
newt = self._transport(new_url)
1106
self.assertRaises(errors.NotBranchError,
1107
bzrdir.BzrDir.open_from_transport, newt)
1109
def test_qualifier_preserved(self):
1110
wt = self.make_branch_and_tree('branch')
1111
old_url = self._qualified_url(self.old_server.host,
1112
self.old_server.port)
1113
start = self._transport(old_url).clone('branch')
1114
bdir = bzrdir.BzrDir.open_from_transport(start)
1115
# Redirection should preserve the qualifier, hence the transport class
1117
self.assertIsInstance(bdir.root_transport, type(start))
1120
class TestHTTPRedirections_urllib(TestHTTPRedirections,
1121
http_utils.TestCaseWithTwoWebservers):
1122
"""Tests redirections for urllib implementation"""
1124
_transport = HttpTransport_urllib
1126
def _qualified_url(self, host, port):
1127
return 'http+urllib://%s:%s' % (host, port)
1131
class TestHTTPRedirections_pycurl(TestWithTransport_pycurl,
1132
TestHTTPRedirections,
1133
http_utils.TestCaseWithTwoWebservers):
1134
"""Tests redirections for pycurl implementation"""
1136
def _qualified_url(self, host, port):
1137
return 'http+pycurl://%s:%s' % (host, port)
1140
class TestHTTPRedirections_nosmart(TestHTTPRedirections,
1141
http_utils.TestCaseWithTwoWebservers):
1142
"""Tests redirections for the nosmart decorator"""
1144
_transport = NoSmartTransportDecorator
1146
def _qualified_url(self, host, port):
1147
return 'nosmart+http://%s:%s' % (host, port)
1150
class TestHTTPRedirections_readonly(TestHTTPRedirections,
1151
http_utils.TestCaseWithTwoWebservers):
1152
"""Tests redirections for readonly decoratror"""
1154
_transport = ReadonlyTransportDecorator
1156
def _qualified_url(self, host, port):
1157
return 'readonly+http://%s:%s' % (host, port)
1160
class TestDotBzrHidden(TestCaseWithTransport):
1163
if sys.platform == 'win32':
1164
ls = [os.environ['COMSPEC'], '/C', 'dir', '/B']
1167
f = subprocess.Popen(self.ls, stdout=subprocess.PIPE,
1168
stderr=subprocess.PIPE)
1169
out, err = f.communicate()
1170
self.assertEqual(0, f.returncode, 'Calling %s failed: %s'
1172
return out.splitlines()
1174
def test_dot_bzr_hidden(self):
1175
if sys.platform == 'win32' and not win32utils.has_win32file:
1176
raise TestSkipped('unable to make file hidden without pywin32 library')
1177
b = bzrdir.BzrDir.create('.')
1178
self.build_tree(['a'])
1179
self.assertEquals(['a'], self.get_ls())
1181
def test_dot_bzr_hidden_with_url(self):
1182
if sys.platform == 'win32' and not win32utils.has_win32file:
1183
raise TestSkipped('unable to make file hidden without pywin32 library')
1184
b = bzrdir.BzrDir.create(urlutils.local_path_to_url('.'))
1185
self.build_tree(['a'])
1186
self.assertEquals(['a'], self.get_ls())
1189
class _TestBzrDirFormat(bzrdir.BzrDirMetaFormat1):
1190
"""Test BzrDirFormat implementation for TestBzrDirSprout."""
1192
def _open(self, transport):
1193
return _TestBzrDir(transport, self)
1196
class _TestBzrDir(bzrdir.BzrDirMeta1):
1197
"""Test BzrDir implementation for TestBzrDirSprout.
1199
When created a _TestBzrDir already has repository and a branch. The branch
1200
is a test double as well.
1203
def __init__(self, *args, **kwargs):
1204
super(_TestBzrDir, self).__init__(*args, **kwargs)
1205
self.test_branch = _TestBranch()
1206
self.test_branch.repository = self.create_repository()
1208
def open_branch(self, unsupported=False):
1209
return self.test_branch
1211
def cloning_metadir(self, require_stacking=False):
1212
return _TestBzrDirFormat()
1215
class _TestBranch(bzrlib.branch.Branch):
1216
"""Test Branch implementation for TestBzrDirSprout."""
1218
def __init__(self, *args, **kwargs):
1219
super(_TestBranch, self).__init__(*args, **kwargs)
1223
def sprout(self, *args, **kwargs):
1224
self.calls.append('sprout')
1225
return _TestBranch()
1227
def copy_content_into(self, destination, revision_id=None):
1228
self.calls.append('copy_content_into')
1230
def get_parent(self):
1233
def set_parent(self, parent):
1234
self._parent = parent
1237
class TestBzrDirSprout(TestCaseWithMemoryTransport):
1239
def test_sprout_uses_branch_sprout(self):
1240
"""BzrDir.sprout calls Branch.sprout.
1242
Usually, BzrDir.sprout should delegate to the branch's sprout method
1243
for part of the work. This allows the source branch to control the
1244
choice of format for the new branch.
1246
There are exceptions, but this tests avoids them:
1247
- if there's no branch in the source bzrdir,
1248
- or if the stacking has been requested and the format needs to be
1249
overridden to satisfy that.
1251
# Make an instrumented bzrdir.
1252
t = self.get_transport('source')
1254
source_bzrdir = _TestBzrDirFormat().initialize_on_transport(t)
1255
# The instrumented bzrdir has a test_branch attribute that logs calls
1256
# made to the branch contained in that bzrdir. Initially the test
1257
# branch exists but no calls have been made to it.
1258
self.assertEqual([], source_bzrdir.test_branch.calls)
1261
target_url = self.get_url('target')
1262
result = source_bzrdir.sprout(target_url, recurse='no')
1264
# The bzrdir called the branch's sprout method.
1265
self.assertSubset(['sprout'], source_bzrdir.test_branch.calls)
1267
def test_sprout_parent(self):
1268
grandparent_tree = self.make_branch('grandparent')
1269
parent = grandparent_tree.bzrdir.sprout('parent').open_branch()
1270
branch_tree = parent.bzrdir.sprout('branch').open_branch()
1271
self.assertContainsRe(branch_tree.get_parent(), '/parent/$')