1
# Copyright (C) 2006-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
"""Tests for the BzrDir facility and any format specific tests.
19
For interface contract tests, see tests/per_bzr_dir.
38
from bzrlib.errors import (NotBranchError,
39
NoColocatedBranchSupport,
41
UnsupportedFormatError,
43
from bzrlib.tests import (
45
TestCaseWithMemoryTransport,
46
TestCaseWithTransport,
49
from bzrlib.tests import(
53
from bzrlib.tests.test_http import TestWithTransport_pycurl
54
from bzrlib.transport import (
58
from bzrlib.transport.http._urllib import HttpTransport_urllib
59
from bzrlib.transport.nosmart import NoSmartTransportDecorator
60
from bzrlib.transport.readonly import ReadonlyTransportDecorator
61
from bzrlib.repofmt import knitrepo, weaverepo, pack_repo
64
class TestDefaultFormat(TestCase):
66
def test_get_set_default_format(self):
67
old_format = bzrdir.BzrDirFormat.get_default_format()
68
# default is BzrDirFormat6
69
self.failUnless(isinstance(old_format, bzrdir.BzrDirMetaFormat1))
70
bzrdir.BzrDirFormat._set_default_format(SampleBzrDirFormat())
71
# creating a bzr dir should now create an instrumented dir.
73
result = bzrdir.BzrDir.create('memory:///')
74
self.failUnless(isinstance(result, SampleBzrDir))
76
bzrdir.BzrDirFormat._set_default_format(old_format)
77
self.assertEqual(old_format, bzrdir.BzrDirFormat.get_default_format())
80
class TestFormatRegistry(TestCase):
82
def make_format_registry(self):
83
my_format_registry = bzrdir.BzrDirFormatRegistry()
84
my_format_registry.register('weave', bzrdir.BzrDirFormat6,
85
'Pre-0.8 format. Slower and does not support checkouts or shared'
86
' repositories', deprecated=True)
87
my_format_registry.register_lazy('lazy', 'bzrlib.bzrdir',
88
'BzrDirFormat6', 'Format registered lazily', deprecated=True)
89
my_format_registry.register_metadir('knit',
90
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
93
my_format_registry.set_default('knit')
94
my_format_registry.register_metadir(
96
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
97
'Experimental successor to knit. Use at your own risk.',
98
branch_format='bzrlib.branch.BzrBranchFormat6',
100
my_format_registry.register_metadir(
102
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
103
'Experimental successor to knit. Use at your own risk.',
104
branch_format='bzrlib.branch.BzrBranchFormat6', hidden=True)
105
my_format_registry.register('hiddenweave', bzrdir.BzrDirFormat6,
106
'Pre-0.8 format. Slower and does not support checkouts or shared'
107
' repositories', hidden=True)
108
my_format_registry.register_lazy('hiddenlazy', 'bzrlib.bzrdir',
109
'BzrDirFormat6', 'Format registered lazily', deprecated=True,
111
return my_format_registry
113
def test_format_registry(self):
114
my_format_registry = self.make_format_registry()
115
my_bzrdir = my_format_registry.make_bzrdir('lazy')
116
self.assertIsInstance(my_bzrdir, bzrdir.BzrDirFormat6)
117
my_bzrdir = my_format_registry.make_bzrdir('weave')
118
self.assertIsInstance(my_bzrdir, bzrdir.BzrDirFormat6)
119
my_bzrdir = my_format_registry.make_bzrdir('default')
120
self.assertIsInstance(my_bzrdir.repository_format,
121
knitrepo.RepositoryFormatKnit1)
122
my_bzrdir = my_format_registry.make_bzrdir('knit')
123
self.assertIsInstance(my_bzrdir.repository_format,
124
knitrepo.RepositoryFormatKnit1)
125
my_bzrdir = my_format_registry.make_bzrdir('branch6')
126
self.assertIsInstance(my_bzrdir.get_branch_format(),
127
bzrlib.branch.BzrBranchFormat6)
129
def test_get_help(self):
130
my_format_registry = self.make_format_registry()
131
self.assertEqual('Format registered lazily',
132
my_format_registry.get_help('lazy'))
133
self.assertEqual('Format using knits',
134
my_format_registry.get_help('knit'))
135
self.assertEqual('Format using knits',
136
my_format_registry.get_help('default'))
137
self.assertEqual('Pre-0.8 format. Slower and does not support'
138
' checkouts or shared repositories',
139
my_format_registry.get_help('weave'))
141
def test_help_topic(self):
142
topics = help_topics.HelpTopicRegistry()
143
registry = self.make_format_registry()
144
topics.register('current-formats', registry.help_topic,
146
topics.register('other-formats', registry.help_topic,
148
new = topics.get_detail('current-formats')
149
rest = topics.get_detail('other-formats')
150
experimental, deprecated = rest.split('Deprecated formats')
151
self.assertContainsRe(new, 'formats-help')
152
self.assertContainsRe(new,
153
':knit:\n \(native\) \(default\) Format using knits\n')
154
self.assertContainsRe(experimental,
155
':branch6:\n \(native\) Experimental successor to knit')
156
self.assertContainsRe(deprecated,
157
':lazy:\n \(native\) Format registered lazily\n')
158
self.assertNotContainsRe(new, 'hidden')
160
def test_set_default_repository(self):
161
default_factory = bzrdir.format_registry.get('default')
162
old_default = [k for k, v in bzrdir.format_registry.iteritems()
163
if v == default_factory and k != 'default'][0]
164
bzrdir.format_registry.set_default_repository('dirstate-with-subtree')
166
self.assertIs(bzrdir.format_registry.get('dirstate-with-subtree'),
167
bzrdir.format_registry.get('default'))
169
repository.RepositoryFormat.get_default_format().__class__,
170
knitrepo.RepositoryFormatKnit3)
172
bzrdir.format_registry.set_default_repository(old_default)
174
def test_aliases(self):
175
a_registry = bzrdir.BzrDirFormatRegistry()
176
a_registry.register('weave', bzrdir.BzrDirFormat6,
177
'Pre-0.8 format. Slower and does not support checkouts or shared'
178
' repositories', deprecated=True)
179
a_registry.register('weavealias', bzrdir.BzrDirFormat6,
180
'Pre-0.8 format. Slower and does not support checkouts or shared'
181
' repositories', deprecated=True, alias=True)
182
self.assertEqual(frozenset(['weavealias']), a_registry.aliases())
185
class SampleBranch(bzrlib.branch.Branch):
186
"""A dummy branch for guess what, dummy use."""
188
def __init__(self, dir):
192
class SampleRepository(bzrlib.repository.Repository):
195
def __init__(self, dir):
199
class SampleBzrDir(bzrdir.BzrDir):
200
"""A sample BzrDir implementation to allow testing static methods."""
202
def create_repository(self, shared=False):
203
"""See BzrDir.create_repository."""
204
return "A repository"
206
def open_repository(self):
207
"""See BzrDir.open_repository."""
208
return SampleRepository(self)
210
def create_branch(self, name=None):
211
"""See BzrDir.create_branch."""
213
raise NoColocatedBranchSupport(self)
214
return SampleBranch(self)
216
def create_workingtree(self):
217
"""See BzrDir.create_workingtree."""
221
class SampleBzrDirFormat(bzrdir.BzrDirFormat):
224
this format is initializable, unsupported to aid in testing the
225
open and open_downlevel routines.
228
def get_format_string(self):
229
"""See BzrDirFormat.get_format_string()."""
230
return "Sample .bzr dir format."
232
def initialize_on_transport(self, t):
233
"""Create a bzr dir."""
235
t.put_bytes('.bzr/branch-format', self.get_format_string())
236
return SampleBzrDir(t, self)
238
def is_supported(self):
241
def open(self, transport, _found=None):
242
return "opened branch."
245
class TestBzrDirFormat(TestCaseWithTransport):
246
"""Tests for the BzrDirFormat facility."""
248
def test_find_format(self):
249
# is the right format object found for a branch?
250
# create a branch with a few known format objects.
251
# this is not quite the same as
252
t = get_transport(self.get_url())
253
self.build_tree(["foo/", "bar/"], transport=t)
254
def check_format(format, url):
255
format.initialize(url)
256
t = get_transport(url)
257
found_format = bzrdir.BzrDirFormat.find_format(t)
258
self.failUnless(isinstance(found_format, format.__class__))
259
check_format(bzrdir.BzrDirFormat5(), "foo")
260
check_format(bzrdir.BzrDirFormat6(), "bar")
262
def test_find_format_nothing_there(self):
263
self.assertRaises(NotBranchError,
264
bzrdir.BzrDirFormat.find_format,
267
def test_find_format_unknown_format(self):
268
t = get_transport(self.get_url())
270
t.put_bytes('.bzr/branch-format', '')
271
self.assertRaises(UnknownFormatError,
272
bzrdir.BzrDirFormat.find_format,
275
def test_register_unregister_format(self):
276
format = SampleBzrDirFormat()
279
format.initialize(url)
280
# register a format for it.
281
bzrdir.BzrDirFormat.register_format(format)
282
# which bzrdir.Open will refuse (not supported)
283
self.assertRaises(UnsupportedFormatError, bzrdir.BzrDir.open, url)
284
# which bzrdir.open_containing will refuse (not supported)
285
self.assertRaises(UnsupportedFormatError, bzrdir.BzrDir.open_containing, url)
286
# but open_downlevel will work
287
t = get_transport(url)
288
self.assertEqual(format.open(t), bzrdir.BzrDir.open_unsupported(url))
289
# unregister the format
290
bzrdir.BzrDirFormat.unregister_format(format)
291
# now open_downlevel should fail too.
292
self.assertRaises(UnknownFormatError, bzrdir.BzrDir.open_unsupported, url)
294
def test_create_branch_and_repo_uses_default(self):
295
format = SampleBzrDirFormat()
296
branch = bzrdir.BzrDir.create_branch_and_repo(self.get_url(),
298
self.assertTrue(isinstance(branch, SampleBranch))
300
def test_create_branch_and_repo_under_shared(self):
301
# creating a branch and repo in a shared repo uses the
303
format = bzrdir.format_registry.make_bzrdir('knit')
304
self.make_repository('.', shared=True, format=format)
305
branch = bzrdir.BzrDir.create_branch_and_repo(
306
self.get_url('child'), format=format)
307
self.assertRaises(errors.NoRepositoryPresent,
308
branch.bzrdir.open_repository)
310
def test_create_branch_and_repo_under_shared_force_new(self):
311
# creating a branch and repo in a shared repo can be forced to
313
format = bzrdir.format_registry.make_bzrdir('knit')
314
self.make_repository('.', shared=True, format=format)
315
branch = bzrdir.BzrDir.create_branch_and_repo(self.get_url('child'),
318
branch.bzrdir.open_repository()
320
def test_create_standalone_working_tree(self):
321
format = SampleBzrDirFormat()
322
# note this is deliberately readonly, as this failure should
323
# occur before any writes.
324
self.assertRaises(errors.NotLocalUrl,
325
bzrdir.BzrDir.create_standalone_workingtree,
326
self.get_readonly_url(), format=format)
327
tree = bzrdir.BzrDir.create_standalone_workingtree('.',
329
self.assertEqual('A tree', tree)
331
def test_create_standalone_working_tree_under_shared_repo(self):
332
# create standalone working tree always makes a repo.
333
format = bzrdir.format_registry.make_bzrdir('knit')
334
self.make_repository('.', shared=True, format=format)
335
# note this is deliberately readonly, as this failure should
336
# occur before any writes.
337
self.assertRaises(errors.NotLocalUrl,
338
bzrdir.BzrDir.create_standalone_workingtree,
339
self.get_readonly_url('child'), format=format)
340
tree = bzrdir.BzrDir.create_standalone_workingtree('child',
342
tree.bzrdir.open_repository()
344
def test_create_branch_convenience(self):
345
# outside a repo the default convenience output is a repo+branch_tree
346
format = bzrdir.format_registry.make_bzrdir('knit')
347
branch = bzrdir.BzrDir.create_branch_convenience('.', format=format)
348
branch.bzrdir.open_workingtree()
349
branch.bzrdir.open_repository()
351
def test_create_branch_convenience_possible_transports(self):
352
"""Check that the optional 'possible_transports' is recognized"""
353
format = bzrdir.format_registry.make_bzrdir('knit')
354
t = self.get_transport()
355
branch = bzrdir.BzrDir.create_branch_convenience(
356
'.', format=format, possible_transports=[t])
357
branch.bzrdir.open_workingtree()
358
branch.bzrdir.open_repository()
360
def test_create_branch_convenience_root(self):
361
"""Creating a branch at the root of a fs should work."""
362
self.vfs_transport_factory = memory.MemoryServer
363
# outside a repo the default convenience output is a repo+branch_tree
364
format = bzrdir.format_registry.make_bzrdir('knit')
365
branch = bzrdir.BzrDir.create_branch_convenience(self.get_url(),
367
self.assertRaises(errors.NoWorkingTree,
368
branch.bzrdir.open_workingtree)
369
branch.bzrdir.open_repository()
371
def test_create_branch_convenience_under_shared_repo(self):
372
# inside a repo the default convenience output is a branch+ follow the
374
format = bzrdir.format_registry.make_bzrdir('knit')
375
self.make_repository('.', shared=True, format=format)
376
branch = bzrdir.BzrDir.create_branch_convenience('child',
378
branch.bzrdir.open_workingtree()
379
self.assertRaises(errors.NoRepositoryPresent,
380
branch.bzrdir.open_repository)
382
def test_create_branch_convenience_under_shared_repo_force_no_tree(self):
383
# inside a repo the default convenience output is a branch+ follow the
384
# repo tree policy but we can override that
385
format = bzrdir.format_registry.make_bzrdir('knit')
386
self.make_repository('.', shared=True, format=format)
387
branch = bzrdir.BzrDir.create_branch_convenience('child',
388
force_new_tree=False, format=format)
389
self.assertRaises(errors.NoWorkingTree,
390
branch.bzrdir.open_workingtree)
391
self.assertRaises(errors.NoRepositoryPresent,
392
branch.bzrdir.open_repository)
394
def test_create_branch_convenience_under_shared_repo_no_tree_policy(self):
395
# inside a repo the default convenience output is a branch+ follow the
397
format = bzrdir.format_registry.make_bzrdir('knit')
398
repo = self.make_repository('.', shared=True, format=format)
399
repo.set_make_working_trees(False)
400
branch = bzrdir.BzrDir.create_branch_convenience('child',
402
self.assertRaises(errors.NoWorkingTree,
403
branch.bzrdir.open_workingtree)
404
self.assertRaises(errors.NoRepositoryPresent,
405
branch.bzrdir.open_repository)
407
def test_create_branch_convenience_under_shared_repo_no_tree_policy_force_tree(self):
408
# inside a repo the default convenience output is a branch+ follow the
409
# repo tree policy but we can override that
410
format = bzrdir.format_registry.make_bzrdir('knit')
411
repo = self.make_repository('.', shared=True, format=format)
412
repo.set_make_working_trees(False)
413
branch = bzrdir.BzrDir.create_branch_convenience('child',
414
force_new_tree=True, format=format)
415
branch.bzrdir.open_workingtree()
416
self.assertRaises(errors.NoRepositoryPresent,
417
branch.bzrdir.open_repository)
419
def test_create_branch_convenience_under_shared_repo_force_new_repo(self):
420
# inside a repo the default convenience output is overridable to give
422
format = bzrdir.format_registry.make_bzrdir('knit')
423
self.make_repository('.', shared=True, format=format)
424
branch = bzrdir.BzrDir.create_branch_convenience('child',
425
force_new_repo=True, format=format)
426
branch.bzrdir.open_repository()
427
branch.bzrdir.open_workingtree()
430
class TestRepositoryAcquisitionPolicy(TestCaseWithTransport):
432
def test_acquire_repository_standalone(self):
433
"""The default acquisition policy should create a standalone branch."""
434
my_bzrdir = self.make_bzrdir('.')
435
repo_policy = my_bzrdir.determine_repository_policy()
436
repo, is_new = repo_policy.acquire_repository()
437
self.assertEqual(repo.bzrdir.root_transport.base,
438
my_bzrdir.root_transport.base)
439
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_default_stacking_with_stackable_branch_unstackable_repo(self):
471
# Make stackable source branch with an unstackable repo format.
472
source_bzrdir = self.make_bzrdir('source')
473
pack_repo.RepositoryFormatKnitPack1().initialize(source_bzrdir)
474
source_branch = bzrlib.branch.BzrBranchFormat7().initialize(source_bzrdir)
475
# Make a directory with a default stacking policy
476
parent_bzrdir = self.make_bzrdir('parent')
477
stacked_on = self.make_branch('parent/stacked-on', format='pack-0.92')
478
parent_bzrdir.get_config().set_default_stack_on(stacked_on.base)
479
# Clone source into directory
480
target = source_bzrdir.clone(self.get_url('parent/target'))
482
def test_sprout_obeys_stacking_policy(self):
483
child_branch, new_child_transport = self.prepare_default_stacking()
484
new_child = child_branch.bzrdir.sprout(new_child_transport.base)
485
self.assertEqual(child_branch.base,
486
new_child.open_branch().get_stacked_on_url())
488
def test_clone_ignores_policy_for_unsupported_formats(self):
489
child_branch, new_child_transport = self.prepare_default_stacking(
490
child_format='pack-0.92')
491
new_child = child_branch.bzrdir.clone_on_transport(new_child_transport)
492
self.assertRaises(errors.UnstackableBranchFormat,
493
new_child.open_branch().get_stacked_on_url)
495
def test_sprout_ignores_policy_for_unsupported_formats(self):
496
child_branch, new_child_transport = self.prepare_default_stacking(
497
child_format='pack-0.92')
498
new_child = child_branch.bzrdir.sprout(new_child_transport.base)
499
self.assertRaises(errors.UnstackableBranchFormat,
500
new_child.open_branch().get_stacked_on_url)
502
def test_sprout_upgrades_format_if_stacked_specified(self):
503
child_branch, new_child_transport = self.prepare_default_stacking(
504
child_format='pack-0.92')
505
new_child = child_branch.bzrdir.sprout(new_child_transport.base,
507
self.assertEqual(child_branch.bzrdir.root_transport.base,
508
new_child.open_branch().get_stacked_on_url())
509
repo = new_child.open_repository()
510
self.assertTrue(repo._format.supports_external_lookups)
511
self.assertFalse(repo.supports_rich_root())
513
def test_clone_on_transport_upgrades_format_if_stacked_on_specified(self):
514
child_branch, new_child_transport = self.prepare_default_stacking(
515
child_format='pack-0.92')
516
new_child = child_branch.bzrdir.clone_on_transport(new_child_transport,
517
stacked_on=child_branch.bzrdir.root_transport.base)
518
self.assertEqual(child_branch.bzrdir.root_transport.base,
519
new_child.open_branch().get_stacked_on_url())
520
repo = new_child.open_repository()
521
self.assertTrue(repo._format.supports_external_lookups)
522
self.assertFalse(repo.supports_rich_root())
524
def test_sprout_upgrades_to_rich_root_format_if_needed(self):
525
child_branch, new_child_transport = self.prepare_default_stacking(
526
child_format='rich-root-pack')
527
new_child = child_branch.bzrdir.sprout(new_child_transport.base,
529
repo = new_child.open_repository()
530
self.assertTrue(repo._format.supports_external_lookups)
531
self.assertTrue(repo.supports_rich_root())
533
def test_add_fallback_repo_handles_absolute_urls(self):
534
stack_on = self.make_branch('stack_on', format='1.6')
535
repo = self.make_repository('repo', format='1.6')
536
policy = bzrdir.UseExistingRepository(repo, stack_on.base)
537
policy._add_fallback(repo)
539
def test_add_fallback_repo_handles_relative_urls(self):
540
stack_on = self.make_branch('stack_on', format='1.6')
541
repo = self.make_repository('repo', format='1.6')
542
policy = bzrdir.UseExistingRepository(repo, '.', stack_on.base)
543
policy._add_fallback(repo)
545
def test_configure_relative_branch_stacking_url(self):
546
stack_on = self.make_branch('stack_on', format='1.6')
547
stacked = self.make_branch('stack_on/stacked', format='1.6')
548
policy = bzrdir.UseExistingRepository(stacked.repository,
550
policy.configure_branch(stacked)
551
self.assertEqual('..', stacked.get_stacked_on_url())
553
def test_relative_branch_stacking_to_absolute(self):
554
stack_on = self.make_branch('stack_on', format='1.6')
555
stacked = self.make_branch('stack_on/stacked', format='1.6')
556
policy = bzrdir.UseExistingRepository(stacked.repository,
557
'.', self.get_readonly_url('stack_on'))
558
policy.configure_branch(stacked)
559
self.assertEqual(self.get_readonly_url('stack_on'),
560
stacked.get_stacked_on_url())
563
class ChrootedTests(TestCaseWithTransport):
564
"""A support class that provides readonly urls outside the local namespace.
566
This is done by checking if self.transport_server is a MemoryServer. if it
567
is then we are chrooted already, if it is not then an HttpServer is used
572
super(ChrootedTests, self).setUp()
573
if not self.vfs_transport_factory == memory.MemoryServer:
574
self.transport_readonly_server = http_server.HttpServer
576
def local_branch_path(self, branch):
577
return os.path.realpath(urlutils.local_path_from_url(branch.base))
579
def test_open_containing(self):
580
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing,
581
self.get_readonly_url(''))
582
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing,
583
self.get_readonly_url('g/p/q'))
584
control = bzrdir.BzrDir.create(self.get_url())
585
branch, relpath = bzrdir.BzrDir.open_containing(self.get_readonly_url(''))
586
self.assertEqual('', relpath)
587
branch, relpath = bzrdir.BzrDir.open_containing(self.get_readonly_url('g/p/q'))
588
self.assertEqual('g/p/q', relpath)
590
def test_open_containing_tree_branch_or_repository_empty(self):
591
self.assertRaises(errors.NotBranchError,
592
bzrdir.BzrDir.open_containing_tree_branch_or_repository,
593
self.get_readonly_url(''))
595
def test_open_containing_tree_branch_or_repository_all(self):
596
self.make_branch_and_tree('topdir')
597
tree, branch, repo, relpath = \
598
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
600
self.assertEqual(os.path.realpath('topdir'),
601
os.path.realpath(tree.basedir))
602
self.assertEqual(os.path.realpath('topdir'),
603
self.local_branch_path(branch))
605
osutils.realpath(os.path.join('topdir', '.bzr', 'repository')),
606
repo.bzrdir.transport.local_abspath('repository'))
607
self.assertEqual(relpath, 'foo')
609
def test_open_containing_tree_branch_or_repository_no_tree(self):
610
self.make_branch('branch')
611
tree, branch, repo, relpath = \
612
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
614
self.assertEqual(tree, None)
615
self.assertEqual(os.path.realpath('branch'),
616
self.local_branch_path(branch))
618
osutils.realpath(os.path.join('branch', '.bzr', 'repository')),
619
repo.bzrdir.transport.local_abspath('repository'))
620
self.assertEqual(relpath, 'foo')
622
def test_open_containing_tree_branch_or_repository_repo(self):
623
self.make_repository('repo')
624
tree, branch, repo, relpath = \
625
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
627
self.assertEqual(tree, None)
628
self.assertEqual(branch, None)
630
osutils.realpath(os.path.join('repo', '.bzr', 'repository')),
631
repo.bzrdir.transport.local_abspath('repository'))
632
self.assertEqual(relpath, '')
634
def test_open_containing_tree_branch_or_repository_shared_repo(self):
635
self.make_repository('shared', shared=True)
636
bzrdir.BzrDir.create_branch_convenience('shared/branch',
637
force_new_tree=False)
638
tree, branch, repo, relpath = \
639
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
641
self.assertEqual(tree, None)
642
self.assertEqual(os.path.realpath('shared/branch'),
643
self.local_branch_path(branch))
645
osutils.realpath(os.path.join('shared', '.bzr', 'repository')),
646
repo.bzrdir.transport.local_abspath('repository'))
647
self.assertEqual(relpath, '')
649
def test_open_containing_tree_branch_or_repository_branch_subdir(self):
650
self.make_branch_and_tree('foo')
651
self.build_tree(['foo/bar/'])
652
tree, branch, repo, relpath = \
653
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
655
self.assertEqual(os.path.realpath('foo'),
656
os.path.realpath(tree.basedir))
657
self.assertEqual(os.path.realpath('foo'),
658
self.local_branch_path(branch))
660
osutils.realpath(os.path.join('foo', '.bzr', 'repository')),
661
repo.bzrdir.transport.local_abspath('repository'))
662
self.assertEqual(relpath, 'bar')
664
def test_open_containing_tree_branch_or_repository_repo_subdir(self):
665
self.make_repository('bar')
666
self.build_tree(['bar/baz/'])
667
tree, branch, repo, relpath = \
668
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
670
self.assertEqual(tree, None)
671
self.assertEqual(branch, None)
673
osutils.realpath(os.path.join('bar', '.bzr', 'repository')),
674
repo.bzrdir.transport.local_abspath('repository'))
675
self.assertEqual(relpath, 'baz')
677
def test_open_containing_from_transport(self):
678
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing_from_transport,
679
get_transport(self.get_readonly_url('')))
680
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing_from_transport,
681
get_transport(self.get_readonly_url('g/p/q')))
682
control = bzrdir.BzrDir.create(self.get_url())
683
branch, relpath = bzrdir.BzrDir.open_containing_from_transport(
684
get_transport(self.get_readonly_url('')))
685
self.assertEqual('', relpath)
686
branch, relpath = bzrdir.BzrDir.open_containing_from_transport(
687
get_transport(self.get_readonly_url('g/p/q')))
688
self.assertEqual('g/p/q', relpath)
690
def test_open_containing_tree_or_branch(self):
691
self.make_branch_and_tree('topdir')
692
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
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
self.assertEqual('foo', relpath)
700
# opening from non-local should not return the tree
701
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
702
self.get_readonly_url('topdir/foo'))
703
self.assertEqual(None, tree)
704
self.assertEqual('foo', relpath)
706
self.make_branch('topdir/foo')
707
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
709
self.assertIs(tree, None)
710
self.assertEqual(os.path.realpath('topdir/foo'),
711
self.local_branch_path(branch))
712
self.assertEqual('', relpath)
714
def test_open_tree_or_branch(self):
715
self.make_branch_and_tree('topdir')
716
tree, branch = bzrdir.BzrDir.open_tree_or_branch('topdir')
717
self.assertEqual(os.path.realpath('topdir'),
718
os.path.realpath(tree.basedir))
719
self.assertEqual(os.path.realpath('topdir'),
720
self.local_branch_path(branch))
721
self.assertIs(tree.bzrdir, branch.bzrdir)
722
# opening from non-local should not return the tree
723
tree, branch = bzrdir.BzrDir.open_tree_or_branch(
724
self.get_readonly_url('topdir'))
725
self.assertEqual(None, tree)
727
self.make_branch('topdir/foo')
728
tree, branch = bzrdir.BzrDir.open_tree_or_branch('topdir/foo')
729
self.assertIs(tree, None)
730
self.assertEqual(os.path.realpath('topdir/foo'),
731
self.local_branch_path(branch))
733
def test_open_from_transport(self):
734
# transport pointing at bzrdir should give a bzrdir with root transport
735
# set to the given transport
736
control = bzrdir.BzrDir.create(self.get_url())
737
transport = get_transport(self.get_url())
738
opened_bzrdir = bzrdir.BzrDir.open_from_transport(transport)
739
self.assertEqual(transport.base, opened_bzrdir.root_transport.base)
740
self.assertIsInstance(opened_bzrdir, bzrdir.BzrDir)
742
def test_open_from_transport_no_bzrdir(self):
743
transport = get_transport(self.get_url())
744
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport,
747
def test_open_from_transport_bzrdir_in_parent(self):
748
control = bzrdir.BzrDir.create(self.get_url())
749
transport = get_transport(self.get_url())
750
transport.mkdir('subdir')
751
transport = transport.clone('subdir')
752
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport,
755
def test_sprout_recursive(self):
756
tree = self.make_branch_and_tree('tree1',
757
format='dirstate-with-subtree')
758
sub_tree = self.make_branch_and_tree('tree1/subtree',
759
format='dirstate-with-subtree')
760
sub_tree.set_root_id('subtree-root')
761
tree.add_reference(sub_tree)
762
self.build_tree(['tree1/subtree/file'])
764
tree.commit('Initial commit')
765
tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
767
self.addCleanup(tree2.unlock)
768
self.failUnlessExists('tree2/subtree/file')
769
self.assertEqual('tree-reference', tree2.kind('subtree-root'))
771
def test_cloning_metadir(self):
772
"""Ensure that cloning metadir is suitable"""
773
bzrdir = self.make_bzrdir('bzrdir')
774
bzrdir.cloning_metadir()
775
branch = self.make_branch('branch', format='knit')
776
format = branch.bzrdir.cloning_metadir()
777
self.assertIsInstance(format.workingtree_format,
778
workingtree.WorkingTreeFormat3)
780
def test_sprout_recursive_treeless(self):
781
tree = self.make_branch_and_tree('tree1',
782
format='dirstate-with-subtree')
783
sub_tree = self.make_branch_and_tree('tree1/subtree',
784
format='dirstate-with-subtree')
785
tree.add_reference(sub_tree)
786
self.build_tree(['tree1/subtree/file'])
788
tree.commit('Initial commit')
789
tree.bzrdir.destroy_workingtree()
790
repo = self.make_repository('repo', shared=True,
791
format='dirstate-with-subtree')
792
repo.set_make_working_trees(False)
793
tree.bzrdir.sprout('repo/tree2')
794
self.failUnlessExists('repo/tree2/subtree')
795
self.failIfExists('repo/tree2/subtree/file')
797
def make_foo_bar_baz(self):
798
foo = bzrdir.BzrDir.create_branch_convenience('foo').bzrdir
799
bar = self.make_branch('foo/bar').bzrdir
800
baz = self.make_branch('baz').bzrdir
803
def test_find_bzrdirs(self):
804
foo, bar, baz = self.make_foo_bar_baz()
805
transport = get_transport(self.get_url())
806
self.assertEqualBzrdirs([baz, foo, bar],
807
bzrdir.BzrDir.find_bzrdirs(transport))
809
def test_find_bzrdirs_list_current(self):
810
def list_current(transport):
811
return [s for s in transport.list_dir('') if s != 'baz']
813
foo, bar, baz = self.make_foo_bar_baz()
814
transport = get_transport(self.get_url())
815
self.assertEqualBzrdirs([foo, bar],
816
bzrdir.BzrDir.find_bzrdirs(transport,
817
list_current=list_current))
820
def test_find_bzrdirs_evaluate(self):
821
def evaluate(bzrdir):
823
repo = bzrdir.open_repository()
824
except NoRepositoryPresent:
825
return True, bzrdir.root_transport.base
827
return False, bzrdir.root_transport.base
829
foo, bar, baz = self.make_foo_bar_baz()
830
transport = get_transport(self.get_url())
831
self.assertEqual([baz.root_transport.base, foo.root_transport.base],
832
list(bzrdir.BzrDir.find_bzrdirs(transport,
835
def assertEqualBzrdirs(self, first, second):
837
second = list(second)
838
self.assertEqual(len(first), len(second))
839
for x, y in zip(first, second):
840
self.assertEqual(x.root_transport.base, y.root_transport.base)
842
def test_find_branches(self):
843
root = self.make_repository('', shared=True)
844
foo, bar, baz = self.make_foo_bar_baz()
845
qux = self.make_bzrdir('foo/qux')
846
transport = get_transport(self.get_url())
847
branches = bzrdir.BzrDir.find_branches(transport)
848
self.assertEqual(baz.root_transport.base, branches[0].base)
849
self.assertEqual(foo.root_transport.base, branches[1].base)
850
self.assertEqual(bar.root_transport.base, branches[2].base)
852
# ensure this works without a top-level repo
853
branches = bzrdir.BzrDir.find_branches(transport.clone('foo'))
854
self.assertEqual(foo.root_transport.base, branches[0].base)
855
self.assertEqual(bar.root_transport.base, branches[1].base)
858
class TestMeta1DirFormat(TestCaseWithTransport):
859
"""Tests specific to the meta1 dir format."""
861
def test_right_base_dirs(self):
862
dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
864
branch_base = t.clone('branch').base
865
self.assertEqual(branch_base, dir.get_branch_transport(None).base)
866
self.assertEqual(branch_base,
867
dir.get_branch_transport(bzrlib.branch.BzrBranchFormat5()).base)
868
repository_base = t.clone('repository').base
869
self.assertEqual(repository_base, dir.get_repository_transport(None).base)
870
self.assertEqual(repository_base,
871
dir.get_repository_transport(weaverepo.RepositoryFormat7()).base)
872
checkout_base = t.clone('checkout').base
873
self.assertEqual(checkout_base, dir.get_workingtree_transport(None).base)
874
self.assertEqual(checkout_base,
875
dir.get_workingtree_transport(workingtree.WorkingTreeFormat3()).base)
877
def test_meta1dir_uses_lockdir(self):
878
"""Meta1 format uses a LockDir to guard the whole directory, not a file."""
879
dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
881
self.assertIsDirectory('branch-lock', t)
883
def test_comparison(self):
884
"""Equality and inequality behave properly.
886
Metadirs should compare equal iff they have the same repo, branch and
889
mydir = bzrdir.format_registry.make_bzrdir('knit')
890
self.assertEqual(mydir, mydir)
891
self.assertFalse(mydir != mydir)
892
otherdir = bzrdir.format_registry.make_bzrdir('knit')
893
self.assertEqual(otherdir, mydir)
894
self.assertFalse(otherdir != mydir)
895
otherdir2 = bzrdir.format_registry.make_bzrdir('dirstate-with-subtree')
896
self.assertNotEqual(otherdir2, mydir)
897
self.assertFalse(otherdir2 == mydir)
899
def test_needs_conversion_different_working_tree(self):
900
# meta1dirs need an conversion if any element is not the default.
901
new_format = bzrdir.format_registry.make_bzrdir('dirstate')
902
tree = self.make_branch_and_tree('tree', format='knit')
903
self.assertTrue(tree.bzrdir.needs_format_conversion(
906
def test_initialize_on_format_uses_smart_transport(self):
907
self.setup_smart_server_with_call_log()
908
new_format = bzrdir.format_registry.make_bzrdir('dirstate')
909
transport = self.get_transport('target')
910
transport.ensure_base()
911
self.reset_smart_call_log()
912
instance = new_format.initialize_on_transport(transport)
913
self.assertIsInstance(instance, remote.RemoteBzrDir)
914
rpc_count = len(self.hpss_calls)
915
# This figure represent the amount of work to perform this use case. It
916
# is entirely ok to reduce this number if a test fails due to rpc_count
917
# being too low. If rpc_count increases, more network roundtrips have
918
# become necessary for this use case. Please do not adjust this number
919
# upwards without agreement from bzr's network support maintainers.
920
self.assertEqual(2, rpc_count)
923
class TestFormat5(TestCaseWithTransport):
924
"""Tests specific to the version 5 bzrdir format."""
926
def test_same_lockfiles_between_tree_repo_branch(self):
927
# this checks that only a single lockfiles instance is created
928
# for format 5 objects
929
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
930
def check_dir_components_use_same_lock(dir):
931
ctrl_1 = dir.open_repository().control_files
932
ctrl_2 = dir.open_branch().control_files
933
ctrl_3 = dir.open_workingtree()._control_files
934
self.assertTrue(ctrl_1 is ctrl_2)
935
self.assertTrue(ctrl_2 is ctrl_3)
936
check_dir_components_use_same_lock(dir)
937
# and if we open it normally.
938
dir = bzrdir.BzrDir.open(self.get_url())
939
check_dir_components_use_same_lock(dir)
941
def test_can_convert(self):
942
# format 5 dirs are convertable
943
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
944
self.assertTrue(dir.can_convert_format())
946
def test_needs_conversion(self):
947
# format 5 dirs need a conversion if they are not the default,
949
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
950
# don't need to convert it to itself
951
self.assertFalse(dir.needs_format_conversion(bzrdir.BzrDirFormat5()))
952
# do need to convert it to the current default
953
self.assertTrue(dir.needs_format_conversion(
954
bzrdir.BzrDirFormat.get_default_format()))
957
class TestFormat6(TestCaseWithTransport):
958
"""Tests specific to the version 6 bzrdir format."""
960
def test_same_lockfiles_between_tree_repo_branch(self):
961
# this checks that only a single lockfiles instance is created
962
# for format 6 objects
963
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
964
def check_dir_components_use_same_lock(dir):
965
ctrl_1 = dir.open_repository().control_files
966
ctrl_2 = dir.open_branch().control_files
967
ctrl_3 = dir.open_workingtree()._control_files
968
self.assertTrue(ctrl_1 is ctrl_2)
969
self.assertTrue(ctrl_2 is ctrl_3)
970
check_dir_components_use_same_lock(dir)
971
# and if we open it normally.
972
dir = bzrdir.BzrDir.open(self.get_url())
973
check_dir_components_use_same_lock(dir)
975
def test_can_convert(self):
976
# format 6 dirs are convertable
977
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
978
self.assertTrue(dir.can_convert_format())
980
def test_needs_conversion(self):
981
# format 6 dirs need an conversion if they are not the default.
982
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
983
self.assertTrue(dir.needs_format_conversion(
984
bzrdir.BzrDirFormat.get_default_format()))
987
class NotBzrDir(bzrlib.bzrdir.BzrDir):
988
"""A non .bzr based control directory."""
990
def __init__(self, transport, format):
991
self._format = format
992
self.root_transport = transport
993
self.transport = transport.clone('.not')
996
class NotBzrDirFormat(bzrlib.bzrdir.BzrDirFormat):
997
"""A test class representing any non-.bzr based disk format."""
999
def initialize_on_transport(self, transport):
1000
"""Initialize a new .not dir in the base directory of a Transport."""
1001
transport.mkdir('.not')
1002
return self.open(transport)
1004
def open(self, transport):
1005
"""Open this directory."""
1006
return NotBzrDir(transport, self)
1009
def _known_formats(self):
1010
return set([NotBzrDirFormat()])
1013
def probe_transport(self, transport):
1014
"""Our format is present if the transport ends in '.not/'."""
1015
if transport.has('.not'):
1016
return NotBzrDirFormat()
1019
class TestNotBzrDir(TestCaseWithTransport):
1020
"""Tests for using the bzrdir api with a non .bzr based disk format.
1022
If/when one of these is in the core, we can let the implementation tests
1026
def test_create_and_find_format(self):
1027
# create a .notbzr dir
1028
format = NotBzrDirFormat()
1029
dir = format.initialize(self.get_url())
1030
self.assertIsInstance(dir, NotBzrDir)
1032
bzrlib.bzrdir.BzrDirFormat.register_control_format(format)
1034
found = bzrlib.bzrdir.BzrDirFormat.find_format(
1035
get_transport(self.get_url()))
1036
self.assertIsInstance(found, NotBzrDirFormat)
1038
bzrlib.bzrdir.BzrDirFormat.unregister_control_format(format)
1040
def test_included_in_known_formats(self):
1041
bzrlib.bzrdir.BzrDirFormat.register_control_format(NotBzrDirFormat)
1043
formats = bzrlib.bzrdir.BzrDirFormat.known_formats()
1044
for format in formats:
1045
if isinstance(format, NotBzrDirFormat):
1047
self.fail("No NotBzrDirFormat in %s" % formats)
1049
bzrlib.bzrdir.BzrDirFormat.unregister_control_format(NotBzrDirFormat)
1052
class NonLocalTests(TestCaseWithTransport):
1053
"""Tests for bzrdir static behaviour on non local paths."""
1056
super(NonLocalTests, self).setUp()
1057
self.vfs_transport_factory = memory.MemoryServer
1059
def test_create_branch_convenience(self):
1060
# outside a repo the default convenience output is a repo+branch_tree
1061
format = bzrdir.format_registry.make_bzrdir('knit')
1062
branch = bzrdir.BzrDir.create_branch_convenience(
1063
self.get_url('foo'), format=format)
1064
self.assertRaises(errors.NoWorkingTree,
1065
branch.bzrdir.open_workingtree)
1066
branch.bzrdir.open_repository()
1068
def test_create_branch_convenience_force_tree_not_local_fails(self):
1069
# outside a repo the default convenience output is a repo+branch_tree
1070
format = bzrdir.format_registry.make_bzrdir('knit')
1071
self.assertRaises(errors.NotLocalUrl,
1072
bzrdir.BzrDir.create_branch_convenience,
1073
self.get_url('foo'),
1074
force_new_tree=True,
1076
t = get_transport(self.get_url('.'))
1077
self.assertFalse(t.has('foo'))
1079
def test_clone(self):
1080
# clone into a nonlocal path works
1081
format = bzrdir.format_registry.make_bzrdir('knit')
1082
branch = bzrdir.BzrDir.create_branch_convenience('local',
1084
branch.bzrdir.open_workingtree()
1085
result = branch.bzrdir.clone(self.get_url('remote'))
1086
self.assertRaises(errors.NoWorkingTree,
1087
result.open_workingtree)
1088
result.open_branch()
1089
result.open_repository()
1091
def test_checkout_metadir(self):
1092
# checkout_metadir has reasonable working tree format even when no
1093
# working tree is present
1094
self.make_branch('branch-knit2', format='dirstate-with-subtree')
1095
my_bzrdir = bzrdir.BzrDir.open(self.get_url('branch-knit2'))
1096
checkout_format = my_bzrdir.checkout_metadir()
1097
self.assertIsInstance(checkout_format.workingtree_format,
1098
workingtree.WorkingTreeFormat3)
1101
class TestHTTPRedirections(object):
1102
"""Test redirection between two http servers.
1104
This MUST be used by daughter classes that also inherit from
1105
TestCaseWithTwoWebservers.
1107
We can't inherit directly from TestCaseWithTwoWebservers or the
1108
test framework will try to create an instance which cannot
1109
run, its implementation being incomplete.
1112
def create_transport_readonly_server(self):
1113
return http_utils.HTTPServerRedirecting()
1115
def create_transport_secondary_server(self):
1116
return http_utils.HTTPServerRedirecting()
1119
super(TestHTTPRedirections, self).setUp()
1120
# The redirections will point to the new server
1121
self.new_server = self.get_readonly_server()
1122
# The requests to the old server will be redirected
1123
self.old_server = self.get_secondary_server()
1124
# Configure the redirections
1125
self.old_server.redirect_to(self.new_server.host, self.new_server.port)
1127
def test_loop(self):
1128
# Both servers redirect to each other creating a loop
1129
self.new_server.redirect_to(self.old_server.host, self.old_server.port)
1130
# Starting from either server should loop
1131
old_url = self._qualified_url(self.old_server.host,
1132
self.old_server.port)
1133
oldt = self._transport(old_url)
1134
self.assertRaises(errors.NotBranchError,
1135
bzrdir.BzrDir.open_from_transport, oldt)
1136
new_url = self._qualified_url(self.new_server.host,
1137
self.new_server.port)
1138
newt = self._transport(new_url)
1139
self.assertRaises(errors.NotBranchError,
1140
bzrdir.BzrDir.open_from_transport, newt)
1142
def test_qualifier_preserved(self):
1143
wt = self.make_branch_and_tree('branch')
1144
old_url = self._qualified_url(self.old_server.host,
1145
self.old_server.port)
1146
start = self._transport(old_url).clone('branch')
1147
bdir = bzrdir.BzrDir.open_from_transport(start)
1148
# Redirection should preserve the qualifier, hence the transport class
1150
self.assertIsInstance(bdir.root_transport, type(start))
1153
class TestHTTPRedirections_urllib(TestHTTPRedirections,
1154
http_utils.TestCaseWithTwoWebservers):
1155
"""Tests redirections for urllib implementation"""
1157
_transport = HttpTransport_urllib
1159
def _qualified_url(self, host, port):
1160
result = 'http+urllib://%s:%s' % (host, port)
1161
self.permit_url(result)
1166
class TestHTTPRedirections_pycurl(TestWithTransport_pycurl,
1167
TestHTTPRedirections,
1168
http_utils.TestCaseWithTwoWebservers):
1169
"""Tests redirections for pycurl implementation"""
1171
def _qualified_url(self, host, port):
1172
result = 'http+pycurl://%s:%s' % (host, port)
1173
self.permit_url(result)
1177
class TestHTTPRedirections_nosmart(TestHTTPRedirections,
1178
http_utils.TestCaseWithTwoWebservers):
1179
"""Tests redirections for the nosmart decorator"""
1181
_transport = NoSmartTransportDecorator
1183
def _qualified_url(self, host, port):
1184
result = 'nosmart+http://%s:%s' % (host, port)
1185
self.permit_url(result)
1189
class TestHTTPRedirections_readonly(TestHTTPRedirections,
1190
http_utils.TestCaseWithTwoWebservers):
1191
"""Tests redirections for readonly decoratror"""
1193
_transport = ReadonlyTransportDecorator
1195
def _qualified_url(self, host, port):
1196
result = 'readonly+http://%s:%s' % (host, port)
1197
self.permit_url(result)
1201
class TestDotBzrHidden(TestCaseWithTransport):
1204
if sys.platform == 'win32':
1205
ls = [os.environ['COMSPEC'], '/C', 'dir', '/B']
1208
f = subprocess.Popen(self.ls, stdout=subprocess.PIPE,
1209
stderr=subprocess.PIPE)
1210
out, err = f.communicate()
1211
self.assertEqual(0, f.returncode, 'Calling %s failed: %s'
1213
return out.splitlines()
1215
def test_dot_bzr_hidden(self):
1216
if sys.platform == 'win32' and not win32utils.has_win32file:
1217
raise TestSkipped('unable to make file hidden without pywin32 library')
1218
b = bzrdir.BzrDir.create('.')
1219
self.build_tree(['a'])
1220
self.assertEquals(['a'], self.get_ls())
1222
def test_dot_bzr_hidden_with_url(self):
1223
if sys.platform == 'win32' and not win32utils.has_win32file:
1224
raise TestSkipped('unable to make file hidden without pywin32 library')
1225
b = bzrdir.BzrDir.create(urlutils.local_path_to_url('.'))
1226
self.build_tree(['a'])
1227
self.assertEquals(['a'], self.get_ls())
1230
class _TestBzrDirFormat(bzrdir.BzrDirMetaFormat1):
1231
"""Test BzrDirFormat implementation for TestBzrDirSprout."""
1233
def _open(self, transport):
1234
return _TestBzrDir(transport, self)
1237
class _TestBzrDir(bzrdir.BzrDirMeta1):
1238
"""Test BzrDir implementation for TestBzrDirSprout.
1240
When created a _TestBzrDir already has repository and a branch. The branch
1241
is a test double as well.
1244
def __init__(self, *args, **kwargs):
1245
super(_TestBzrDir, self).__init__(*args, **kwargs)
1246
self.test_branch = _TestBranch()
1247
self.test_branch.repository = self.create_repository()
1249
def open_branch(self, unsupported=False):
1250
return self.test_branch
1252
def cloning_metadir(self, require_stacking=False):
1253
return _TestBzrDirFormat()
1256
class _TestBranchFormat(bzrlib.branch.BranchFormat):
1257
"""Test Branch format for TestBzrDirSprout."""
1260
class _TestBranch(bzrlib.branch.Branch):
1261
"""Test Branch implementation for TestBzrDirSprout."""
1263
def __init__(self, *args, **kwargs):
1264
self._format = _TestBranchFormat()
1265
super(_TestBranch, self).__init__(*args, **kwargs)
1269
def sprout(self, *args, **kwargs):
1270
self.calls.append('sprout')
1271
return _TestBranch()
1273
def copy_content_into(self, destination, revision_id=None):
1274
self.calls.append('copy_content_into')
1276
def get_parent(self):
1279
def set_parent(self, parent):
1280
self._parent = parent
1283
class TestBzrDirSprout(TestCaseWithMemoryTransport):
1285
def test_sprout_uses_branch_sprout(self):
1286
"""BzrDir.sprout calls Branch.sprout.
1288
Usually, BzrDir.sprout should delegate to the branch's sprout method
1289
for part of the work. This allows the source branch to control the
1290
choice of format for the new branch.
1292
There are exceptions, but this tests avoids them:
1293
- if there's no branch in the source bzrdir,
1294
- or if the stacking has been requested and the format needs to be
1295
overridden to satisfy that.
1297
# Make an instrumented bzrdir.
1298
t = self.get_transport('source')
1300
source_bzrdir = _TestBzrDirFormat().initialize_on_transport(t)
1301
# The instrumented bzrdir has a test_branch attribute that logs calls
1302
# made to the branch contained in that bzrdir. Initially the test
1303
# branch exists but no calls have been made to it.
1304
self.assertEqual([], source_bzrdir.test_branch.calls)
1307
target_url = self.get_url('target')
1308
result = source_bzrdir.sprout(target_url, recurse='no')
1310
# The bzrdir called the branch's sprout method.
1311
self.assertSubset(['sprout'], source_bzrdir.test_branch.calls)
1313
def test_sprout_parent(self):
1314
grandparent_tree = self.make_branch('grandparent')
1315
parent = grandparent_tree.bzrdir.sprout('parent').open_branch()
1316
branch_tree = parent.bzrdir.sprout('branch').open_branch()
1317
self.assertContainsRe(branch_tree.get_parent(), '/parent/$')
1320
class TestBzrDirHooks(TestCaseWithMemoryTransport):
1322
def test_pre_open_called(self):
1324
bzrdir.BzrDir.hooks.install_named_hook('pre_open', calls.append, None)
1325
transport = self.get_transport('foo')
1326
url = transport.base
1327
self.assertRaises(errors.NotBranchError, bzrdir.BzrDir.open, url)
1328
self.assertEqual([transport.base], [t.base for t in calls])
1330
def test_pre_open_actual_exceptions_raised(self):
1332
def fail_once(transport):
1335
raise errors.BzrError("fail")
1336
bzrdir.BzrDir.hooks.install_named_hook('pre_open', fail_once, None)
1337
transport = self.get_transport('foo')
1338
url = transport.base
1339
err = self.assertRaises(errors.BzrError, bzrdir.BzrDir.open, url)
1340
self.assertEqual('fail', err._preformatted_string)