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
41
from bzrlib.errors import (NotBranchError,
43
UnsupportedFormatError,
45
from bzrlib.tests import (
47
TestCaseWithMemoryTransport,
48
TestCaseWithTransport,
52
from bzrlib.tests import(
56
from bzrlib.tests.test_http import TestWithTransport_pycurl
57
from bzrlib.transport import get_transport
58
from bzrlib.transport.http._urllib import HttpTransport_urllib
59
from bzrlib.transport.memory import MemoryServer
60
from bzrlib.transport.nosmart import NoSmartTransportDecorator
61
from bzrlib.transport.readonly import ReadonlyTransportDecorator
62
from bzrlib.repofmt import knitrepo, weaverepo
65
class TestDefaultFormat(TestCase):
67
def test_get_set_default_format(self):
68
old_format = bzrdir.BzrDirFormat.get_default_format()
69
# default is BzrDirFormat6
70
self.failUnless(isinstance(old_format, bzrdir.BzrDirMetaFormat1))
71
bzrdir.BzrDirFormat._set_default_format(SampleBzrDirFormat())
72
# creating a bzr dir should now create an instrumented dir.
74
result = bzrdir.BzrDir.create('memory:///')
75
self.failUnless(isinstance(result, SampleBzrDir))
77
bzrdir.BzrDirFormat._set_default_format(old_format)
78
self.assertEqual(old_format, bzrdir.BzrDirFormat.get_default_format())
81
class TestFormatRegistry(TestCase):
83
def make_format_registry(self):
84
my_format_registry = bzrdir.BzrDirFormatRegistry()
85
my_format_registry.register('weave', bzrdir.BzrDirFormat6,
86
'Pre-0.8 format. Slower and does not support checkouts or shared'
87
' repositories', deprecated=True)
88
my_format_registry.register_lazy('lazy', 'bzrlib.bzrdir',
89
'BzrDirFormat6', 'Format registered lazily', deprecated=True)
90
my_format_registry.register_metadir('knit',
91
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
94
my_format_registry.set_default('knit')
95
my_format_registry.register_metadir(
97
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
98
'Experimental successor to knit. Use at your own risk.',
99
branch_format='bzrlib.branch.BzrBranchFormat6',
101
my_format_registry.register_metadir(
103
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
104
'Experimental successor to knit. Use at your own risk.',
105
branch_format='bzrlib.branch.BzrBranchFormat6', hidden=True)
106
my_format_registry.register('hiddenweave', bzrdir.BzrDirFormat6,
107
'Pre-0.8 format. Slower and does not support checkouts or shared'
108
' repositories', hidden=True)
109
my_format_registry.register_lazy('hiddenlazy', 'bzrlib.bzrdir',
110
'BzrDirFormat6', 'Format registered lazily', deprecated=True,
112
return my_format_registry
114
def test_format_registry(self):
115
my_format_registry = self.make_format_registry()
116
my_bzrdir = my_format_registry.make_bzrdir('lazy')
117
self.assertIsInstance(my_bzrdir, bzrdir.BzrDirFormat6)
118
my_bzrdir = my_format_registry.make_bzrdir('weave')
119
self.assertIsInstance(my_bzrdir, bzrdir.BzrDirFormat6)
120
my_bzrdir = my_format_registry.make_bzrdir('default')
121
self.assertIsInstance(my_bzrdir.repository_format,
122
knitrepo.RepositoryFormatKnit1)
123
my_bzrdir = my_format_registry.make_bzrdir('knit')
124
self.assertIsInstance(my_bzrdir.repository_format,
125
knitrepo.RepositoryFormatKnit1)
126
my_bzrdir = my_format_registry.make_bzrdir('branch6')
127
self.assertIsInstance(my_bzrdir.get_branch_format(),
128
bzrlib.branch.BzrBranchFormat6)
130
def test_get_help(self):
131
my_format_registry = self.make_format_registry()
132
self.assertEqual('Format registered lazily',
133
my_format_registry.get_help('lazy'))
134
self.assertEqual('Format using knits',
135
my_format_registry.get_help('knit'))
136
self.assertEqual('Format using knits',
137
my_format_registry.get_help('default'))
138
self.assertEqual('Pre-0.8 format. Slower and does not support'
139
' checkouts or shared repositories',
140
my_format_registry.get_help('weave'))
142
def test_help_topic(self):
143
topics = help_topics.HelpTopicRegistry()
144
registry = self.make_format_registry()
145
topics.register('current-formats', registry.help_topic,
147
topics.register('other-formats', registry.help_topic,
149
new = topics.get_detail('current-formats')
150
rest = topics.get_detail('other-formats')
151
experimental, deprecated = rest.split('Deprecated formats')
152
self.assertContainsRe(new, 'bzr help formats')
153
self.assertContainsRe(new,
154
':knit:\n \(native\) \(default\) Format using knits\n')
155
self.assertContainsRe(experimental,
156
':branch6:\n \(native\) Experimental successor to knit')
157
self.assertContainsRe(deprecated,
158
':lazy:\n \(native\) Format registered lazily\n')
159
self.assertNotContainsRe(new, 'hidden')
161
def test_set_default_repository(self):
162
default_factory = bzrdir.format_registry.get('default')
163
old_default = [k for k, v in bzrdir.format_registry.iteritems()
164
if v == default_factory and k != 'default'][0]
165
bzrdir.format_registry.set_default_repository('dirstate-with-subtree')
167
self.assertIs(bzrdir.format_registry.get('dirstate-with-subtree'),
168
bzrdir.format_registry.get('default'))
170
repository.RepositoryFormat.get_default_format().__class__,
171
knitrepo.RepositoryFormatKnit3)
173
bzrdir.format_registry.set_default_repository(old_default)
175
def test_aliases(self):
176
a_registry = bzrdir.BzrDirFormatRegistry()
177
a_registry.register('weave', bzrdir.BzrDirFormat6,
178
'Pre-0.8 format. Slower and does not support checkouts or shared'
179
' repositories', deprecated=True)
180
a_registry.register('weavealias', bzrdir.BzrDirFormat6,
181
'Pre-0.8 format. Slower and does not support checkouts or shared'
182
' repositories', deprecated=True, alias=True)
183
self.assertEqual(frozenset(['weavealias']), a_registry.aliases())
186
class SampleBranch(bzrlib.branch.Branch):
187
"""A dummy branch for guess what, dummy use."""
189
def __init__(self, dir):
193
class SampleRepository(bzrlib.repository.Repository):
196
def __init__(self, dir):
200
class SampleBzrDir(bzrdir.BzrDir):
201
"""A sample BzrDir implementation to allow testing static methods."""
203
def create_repository(self, shared=False):
204
"""See BzrDir.create_repository."""
205
return "A repository"
207
def open_repository(self):
208
"""See BzrDir.open_repository."""
209
return SampleRepository(self)
211
def create_branch(self):
212
"""See BzrDir.create_branch."""
213
return SampleBranch(self)
215
def create_workingtree(self):
216
"""See BzrDir.create_workingtree."""
220
class SampleBzrDirFormat(bzrdir.BzrDirFormat):
223
this format is initializable, unsupported to aid in testing the
224
open and open_downlevel routines.
227
def get_format_string(self):
228
"""See BzrDirFormat.get_format_string()."""
229
return "Sample .bzr dir format."
231
def initialize_on_transport(self, t):
232
"""Create a bzr dir."""
234
t.put_bytes('.bzr/branch-format', self.get_format_string())
235
return SampleBzrDir(t, self)
237
def is_supported(self):
240
def open(self, transport, _found=None):
241
return "opened branch."
244
class TestBzrDirFormat(TestCaseWithTransport):
245
"""Tests for the BzrDirFormat facility."""
247
def test_find_format(self):
248
# is the right format object found for a branch?
249
# create a branch with a few known format objects.
250
# this is not quite the same as
251
t = get_transport(self.get_url())
252
self.build_tree(["foo/", "bar/"], transport=t)
253
def check_format(format, url):
254
format.initialize(url)
255
t = get_transport(url)
256
found_format = bzrdir.BzrDirFormat.find_format(t)
257
self.failUnless(isinstance(found_format, format.__class__))
258
check_format(bzrdir.BzrDirFormat5(), "foo")
259
check_format(bzrdir.BzrDirFormat6(), "bar")
261
def test_find_format_nothing_there(self):
262
self.assertRaises(NotBranchError,
263
bzrdir.BzrDirFormat.find_format,
266
def test_find_format_unknown_format(self):
267
t = get_transport(self.get_url())
269
t.put_bytes('.bzr/branch-format', '')
270
self.assertRaises(UnknownFormatError,
271
bzrdir.BzrDirFormat.find_format,
274
def test_register_unregister_format(self):
275
format = SampleBzrDirFormat()
278
format.initialize(url)
279
# register a format for it.
280
bzrdir.BzrDirFormat.register_format(format)
281
# which bzrdir.Open will refuse (not supported)
282
self.assertRaises(UnsupportedFormatError, bzrdir.BzrDir.open, url)
283
# which bzrdir.open_containing will refuse (not supported)
284
self.assertRaises(UnsupportedFormatError, bzrdir.BzrDir.open_containing, url)
285
# but open_downlevel will work
286
t = get_transport(url)
287
self.assertEqual(format.open(t), bzrdir.BzrDir.open_unsupported(url))
288
# unregister the format
289
bzrdir.BzrDirFormat.unregister_format(format)
290
# now open_downlevel should fail too.
291
self.assertRaises(UnknownFormatError, bzrdir.BzrDir.open_unsupported, url)
293
def test_create_branch_and_repo_uses_default(self):
294
format = SampleBzrDirFormat()
295
branch = bzrdir.BzrDir.create_branch_and_repo(self.get_url(),
297
self.assertTrue(isinstance(branch, SampleBranch))
299
def test_create_branch_and_repo_under_shared(self):
300
# creating a branch and repo in a shared repo uses the
302
format = bzrdir.format_registry.make_bzrdir('knit')
303
self.make_repository('.', shared=True, format=format)
304
branch = bzrdir.BzrDir.create_branch_and_repo(
305
self.get_url('child'), format=format)
306
self.assertRaises(errors.NoRepositoryPresent,
307
branch.bzrdir.open_repository)
309
def test_create_branch_and_repo_under_shared_force_new(self):
310
# creating a branch and repo in a shared repo can be forced to
312
format = bzrdir.format_registry.make_bzrdir('knit')
313
self.make_repository('.', shared=True, format=format)
314
branch = bzrdir.BzrDir.create_branch_and_repo(self.get_url('child'),
317
branch.bzrdir.open_repository()
319
def test_create_standalone_working_tree(self):
320
format = SampleBzrDirFormat()
321
# note this is deliberately readonly, as this failure should
322
# occur before any writes.
323
self.assertRaises(errors.NotLocalUrl,
324
bzrdir.BzrDir.create_standalone_workingtree,
325
self.get_readonly_url(), format=format)
326
tree = bzrdir.BzrDir.create_standalone_workingtree('.',
328
self.assertEqual('A tree', tree)
330
def test_create_standalone_working_tree_under_shared_repo(self):
331
# create standalone working tree always makes a repo.
332
format = bzrdir.format_registry.make_bzrdir('knit')
333
self.make_repository('.', shared=True, format=format)
334
# note this is deliberately readonly, as this failure should
335
# occur before any writes.
336
self.assertRaises(errors.NotLocalUrl,
337
bzrdir.BzrDir.create_standalone_workingtree,
338
self.get_readonly_url('child'), format=format)
339
tree = bzrdir.BzrDir.create_standalone_workingtree('child',
341
tree.bzrdir.open_repository()
343
def test_create_branch_convenience(self):
344
# outside a repo the default convenience output is a repo+branch_tree
345
format = bzrdir.format_registry.make_bzrdir('knit')
346
branch = bzrdir.BzrDir.create_branch_convenience('.', format=format)
347
branch.bzrdir.open_workingtree()
348
branch.bzrdir.open_repository()
350
def test_create_branch_convenience_possible_transports(self):
351
"""Check that the optional 'possible_transports' is recognized"""
352
format = bzrdir.format_registry.make_bzrdir('knit')
353
t = self.get_transport()
354
branch = bzrdir.BzrDir.create_branch_convenience(
355
'.', format=format, possible_transports=[t])
356
branch.bzrdir.open_workingtree()
357
branch.bzrdir.open_repository()
359
def test_create_branch_convenience_root(self):
360
"""Creating a branch at the root of a fs should work."""
361
self.vfs_transport_factory = MemoryServer
362
# outside a repo the default convenience output is a repo+branch_tree
363
format = bzrdir.format_registry.make_bzrdir('knit')
364
branch = bzrdir.BzrDir.create_branch_convenience(self.get_url(),
366
self.assertRaises(errors.NoWorkingTree,
367
branch.bzrdir.open_workingtree)
368
branch.bzrdir.open_repository()
370
def test_create_branch_convenience_under_shared_repo(self):
371
# inside a repo the default convenience output is a branch+ follow the
373
format = bzrdir.format_registry.make_bzrdir('knit')
374
self.make_repository('.', shared=True, format=format)
375
branch = bzrdir.BzrDir.create_branch_convenience('child',
377
branch.bzrdir.open_workingtree()
378
self.assertRaises(errors.NoRepositoryPresent,
379
branch.bzrdir.open_repository)
381
def test_create_branch_convenience_under_shared_repo_force_no_tree(self):
382
# inside a repo the default convenience output is a branch+ follow the
383
# repo tree policy but we can override that
384
format = bzrdir.format_registry.make_bzrdir('knit')
385
self.make_repository('.', shared=True, format=format)
386
branch = bzrdir.BzrDir.create_branch_convenience('child',
387
force_new_tree=False, format=format)
388
self.assertRaises(errors.NoWorkingTree,
389
branch.bzrdir.open_workingtree)
390
self.assertRaises(errors.NoRepositoryPresent,
391
branch.bzrdir.open_repository)
393
def test_create_branch_convenience_under_shared_repo_no_tree_policy(self):
394
# inside a repo the default convenience output is a branch+ follow the
396
format = bzrdir.format_registry.make_bzrdir('knit')
397
repo = self.make_repository('.', shared=True, format=format)
398
repo.set_make_working_trees(False)
399
branch = bzrdir.BzrDir.create_branch_convenience('child',
401
self.assertRaises(errors.NoWorkingTree,
402
branch.bzrdir.open_workingtree)
403
self.assertRaises(errors.NoRepositoryPresent,
404
branch.bzrdir.open_repository)
406
def test_create_branch_convenience_under_shared_repo_no_tree_policy_force_tree(self):
407
# inside a repo the default convenience output is a branch+ follow the
408
# repo tree policy but we can override that
409
format = bzrdir.format_registry.make_bzrdir('knit')
410
repo = self.make_repository('.', shared=True, format=format)
411
repo.set_make_working_trees(False)
412
branch = bzrdir.BzrDir.create_branch_convenience('child',
413
force_new_tree=True, format=format)
414
branch.bzrdir.open_workingtree()
415
self.assertRaises(errors.NoRepositoryPresent,
416
branch.bzrdir.open_repository)
418
def test_create_branch_convenience_under_shared_repo_force_new_repo(self):
419
# inside a repo the default convenience output is overridable to give
421
format = bzrdir.format_registry.make_bzrdir('knit')
422
self.make_repository('.', shared=True, format=format)
423
branch = bzrdir.BzrDir.create_branch_convenience('child',
424
force_new_repo=True, format=format)
425
branch.bzrdir.open_repository()
426
branch.bzrdir.open_workingtree()
429
class TestRepositoryAcquisitionPolicy(TestCaseWithTransport):
431
def test_acquire_repository_standalone(self):
432
"""The default acquisition policy should create a standalone branch."""
433
my_bzrdir = self.make_bzrdir('.')
434
repo_policy = my_bzrdir.determine_repository_policy()
435
repo = repo_policy.acquire_repository()
436
self.assertEqual(repo.bzrdir.root_transport.base,
437
my_bzrdir.root_transport.base)
438
self.assertFalse(repo.is_shared())
441
def test_determine_stacking_policy(self):
442
parent_bzrdir = self.make_bzrdir('.')
443
child_bzrdir = self.make_bzrdir('child')
444
parent_bzrdir.get_config().set_default_stack_on('http://example.org')
445
repo_policy = child_bzrdir.determine_repository_policy()
446
self.assertEqual('http://example.org', repo_policy._stack_on)
448
def test_determine_stacking_policy_relative(self):
449
parent_bzrdir = self.make_bzrdir('.')
450
child_bzrdir = self.make_bzrdir('child')
451
parent_bzrdir.get_config().set_default_stack_on('child2')
452
repo_policy = child_bzrdir.determine_repository_policy()
453
self.assertEqual('child2', repo_policy._stack_on)
454
self.assertEqual(parent_bzrdir.root_transport.base,
455
repo_policy._stack_on_pwd)
457
def prepare_default_stacking(self, child_format='1.6'):
458
parent_bzrdir = self.make_bzrdir('.')
459
child_branch = self.make_branch('child', format=child_format)
460
parent_bzrdir.get_config().set_default_stack_on(child_branch.base)
461
new_child_transport = parent_bzrdir.transport.clone('child2')
462
return child_branch, new_child_transport
464
def test_clone_on_transport_obeys_stacking_policy(self):
465
child_branch, new_child_transport = self.prepare_default_stacking()
466
new_child = child_branch.bzrdir.clone_on_transport(new_child_transport)
467
self.assertEqual(child_branch.base,
468
new_child.open_branch().get_stacked_on_url())
470
def test_sprout_obeys_stacking_policy(self):
471
child_branch, new_child_transport = self.prepare_default_stacking()
472
new_child = child_branch.bzrdir.sprout(new_child_transport.base)
473
self.assertEqual(child_branch.base,
474
new_child.open_branch().get_stacked_on_url())
476
def test_clone_ignores_policy_for_unsupported_formats(self):
477
child_branch, new_child_transport = self.prepare_default_stacking(
478
child_format='pack-0.92')
479
new_child = child_branch.bzrdir.clone_on_transport(new_child_transport)
480
self.assertRaises(errors.UnstackableBranchFormat,
481
new_child.open_branch().get_stacked_on_url)
483
def test_sprout_ignores_policy_for_unsupported_formats(self):
484
child_branch, new_child_transport = self.prepare_default_stacking(
485
child_format='pack-0.92')
486
new_child = child_branch.bzrdir.sprout(new_child_transport.base)
487
self.assertRaises(errors.UnstackableBranchFormat,
488
new_child.open_branch().get_stacked_on_url)
490
def test_sprout_upgrades_format_if_stacked_specified(self):
491
child_branch, new_child_transport = self.prepare_default_stacking(
492
child_format='pack-0.92')
493
new_child = child_branch.bzrdir.sprout(new_child_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_clone_on_transport_upgrades_format_if_stacked_on_specified(self):
502
child_branch, new_child_transport = self.prepare_default_stacking(
503
child_format='pack-0.92')
504
new_child = child_branch.bzrdir.clone_on_transport(new_child_transport,
505
stacked_on=child_branch.bzrdir.root_transport.base)
506
self.assertEqual(child_branch.bzrdir.root_transport.base,
507
new_child.open_branch().get_stacked_on_url())
508
repo = new_child.open_repository()
509
self.assertTrue(repo._format.supports_external_lookups)
510
self.assertFalse(repo.supports_rich_root())
512
def test_sprout_upgrades_to_rich_root_format_if_needed(self):
513
child_branch, new_child_transport = self.prepare_default_stacking(
514
child_format='rich-root-pack')
515
new_child = child_branch.bzrdir.sprout(new_child_transport.base,
517
repo = new_child.open_repository()
518
self.assertTrue(repo._format.supports_external_lookups)
519
self.assertTrue(repo.supports_rich_root())
521
def test_add_fallback_repo_handles_absolute_urls(self):
522
stack_on = self.make_branch('stack_on', format='1.6')
523
repo = self.make_repository('repo', format='1.6')
524
policy = bzrdir.UseExistingRepository(repo, stack_on.base)
525
policy._add_fallback(repo)
527
def test_add_fallback_repo_handles_relative_urls(self):
528
stack_on = self.make_branch('stack_on', format='1.6')
529
repo = self.make_repository('repo', format='1.6')
530
policy = bzrdir.UseExistingRepository(repo, '.', stack_on.base)
531
policy._add_fallback(repo)
533
def test_configure_relative_branch_stacking_url(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,
538
policy.configure_branch(stacked)
539
self.assertEqual('..', stacked.get_stacked_on_url())
541
def test_relative_branch_stacking_to_absolute(self):
542
stack_on = self.make_branch('stack_on', format='1.6')
543
stacked = self.make_branch('stack_on/stacked', format='1.6')
544
policy = bzrdir.UseExistingRepository(stacked.repository,
545
'.', self.get_readonly_url('stack_on'))
546
policy.configure_branch(stacked)
547
self.assertEqual(self.get_readonly_url('stack_on'),
548
stacked.get_stacked_on_url())
551
class ChrootedTests(TestCaseWithTransport):
552
"""A support class that provides readonly urls outside the local namespace.
554
This is done by checking if self.transport_server is a MemoryServer. if it
555
is then we are chrooted already, if it is not then an HttpServer is used
560
super(ChrootedTests, self).setUp()
561
if not self.vfs_transport_factory == MemoryServer:
562
self.transport_readonly_server = http_server.HttpServer
564
def local_branch_path(self, branch):
565
return os.path.realpath(urlutils.local_path_from_url(branch.base))
567
def test_open_containing(self):
568
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing,
569
self.get_readonly_url(''))
570
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing,
571
self.get_readonly_url('g/p/q'))
572
control = bzrdir.BzrDir.create(self.get_url())
573
branch, relpath = bzrdir.BzrDir.open_containing(self.get_readonly_url(''))
574
self.assertEqual('', relpath)
575
branch, relpath = bzrdir.BzrDir.open_containing(self.get_readonly_url('g/p/q'))
576
self.assertEqual('g/p/q', relpath)
578
def test_open_containing_tree_branch_or_repository_empty(self):
579
self.assertRaises(errors.NotBranchError,
580
bzrdir.BzrDir.open_containing_tree_branch_or_repository,
581
self.get_readonly_url(''))
583
def test_open_containing_tree_branch_or_repository_all(self):
584
self.make_branch_and_tree('topdir')
585
tree, branch, repo, relpath = \
586
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
588
self.assertEqual(os.path.realpath('topdir'),
589
os.path.realpath(tree.basedir))
590
self.assertEqual(os.path.realpath('topdir'),
591
self.local_branch_path(branch))
593
osutils.realpath(os.path.join('topdir', '.bzr', 'repository')),
594
repo.bzrdir.transport.local_abspath('repository'))
595
self.assertEqual(relpath, 'foo')
597
def test_open_containing_tree_branch_or_repository_no_tree(self):
598
self.make_branch('branch')
599
tree, branch, repo, relpath = \
600
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
602
self.assertEqual(tree, None)
603
self.assertEqual(os.path.realpath('branch'),
604
self.local_branch_path(branch))
606
osutils.realpath(os.path.join('branch', '.bzr', 'repository')),
607
repo.bzrdir.transport.local_abspath('repository'))
608
self.assertEqual(relpath, 'foo')
610
def test_open_containing_tree_branch_or_repository_repo(self):
611
self.make_repository('repo')
612
tree, branch, repo, relpath = \
613
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
615
self.assertEqual(tree, None)
616
self.assertEqual(branch, None)
618
osutils.realpath(os.path.join('repo', '.bzr', 'repository')),
619
repo.bzrdir.transport.local_abspath('repository'))
620
self.assertEqual(relpath, '')
622
def test_open_containing_tree_branch_or_repository_shared_repo(self):
623
self.make_repository('shared', shared=True)
624
bzrdir.BzrDir.create_branch_convenience('shared/branch',
625
force_new_tree=False)
626
tree, branch, repo, relpath = \
627
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
629
self.assertEqual(tree, None)
630
self.assertEqual(os.path.realpath('shared/branch'),
631
self.local_branch_path(branch))
633
osutils.realpath(os.path.join('shared', '.bzr', 'repository')),
634
repo.bzrdir.transport.local_abspath('repository'))
635
self.assertEqual(relpath, '')
637
def test_open_containing_tree_branch_or_repository_branch_subdir(self):
638
self.make_branch_and_tree('foo')
639
self.build_tree(['foo/bar/'])
640
tree, branch, repo, relpath = \
641
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
643
self.assertEqual(os.path.realpath('foo'),
644
os.path.realpath(tree.basedir))
645
self.assertEqual(os.path.realpath('foo'),
646
self.local_branch_path(branch))
648
osutils.realpath(os.path.join('foo', '.bzr', 'repository')),
649
repo.bzrdir.transport.local_abspath('repository'))
650
self.assertEqual(relpath, 'bar')
652
def test_open_containing_tree_branch_or_repository_repo_subdir(self):
653
self.make_repository('bar')
654
self.build_tree(['bar/baz/'])
655
tree, branch, repo, relpath = \
656
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
658
self.assertEqual(tree, None)
659
self.assertEqual(branch, None)
661
osutils.realpath(os.path.join('bar', '.bzr', 'repository')),
662
repo.bzrdir.transport.local_abspath('repository'))
663
self.assertEqual(relpath, 'baz')
665
def test_open_containing_from_transport(self):
666
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing_from_transport,
667
get_transport(self.get_readonly_url('')))
668
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing_from_transport,
669
get_transport(self.get_readonly_url('g/p/q')))
670
control = bzrdir.BzrDir.create(self.get_url())
671
branch, relpath = bzrdir.BzrDir.open_containing_from_transport(
672
get_transport(self.get_readonly_url('')))
673
self.assertEqual('', relpath)
674
branch, relpath = bzrdir.BzrDir.open_containing_from_transport(
675
get_transport(self.get_readonly_url('g/p/q')))
676
self.assertEqual('g/p/q', relpath)
678
def test_open_containing_tree_or_branch(self):
679
self.make_branch_and_tree('topdir')
680
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
682
self.assertEqual(os.path.realpath('topdir'),
683
os.path.realpath(tree.basedir))
684
self.assertEqual(os.path.realpath('topdir'),
685
self.local_branch_path(branch))
686
self.assertIs(tree.bzrdir, branch.bzrdir)
687
self.assertEqual('foo', relpath)
688
# opening from non-local should not return the tree
689
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
690
self.get_readonly_url('topdir/foo'))
691
self.assertEqual(None, tree)
692
self.assertEqual('foo', relpath)
694
self.make_branch('topdir/foo')
695
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
697
self.assertIs(tree, None)
698
self.assertEqual(os.path.realpath('topdir/foo'),
699
self.local_branch_path(branch))
700
self.assertEqual('', relpath)
702
def test_open_tree_or_branch(self):
703
self.make_branch_and_tree('topdir')
704
tree, branch = bzrdir.BzrDir.open_tree_or_branch('topdir')
705
self.assertEqual(os.path.realpath('topdir'),
706
os.path.realpath(tree.basedir))
707
self.assertEqual(os.path.realpath('topdir'),
708
self.local_branch_path(branch))
709
self.assertIs(tree.bzrdir, branch.bzrdir)
710
# opening from non-local should not return the tree
711
tree, branch = bzrdir.BzrDir.open_tree_or_branch(
712
self.get_readonly_url('topdir'))
713
self.assertEqual(None, tree)
715
self.make_branch('topdir/foo')
716
tree, branch = bzrdir.BzrDir.open_tree_or_branch('topdir/foo')
717
self.assertIs(tree, None)
718
self.assertEqual(os.path.realpath('topdir/foo'),
719
self.local_branch_path(branch))
721
def test_open_from_transport(self):
722
# transport pointing at bzrdir should give a bzrdir with root transport
723
# set to the given transport
724
control = bzrdir.BzrDir.create(self.get_url())
725
transport = get_transport(self.get_url())
726
opened_bzrdir = bzrdir.BzrDir.open_from_transport(transport)
727
self.assertEqual(transport.base, opened_bzrdir.root_transport.base)
728
self.assertIsInstance(opened_bzrdir, bzrdir.BzrDir)
730
def test_open_from_transport_no_bzrdir(self):
731
transport = get_transport(self.get_url())
732
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport,
735
def test_open_from_transport_bzrdir_in_parent(self):
736
control = bzrdir.BzrDir.create(self.get_url())
737
transport = get_transport(self.get_url())
738
transport.mkdir('subdir')
739
transport = transport.clone('subdir')
740
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport,
743
def test_sprout_recursive(self):
744
tree = self.make_branch_and_tree('tree1', format='dirstate-with-subtree')
745
sub_tree = self.make_branch_and_tree('tree1/subtree',
746
format='dirstate-with-subtree')
747
tree.add_reference(sub_tree)
748
self.build_tree(['tree1/subtree/file'])
750
tree.commit('Initial commit')
751
tree.bzrdir.sprout('tree2')
752
self.failUnlessExists('tree2/subtree/file')
754
def test_cloning_metadir(self):
755
"""Ensure that cloning metadir is suitable"""
756
bzrdir = self.make_bzrdir('bzrdir')
757
bzrdir.cloning_metadir()
758
branch = self.make_branch('branch', format='knit')
759
format = branch.bzrdir.cloning_metadir()
760
self.assertIsInstance(format.workingtree_format,
761
workingtree.WorkingTreeFormat3)
763
def test_sprout_recursive_treeless(self):
764
tree = self.make_branch_and_tree('tree1',
765
format='dirstate-with-subtree')
766
sub_tree = self.make_branch_and_tree('tree1/subtree',
767
format='dirstate-with-subtree')
768
tree.add_reference(sub_tree)
769
self.build_tree(['tree1/subtree/file'])
771
tree.commit('Initial commit')
772
tree.bzrdir.destroy_workingtree()
773
repo = self.make_repository('repo', shared=True,
774
format='dirstate-with-subtree')
775
repo.set_make_working_trees(False)
776
tree.bzrdir.sprout('repo/tree2')
777
self.failUnlessExists('repo/tree2/subtree')
778
self.failIfExists('repo/tree2/subtree/file')
780
def make_foo_bar_baz(self):
781
foo = bzrdir.BzrDir.create_branch_convenience('foo').bzrdir
782
bar = self.make_branch('foo/bar').bzrdir
783
baz = self.make_branch('baz').bzrdir
786
def test_find_bzrdirs(self):
787
foo, bar, baz = self.make_foo_bar_baz()
788
transport = get_transport(self.get_url())
789
self.assertEqualBzrdirs([baz, foo, bar],
790
bzrdir.BzrDir.find_bzrdirs(transport))
792
def test_find_bzrdirs_list_current(self):
793
def list_current(transport):
794
return [s for s in transport.list_dir('') if s != 'baz']
796
foo, bar, baz = self.make_foo_bar_baz()
797
transport = get_transport(self.get_url())
798
self.assertEqualBzrdirs([foo, bar],
799
bzrdir.BzrDir.find_bzrdirs(transport,
800
list_current=list_current))
803
def test_find_bzrdirs_evaluate(self):
804
def evaluate(bzrdir):
806
repo = bzrdir.open_repository()
807
except NoRepositoryPresent:
808
return True, bzrdir.root_transport.base
810
return False, bzrdir.root_transport.base
812
foo, bar, baz = self.make_foo_bar_baz()
813
transport = get_transport(self.get_url())
814
self.assertEqual([baz.root_transport.base, foo.root_transport.base],
815
list(bzrdir.BzrDir.find_bzrdirs(transport,
818
def assertEqualBzrdirs(self, first, second):
820
second = list(second)
821
self.assertEqual(len(first), len(second))
822
for x, y in zip(first, second):
823
self.assertEqual(x.root_transport.base, y.root_transport.base)
825
def test_find_branches(self):
826
root = self.make_repository('', shared=True)
827
foo, bar, baz = self.make_foo_bar_baz()
828
qux = self.make_bzrdir('foo/qux')
829
transport = get_transport(self.get_url())
830
branches = bzrdir.BzrDir.find_branches(transport)
831
self.assertEqual(baz.root_transport.base, branches[0].base)
832
self.assertEqual(foo.root_transport.base, branches[1].base)
833
self.assertEqual(bar.root_transport.base, branches[2].base)
835
# ensure this works without a top-level repo
836
branches = bzrdir.BzrDir.find_branches(transport.clone('foo'))
837
self.assertEqual(foo.root_transport.base, branches[0].base)
838
self.assertEqual(bar.root_transport.base, branches[1].base)
841
class TestMeta1DirFormat(TestCaseWithTransport):
842
"""Tests specific to the meta1 dir format."""
844
def test_right_base_dirs(self):
845
dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
847
branch_base = t.clone('branch').base
848
self.assertEqual(branch_base, dir.get_branch_transport(None).base)
849
self.assertEqual(branch_base,
850
dir.get_branch_transport(bzrlib.branch.BzrBranchFormat5()).base)
851
repository_base = t.clone('repository').base
852
self.assertEqual(repository_base, dir.get_repository_transport(None).base)
853
self.assertEqual(repository_base,
854
dir.get_repository_transport(weaverepo.RepositoryFormat7()).base)
855
checkout_base = t.clone('checkout').base
856
self.assertEqual(checkout_base, dir.get_workingtree_transport(None).base)
857
self.assertEqual(checkout_base,
858
dir.get_workingtree_transport(workingtree.WorkingTreeFormat3()).base)
860
def test_meta1dir_uses_lockdir(self):
861
"""Meta1 format uses a LockDir to guard the whole directory, not a file."""
862
dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
864
self.assertIsDirectory('branch-lock', t)
866
def test_comparison(self):
867
"""Equality and inequality behave properly.
869
Metadirs should compare equal iff they have the same repo, branch and
872
mydir = bzrdir.format_registry.make_bzrdir('knit')
873
self.assertEqual(mydir, mydir)
874
self.assertFalse(mydir != mydir)
875
otherdir = bzrdir.format_registry.make_bzrdir('knit')
876
self.assertEqual(otherdir, mydir)
877
self.assertFalse(otherdir != mydir)
878
otherdir2 = bzrdir.format_registry.make_bzrdir('dirstate-with-subtree')
879
self.assertNotEqual(otherdir2, mydir)
880
self.assertFalse(otherdir2 == mydir)
882
def test_needs_conversion_different_working_tree(self):
883
# meta1dirs need an conversion if any element is not the default.
884
new_format = bzrdir.format_registry.make_bzrdir('dirstate')
885
tree = self.make_branch_and_tree('tree', format='knit')
886
self.assertTrue(tree.bzrdir.needs_format_conversion(
889
def test_initialize_on_format_uses_smart_transport(self):
890
self.setup_smart_server_with_call_log()
891
new_format = bzrdir.format_registry.make_bzrdir('dirstate')
892
transport = self.get_transport('target')
893
transport.ensure_base()
894
self.reset_smart_call_log()
895
instance = new_format.initialize_on_transport(transport)
896
self.assertIsInstance(instance, remote.RemoteBzrDir)
897
rpc_count = len(self.hpss_calls)
898
# This figure represent the amount of work to perform this use case. It
899
# is entirely ok to reduce this number if a test fails due to rpc_count
900
# being too low. If rpc_count increases, more network roundtrips have
901
# become necessary for this use case. Please do not adjust this number
902
# upwards without agreement from bzr's network support maintainers.
903
self.assertEqual(2, rpc_count)
906
class TestFormat5(TestCaseWithTransport):
907
"""Tests specific to the version 5 bzrdir format."""
909
def test_same_lockfiles_between_tree_repo_branch(self):
910
# this checks that only a single lockfiles instance is created
911
# for format 5 objects
912
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
913
def check_dir_components_use_same_lock(dir):
914
ctrl_1 = dir.open_repository().control_files
915
ctrl_2 = dir.open_branch().control_files
916
ctrl_3 = dir.open_workingtree()._control_files
917
self.assertTrue(ctrl_1 is ctrl_2)
918
self.assertTrue(ctrl_2 is ctrl_3)
919
check_dir_components_use_same_lock(dir)
920
# and if we open it normally.
921
dir = bzrdir.BzrDir.open(self.get_url())
922
check_dir_components_use_same_lock(dir)
924
def test_can_convert(self):
925
# format 5 dirs are convertable
926
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
927
self.assertTrue(dir.can_convert_format())
929
def test_needs_conversion(self):
930
# format 5 dirs need a conversion if they are not the default,
932
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
933
# don't need to convert it to itself
934
self.assertFalse(dir.needs_format_conversion(bzrdir.BzrDirFormat5()))
935
# do need to convert it to the current default
936
self.assertTrue(dir.needs_format_conversion(
937
bzrdir.BzrDirFormat.get_default_format()))
940
class TestFormat6(TestCaseWithTransport):
941
"""Tests specific to the version 6 bzrdir format."""
943
def test_same_lockfiles_between_tree_repo_branch(self):
944
# this checks that only a single lockfiles instance is created
945
# for format 6 objects
946
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
947
def check_dir_components_use_same_lock(dir):
948
ctrl_1 = dir.open_repository().control_files
949
ctrl_2 = dir.open_branch().control_files
950
ctrl_3 = dir.open_workingtree()._control_files
951
self.assertTrue(ctrl_1 is ctrl_2)
952
self.assertTrue(ctrl_2 is ctrl_3)
953
check_dir_components_use_same_lock(dir)
954
# and if we open it normally.
955
dir = bzrdir.BzrDir.open(self.get_url())
956
check_dir_components_use_same_lock(dir)
958
def test_can_convert(self):
959
# format 6 dirs are convertable
960
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
961
self.assertTrue(dir.can_convert_format())
963
def test_needs_conversion(self):
964
# format 6 dirs need an conversion if they are not the default.
965
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
966
self.assertTrue(dir.needs_format_conversion(
967
bzrdir.BzrDirFormat.get_default_format()))
970
class NotBzrDir(bzrlib.bzrdir.BzrDir):
971
"""A non .bzr based control directory."""
973
def __init__(self, transport, format):
974
self._format = format
975
self.root_transport = transport
976
self.transport = transport.clone('.not')
979
class NotBzrDirFormat(bzrlib.bzrdir.BzrDirFormat):
980
"""A test class representing any non-.bzr based disk format."""
982
def initialize_on_transport(self, transport):
983
"""Initialize a new .not dir in the base directory of a Transport."""
984
transport.mkdir('.not')
985
return self.open(transport)
987
def open(self, transport):
988
"""Open this directory."""
989
return NotBzrDir(transport, self)
992
def _known_formats(self):
993
return set([NotBzrDirFormat()])
996
def probe_transport(self, transport):
997
"""Our format is present if the transport ends in '.not/'."""
998
if transport.has('.not'):
999
return NotBzrDirFormat()
1002
class TestNotBzrDir(TestCaseWithTransport):
1003
"""Tests for using the bzrdir api with a non .bzr based disk format.
1005
If/when one of these is in the core, we can let the implementation tests
1009
def test_create_and_find_format(self):
1010
# create a .notbzr dir
1011
format = NotBzrDirFormat()
1012
dir = format.initialize(self.get_url())
1013
self.assertIsInstance(dir, NotBzrDir)
1015
bzrlib.bzrdir.BzrDirFormat.register_control_format(format)
1017
found = bzrlib.bzrdir.BzrDirFormat.find_format(
1018
get_transport(self.get_url()))
1019
self.assertIsInstance(found, NotBzrDirFormat)
1021
bzrlib.bzrdir.BzrDirFormat.unregister_control_format(format)
1023
def test_included_in_known_formats(self):
1024
bzrlib.bzrdir.BzrDirFormat.register_control_format(NotBzrDirFormat)
1026
formats = bzrlib.bzrdir.BzrDirFormat.known_formats()
1027
for format in formats:
1028
if isinstance(format, NotBzrDirFormat):
1030
self.fail("No NotBzrDirFormat in %s" % formats)
1032
bzrlib.bzrdir.BzrDirFormat.unregister_control_format(NotBzrDirFormat)
1035
class NonLocalTests(TestCaseWithTransport):
1036
"""Tests for bzrdir static behaviour on non local paths."""
1039
super(NonLocalTests, self).setUp()
1040
self.vfs_transport_factory = MemoryServer
1042
def test_create_branch_convenience(self):
1043
# outside a repo the default convenience output is a repo+branch_tree
1044
format = bzrdir.format_registry.make_bzrdir('knit')
1045
branch = bzrdir.BzrDir.create_branch_convenience(
1046
self.get_url('foo'), format=format)
1047
self.assertRaises(errors.NoWorkingTree,
1048
branch.bzrdir.open_workingtree)
1049
branch.bzrdir.open_repository()
1051
def test_create_branch_convenience_force_tree_not_local_fails(self):
1052
# outside a repo the default convenience output is a repo+branch_tree
1053
format = bzrdir.format_registry.make_bzrdir('knit')
1054
self.assertRaises(errors.NotLocalUrl,
1055
bzrdir.BzrDir.create_branch_convenience,
1056
self.get_url('foo'),
1057
force_new_tree=True,
1059
t = get_transport(self.get_url('.'))
1060
self.assertFalse(t.has('foo'))
1062
def test_clone(self):
1063
# clone into a nonlocal path works
1064
format = bzrdir.format_registry.make_bzrdir('knit')
1065
branch = bzrdir.BzrDir.create_branch_convenience('local',
1067
branch.bzrdir.open_workingtree()
1068
result = branch.bzrdir.clone(self.get_url('remote'))
1069
self.assertRaises(errors.NoWorkingTree,
1070
result.open_workingtree)
1071
result.open_branch()
1072
result.open_repository()
1074
def test_checkout_metadir(self):
1075
# checkout_metadir has reasonable working tree format even when no
1076
# working tree is present
1077
self.make_branch('branch-knit2', format='dirstate-with-subtree')
1078
my_bzrdir = bzrdir.BzrDir.open(self.get_url('branch-knit2'))
1079
checkout_format = my_bzrdir.checkout_metadir()
1080
self.assertIsInstance(checkout_format.workingtree_format,
1081
workingtree.WorkingTreeFormat3)
1084
class TestHTTPRedirections(object):
1085
"""Test redirection between two http servers.
1087
This MUST be used by daughter classes that also inherit from
1088
TestCaseWithTwoWebservers.
1090
We can't inherit directly from TestCaseWithTwoWebservers or the
1091
test framework will try to create an instance which cannot
1092
run, its implementation being incomplete.
1095
def create_transport_readonly_server(self):
1096
return http_utils.HTTPServerRedirecting()
1098
def create_transport_secondary_server(self):
1099
return http_utils.HTTPServerRedirecting()
1102
super(TestHTTPRedirections, self).setUp()
1103
# The redirections will point to the new server
1104
self.new_server = self.get_readonly_server()
1105
# The requests to the old server will be redirected
1106
self.old_server = self.get_secondary_server()
1107
# Configure the redirections
1108
self.old_server.redirect_to(self.new_server.host, self.new_server.port)
1110
def test_loop(self):
1111
# Both servers redirect to each other creating a loop
1112
self.new_server.redirect_to(self.old_server.host, self.old_server.port)
1113
# Starting from either server should loop
1114
old_url = self._qualified_url(self.old_server.host,
1115
self.old_server.port)
1116
oldt = self._transport(old_url)
1117
self.assertRaises(errors.NotBranchError,
1118
bzrdir.BzrDir.open_from_transport, oldt)
1119
new_url = self._qualified_url(self.new_server.host,
1120
self.new_server.port)
1121
newt = self._transport(new_url)
1122
self.assertRaises(errors.NotBranchError,
1123
bzrdir.BzrDir.open_from_transport, newt)
1125
def test_qualifier_preserved(self):
1126
wt = self.make_branch_and_tree('branch')
1127
old_url = self._qualified_url(self.old_server.host,
1128
self.old_server.port)
1129
start = self._transport(old_url).clone('branch')
1130
bdir = bzrdir.BzrDir.open_from_transport(start)
1131
# Redirection should preserve the qualifier, hence the transport class
1133
self.assertIsInstance(bdir.root_transport, type(start))
1136
class TestHTTPRedirections_urllib(TestHTTPRedirections,
1137
http_utils.TestCaseWithTwoWebservers):
1138
"""Tests redirections for urllib implementation"""
1140
_transport = HttpTransport_urllib
1142
def _qualified_url(self, host, port):
1143
return 'http+urllib://%s:%s' % (host, port)
1147
class TestHTTPRedirections_pycurl(TestWithTransport_pycurl,
1148
TestHTTPRedirections,
1149
http_utils.TestCaseWithTwoWebservers):
1150
"""Tests redirections for pycurl implementation"""
1152
def _qualified_url(self, host, port):
1153
return 'http+pycurl://%s:%s' % (host, port)
1156
class TestHTTPRedirections_nosmart(TestHTTPRedirections,
1157
http_utils.TestCaseWithTwoWebservers):
1158
"""Tests redirections for the nosmart decorator"""
1160
_transport = NoSmartTransportDecorator
1162
def _qualified_url(self, host, port):
1163
return 'nosmart+http://%s:%s' % (host, port)
1166
class TestHTTPRedirections_readonly(TestHTTPRedirections,
1167
http_utils.TestCaseWithTwoWebservers):
1168
"""Tests redirections for readonly decoratror"""
1170
_transport = ReadonlyTransportDecorator
1172
def _qualified_url(self, host, port):
1173
return 'readonly+http://%s:%s' % (host, port)
1176
class TestDotBzrHidden(TestCaseWithTransport):
1179
if sys.platform == 'win32':
1180
ls = [os.environ['COMSPEC'], '/C', 'dir', '/B']
1183
f = subprocess.Popen(self.ls, stdout=subprocess.PIPE,
1184
stderr=subprocess.PIPE)
1185
out, err = f.communicate()
1186
self.assertEqual(0, f.returncode, 'Calling %s failed: %s'
1188
return out.splitlines()
1190
def test_dot_bzr_hidden(self):
1191
if sys.platform == 'win32' and not win32utils.has_win32file:
1192
raise TestSkipped('unable to make file hidden without pywin32 library')
1193
b = bzrdir.BzrDir.create('.')
1194
self.build_tree(['a'])
1195
self.assertEquals(['a'], self.get_ls())
1197
def test_dot_bzr_hidden_with_url(self):
1198
if sys.platform == 'win32' and not win32utils.has_win32file:
1199
raise TestSkipped('unable to make file hidden without pywin32 library')
1200
b = bzrdir.BzrDir.create(urlutils.local_path_to_url('.'))
1201
self.build_tree(['a'])
1202
self.assertEquals(['a'], self.get_ls())
1205
class _TestBzrDirFormat(bzrdir.BzrDirMetaFormat1):
1206
"""Test BzrDirFormat implementation for TestBzrDirSprout."""
1208
def _open(self, transport):
1209
return _TestBzrDir(transport, self)
1212
class _TestBzrDir(bzrdir.BzrDirMeta1):
1213
"""Test BzrDir implementation for TestBzrDirSprout.
1215
When created a _TestBzrDir already has repository and a branch. The branch
1216
is a test double as well.
1219
def __init__(self, *args, **kwargs):
1220
super(_TestBzrDir, self).__init__(*args, **kwargs)
1221
self.test_branch = _TestBranch()
1222
self.test_branch.repository = self.create_repository()
1224
def open_branch(self, unsupported=False):
1225
return self.test_branch
1227
def cloning_metadir(self, require_stacking=False):
1228
return _TestBzrDirFormat()
1231
class _TestBranch(bzrlib.branch.Branch):
1232
"""Test Branch implementation for TestBzrDirSprout."""
1234
def __init__(self, *args, **kwargs):
1235
super(_TestBranch, self).__init__(*args, **kwargs)
1239
def sprout(self, *args, **kwargs):
1240
self.calls.append('sprout')
1241
return _TestBranch()
1243
def copy_content_into(self, destination, revision_id=None):
1244
self.calls.append('copy_content_into')
1246
def get_parent(self):
1249
def set_parent(self, parent):
1250
self._parent = parent
1253
class TestBzrDirSprout(TestCaseWithMemoryTransport):
1255
def test_sprout_uses_branch_sprout(self):
1256
"""BzrDir.sprout calls Branch.sprout.
1258
Usually, BzrDir.sprout should delegate to the branch's sprout method
1259
for part of the work. This allows the source branch to control the
1260
choice of format for the new branch.
1262
There are exceptions, but this tests avoids them:
1263
- if there's no branch in the source bzrdir,
1264
- or if the stacking has been requested and the format needs to be
1265
overridden to satisfy that.
1267
# Make an instrumented bzrdir.
1268
t = self.get_transport('source')
1270
source_bzrdir = _TestBzrDirFormat().initialize_on_transport(t)
1271
# The instrumented bzrdir has a test_branch attribute that logs calls
1272
# made to the branch contained in that bzrdir. Initially the test
1273
# branch exists but no calls have been made to it.
1274
self.assertEqual([], source_bzrdir.test_branch.calls)
1277
target_url = self.get_url('target')
1278
result = source_bzrdir.sprout(target_url, recurse='no')
1280
# The bzrdir called the branch's sprout method.
1281
self.assertSubset(['sprout'], source_bzrdir.test_branch.calls)
1283
def test_sprout_parent(self):
1284
grandparent_tree = self.make_branch('grandparent')
1285
parent = grandparent_tree.bzrdir.sprout('parent').open_branch()
1286
branch_tree = parent.bzrdir.sprout('branch').open_branch()
1287
self.assertContainsRe(branch_tree.get_parent(), '/parent/$')