1
# Copyright (C) 2010, 2011, 2012, 2016 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 bzrdir implementations - tests a bzrdir format."""
20
from stat import S_ISDIR
28
revision as _mod_revision,
32
from bzrlib.remote import RemoteBzrDirFormat
33
from bzrlib.tests import (
37
from bzrlib.tests.per_bzrdir import TestCaseWithBzrDir
38
from bzrlib.transport.local import (
43
class AnonymousTestBranchFormat(bzrlib.branch.BranchFormat):
44
"""An anonymous branch format (does not have a format string)"""
46
def get_format_string(self):
47
raise NotImplementedError(self.get_format_string)
50
class IdentifiableTestBranchFormat(bzrlib.branch.BranchFormat):
51
"""An identifable branch format (has a format string)"""
53
def get_format_string(self):
54
return "I have an identity"
57
class AnonymousTestRepositoryFormat(repository.RepositoryFormat):
58
"""An anonymous branch format (does not have a format string)"""
60
def get_format_string(self):
61
raise NotImplementedError(self.get_format_string)
64
class IdentifiableTestRepositoryFormat(repository.RepositoryFormat):
65
"""An identifable branch format (has a format string)"""
67
def get_format_string(self):
68
return "I have an identity"
71
class AnonymousTestWorkingTreeFormat(workingtree.WorkingTreeFormat):
72
"""An anonymous branch format (does not have a format string)"""
74
def get_format_string(self):
75
raise NotImplementedError(self.get_format_string)
78
class IdentifiableTestWorkingTreeFormat(workingtree.WorkingTreeFormat):
79
"""An identifable branch format (has a format string)"""
81
def get_format_string(self):
82
return "I have an identity"
85
class TestBzrDir(TestCaseWithBzrDir):
87
# Many of these tests test for disk equality rather than checking
88
# for semantic equivalence. This works well for some tests but
89
# is not good at handling changes in representation or the addition
90
# or removal of control data. It would be nice to for instance:
91
# sprout a new branch, check that the nickname has been reset by hand
92
# and then set the nickname to match the source branch, at which point
93
# a semantic equivalence should pass
95
def assertDirectoriesEqual(self, source, target, ignore_list=[]):
96
"""Assert that the content of source and target are identical.
98
paths in ignore list will be completely ignored.
100
We ignore paths that represent data which is allowed to change during
101
a clone or sprout: for instance, inventory.knit contains gzip fragements
102
which have timestamps in them, and as we have read the inventory from
103
the source knit, the already-read data is recompressed rather than
104
reading it again, which leads to changed timestamps. This is ok though,
105
because the inventory.kndx file is not ignored, and the integrity of
106
knit joins is tested by test_knit and test_versionedfile.
108
:seealso: Additionally, assertRepositoryHasSameItems provides value
109
rather than representation checking of repositories for
115
dir = directories.pop()
116
for path in set(source.list_dir(dir) + target.list_dir(dir)):
117
path = dir + '/' + path
118
if path in ignore_list:
121
stat = source.stat(path)
122
except errors.NoSuchFile:
123
self.fail('%s not in source' % path)
124
if S_ISDIR(stat.st_mode):
125
self.assertTrue(S_ISDIR(target.stat(path).st_mode))
126
directories.append(path)
128
self.assertEqualDiff(source.get_bytes(path),
129
target.get_bytes(path),
130
"text for file %r differs:\n" % path)
132
def assertRepositoryHasSameItems(self, left_repo, right_repo):
133
"""require left_repo and right_repo to contain the same data."""
134
# XXX: TODO: Doesn't work yet, because we need to be able to compare
135
# local repositories to remote ones... but this is an as-yet unsolved
136
# aspect of format management and the Remote protocols...
137
# self.assertEqual(left_repo._format.__class__,
138
# right_repo._format.__class__)
139
left_repo.lock_read()
141
right_repo.lock_read()
144
all_revs = left_repo.all_revision_ids()
145
self.assertEqual(left_repo.all_revision_ids(),
146
right_repo.all_revision_ids())
147
for rev_id in left_repo.all_revision_ids():
148
self.assertEqual(left_repo.get_revision(rev_id),
149
right_repo.get_revision(rev_id))
150
# Assert the revision trees (and thus the inventories) are equal
151
sort_key = lambda rev_tree: rev_tree.get_revision_id()
152
rev_trees_a = sorted(
153
left_repo.revision_trees(all_revs), key=sort_key)
154
rev_trees_b = sorted(
155
right_repo.revision_trees(all_revs), key=sort_key)
156
for tree_a, tree_b in zip(rev_trees_a, rev_trees_b):
157
self.assertEqual([], list(tree_a.iter_changes(tree_b)))
159
text_index = left_repo._generate_text_key_index()
160
self.assertEqual(text_index,
161
right_repo._generate_text_key_index())
163
for file_id, revision_id in text_index.iterkeys():
164
desired_files.append(
165
(file_id, revision_id, (file_id, revision_id)))
166
left_texts = [(identifier, "".join(bytes_iterator)) for
167
(identifier, bytes_iterator) in
168
left_repo.iter_files_bytes(desired_files)]
169
right_texts = [(identifier, "".join(bytes_iterator)) for
170
(identifier, bytes_iterator) in
171
right_repo.iter_files_bytes(desired_files)]
174
self.assertEqual(left_texts, right_texts)
176
for rev_id in all_revs:
178
left_text = left_repo.get_signature_text(rev_id)
179
except errors.NoSuchRevision:
181
right_text = right_repo.get_signature_text(rev_id)
182
self.assertEqual(left_text, right_text)
188
def sproutOrSkip(self, from_bzrdir, to_url, revision_id=None,
189
force_new_repo=False, accelerator_tree=None,
190
create_tree_if_local=True):
191
"""Sprout from_bzrdir into to_url, or raise TestSkipped.
193
A simple wrapper for from_bzrdir.sprout that translates NotLocalUrl into
194
TestSkipped. Returns the newly sprouted bzrdir.
196
to_transport = transport.get_transport(to_url)
197
if not isinstance(to_transport, LocalTransport):
198
raise TestSkipped('Cannot sprout to remote bzrdirs.')
199
target = from_bzrdir.sprout(to_url, revision_id=revision_id,
200
force_new_repo=force_new_repo,
201
possible_transports=[to_transport],
202
accelerator_tree=accelerator_tree,
203
create_tree_if_local=create_tree_if_local)
206
def skipIfNoWorkingTree(self, a_bzrdir):
207
"""Raises TestSkipped if a_bzrdir doesn't have a working tree.
209
If the bzrdir does have a workingtree, this is a no-op.
212
a_bzrdir.open_workingtree()
213
except (errors.NotLocalUrl, errors.NoWorkingTree):
214
raise TestSkipped("bzrdir on transport %r has no working tree"
215
% a_bzrdir.transport)
217
def createWorkingTreeOrSkip(self, a_bzrdir):
218
"""Create a working tree on a_bzrdir, or raise TestSkipped.
220
A simple wrapper for create_workingtree that translates NotLocalUrl into
221
TestSkipped. Returns the newly created working tree.
224
# This passes in many named options to make sure they're
225
# understood by subclasses: see
226
# <https://bugs.launchpad.net/bzr/+bug/524627>.
227
return a_bzrdir.create_workingtree(
230
accelerator_tree=None,
232
except errors.NotLocalUrl:
233
raise TestSkipped("cannot make working tree with transport %r"
234
% a_bzrdir.transport)
236
def test_clone_bzrdir_repository_under_shared_force_new_repo(self):
237
tree = self.make_branch_and_tree('commit_tree')
238
self.build_tree(['commit_tree/foo'])
240
tree.commit('revision 1', rev_id='1')
241
dir = self.make_bzrdir('source')
242
repo = dir.create_repository()
243
repo.fetch(tree.branch.repository)
244
self.assertTrue(repo.has_revision('1'))
246
self.make_repository('target', shared=True)
247
except errors.IncompatibleFormat:
249
target = dir.clone(self.get_url('target/child'), force_new_repo=True)
250
self.assertNotEqual(dir.transport.base, target.transport.base)
251
self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
252
['./.bzr/repository',
254
self.assertRepositoryHasSameItems(tree.branch.repository, repo)
256
def test_clone_bzrdir_branch_and_repo(self):
257
tree = self.make_branch_and_tree('commit_tree')
258
self.build_tree(['commit_tree/foo'])
260
tree.commit('revision 1')
261
source = self.make_branch('source')
262
tree.branch.repository.copy_content_into(source.repository)
263
tree.branch.copy_content_into(source)
265
target = dir.clone(self.get_url('target'))
266
self.assertNotEqual(dir.transport.base, target.transport.base)
267
self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
269
'./.bzr/basis-inventory-cache',
270
'./.bzr/checkout/stat-cache',
271
'./.bzr/merge-hashes',
275
self.assertRepositoryHasSameItems(
276
tree.branch.repository, target.open_repository())
278
def test_clone_on_transport(self):
279
a_dir = self.make_bzrdir('source')
280
target_transport = a_dir.root_transport.clone('..').clone('target')
281
target = a_dir.clone_on_transport(target_transport)
282
self.assertNotEqual(a_dir.transport.base, target.transport.base)
283
self.assertDirectoriesEqual(a_dir.root_transport, target.root_transport,
284
['./.bzr/merge-hashes'])
286
def test_clone_bzrdir_empty(self):
287
dir = self.make_bzrdir('source')
288
target = dir.clone(self.get_url('target'))
289
self.assertNotEqual(dir.transport.base, target.transport.base)
290
self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
291
['./.bzr/merge-hashes'])
293
def test_clone_bzrdir_empty_force_new_ignored(self):
294
# the force_new_repo parameter should have no effect on an empty
295
# bzrdir's clone logic
296
dir = self.make_bzrdir('source')
297
target = dir.clone(self.get_url('target'), force_new_repo=True)
298
self.assertNotEqual(dir.transport.base, target.transport.base)
299
self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
300
['./.bzr/merge-hashes'])
302
def test_clone_bzrdir_repository(self):
303
tree = self.make_branch_and_tree('commit_tree')
304
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
306
tree.commit('revision 1', rev_id='1')
307
dir = self.make_bzrdir('source')
308
repo = dir.create_repository()
309
repo.fetch(tree.branch.repository)
310
self.assertTrue(repo.has_revision('1'))
311
target = dir.clone(self.get_url('target'))
312
self.assertNotEqual(dir.transport.base, target.transport.base)
313
self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
315
'./.bzr/merge-hashes',
318
self.assertRepositoryHasSameItems(tree.branch.repository,
319
target.open_repository())
321
def test_clone_bzrdir_tree_branch_repo(self):
322
tree = self.make_branch_and_tree('source')
323
self.build_tree(['source/foo'])
325
tree.commit('revision 1')
327
target = dir.clone(self.get_url('target'))
328
self.skipIfNoWorkingTree(target)
329
self.assertNotEqual(dir.transport.base, target.transport.base)
330
self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
331
['./.bzr/stat-cache',
332
'./.bzr/checkout/dirstate',
333
'./.bzr/checkout/stat-cache',
334
'./.bzr/checkout/merge-hashes',
335
'./.bzr/merge-hashes',
338
self.assertRepositoryHasSameItems(tree.branch.repository,
339
target.open_branch().repository)
340
target.open_workingtree().revert()
342
def test_revert_inventory(self):
343
tree = self.make_branch_and_tree('source')
344
self.build_tree(['source/foo'])
346
tree.commit('revision 1')
348
target = dir.clone(self.get_url('target'))
349
self.skipIfNoWorkingTree(target)
350
self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
351
['./.bzr/stat-cache',
352
'./.bzr/checkout/dirstate',
353
'./.bzr/checkout/stat-cache',
354
'./.bzr/checkout/merge-hashes',
355
'./.bzr/merge-hashes',
358
self.assertRepositoryHasSameItems(tree.branch.repository,
359
target.open_branch().repository)
361
target.open_workingtree().revert()
362
self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
363
['./.bzr/stat-cache',
364
'./.bzr/checkout/dirstate',
365
'./.bzr/checkout/stat-cache',
366
'./.bzr/checkout/merge-hashes',
367
'./.bzr/merge-hashes',
370
self.assertRepositoryHasSameItems(tree.branch.repository,
371
target.open_branch().repository)
373
def test_clone_bzrdir_tree_branch_reference(self):
374
# a tree with a branch reference (aka a checkout)
375
# should stay a checkout on clone.
376
referenced_branch = self.make_branch('referencced')
377
dir = self.make_bzrdir('source')
379
dir.set_branch_reference(referenced_branch)
380
except errors.IncompatibleFormat:
381
# this is ok too, not all formats have to support references.
383
self.createWorkingTreeOrSkip(dir)
384
target = dir.clone(self.get_url('target'))
385
self.skipIfNoWorkingTree(target)
386
self.assertNotEqual(dir.transport.base, target.transport.base)
387
self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
388
['./.bzr/stat-cache',
389
'./.bzr/checkout/stat-cache',
390
'./.bzr/checkout/merge-hashes',
391
'./.bzr/merge-hashes',
392
'./.bzr/repository/inventory.knit',
395
def test_clone_bzrdir_branch_and_repo_into_shared_repo_force_new_repo(self):
396
# by default cloning into a shared repo uses the shared repo.
397
tree = self.make_branch_and_tree('commit_tree')
398
self.build_tree(['commit_tree/foo'])
400
tree.commit('revision 1')
401
source = self.make_branch('source')
402
tree.branch.repository.copy_content_into(source.repository)
403
tree.branch.copy_content_into(source)
405
self.make_repository('target', shared=True)
406
except errors.IncompatibleFormat:
409
target = dir.clone(self.get_url('target/child'), force_new_repo=True)
410
self.assertNotEqual(dir.transport.base, target.transport.base)
411
repo = target.open_repository()
412
self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
413
['./.bzr/repository',
415
self.assertRepositoryHasSameItems(tree.branch.repository, repo)
417
def test_clone_bzrdir_branch_reference(self):
418
# cloning should preserve the reference status of the branch in a bzrdir
419
referenced_branch = self.make_branch('referencced')
420
dir = self.make_bzrdir('source')
422
dir.set_branch_reference(referenced_branch)
423
except errors.IncompatibleFormat:
424
# this is ok too, not all formats have to support references.
426
target = dir.clone(self.get_url('target'))
427
self.assertNotEqual(dir.transport.base, target.transport.base)
428
self.assertDirectoriesEqual(dir.root_transport, target.root_transport)
430
def test_sprout_bzrdir_repository(self):
431
tree = self.make_branch_and_tree('commit_tree')
432
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
434
tree.commit('revision 1', rev_id='1')
435
dir = self.make_bzrdir('source')
436
repo = dir.create_repository()
437
repo.fetch(tree.branch.repository)
438
self.assertTrue(repo.has_revision('1'))
441
_mod_revision.is_null(_mod_revision.ensure_null(
442
dir.open_branch().last_revision())))
443
except errors.NotBranchError:
445
target = dir.sprout(self.get_url('target'))
446
self.assertNotEqual(dir.transport.base, target.transport.base)
447
# testing inventory isn't reasonable for repositories
448
self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
454
'./.bzr/repository/inventory.knit',
457
local_inventory = dir.transport.local_abspath('inventory')
458
except errors.NotLocalUrl:
461
# If we happen to have a tree, we'll guarantee everything
462
# except for the tree root is the same.
463
inventory_f = file(local_inventory, 'rb')
464
self.addCleanup(inventory_f.close)
465
self.assertContainsRe(inventory_f.read(),
466
'<inventory format="5">\n</inventory>\n')
468
if e.errno != errno.ENOENT:
471
def test_sprout_bzrdir_branch_and_repo(self):
472
tree = self.make_branch_and_tree('commit_tree')
473
self.build_tree(['commit_tree/foo'])
475
tree.commit('revision 1')
476
source = self.make_branch('source')
477
tree.branch.repository.copy_content_into(source.repository)
478
tree.bzrdir.open_branch().copy_content_into(source)
480
target = dir.sprout(self.get_url('target'))
481
self.assertNotEqual(dir.transport.base, target.transport.base)
482
target_repo = target.open_repository()
483
self.assertRepositoryHasSameItems(source.repository, target_repo)
484
self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
486
'./.bzr/basis-inventory-cache',
487
'./.bzr/branch/branch.conf',
488
'./.bzr/branch/parent',
490
'./.bzr/checkout/inventory',
491
'./.bzr/checkout/stat-cache',
499
def test_sprout_bzrdir_tree_branch_repo(self):
500
tree = self.make_branch_and_tree('source')
501
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
503
tree.commit('revision 1')
505
target = self.sproutOrSkip(dir, self.get_url('target'))
506
self.assertNotEqual(dir.transport.base, target.transport.base)
507
self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
510
'./.bzr/checkout/dirstate',
511
'./.bzr/checkout/stat-cache',
512
'./.bzr/checkout/inventory',
518
self.assertRepositoryHasSameItems(
519
tree.branch.repository, target.open_repository())
522
def test_retire_bzrdir(self):
523
bd = self.make_bzrdir('.')
524
transport = bd.root_transport
525
# must not overwrite existing directories
526
self.build_tree(['.bzr.retired.0/', '.bzr.retired.0/junk',],
528
self.assertTrue(transport.has('.bzr'))
530
self.assertFalse(transport.has('.bzr'))
531
self.assertTrue(transport.has('.bzr.retired.1'))
533
def test_retire_bzrdir_limited(self):
534
bd = self.make_bzrdir('.')
535
transport = bd.root_transport
536
# must not overwrite existing directories
537
self.build_tree(['.bzr.retired.0/', '.bzr.retired.0/junk',],
539
self.assertTrue(transport.has('.bzr'))
540
self.assertRaises((errors.FileExists, errors.DirectoryNotEmpty),
541
bd.retire_bzrdir, limit=0)
543
def test_get_branch_transport(self):
544
dir = self.make_bzrdir('.')
545
# without a format, get_branch_transport gives use a transport
546
# which -may- point to an existing dir.
547
self.assertTrue(isinstance(dir.get_branch_transport(None),
548
transport.Transport))
549
# with a given format, either the bzr dir supports identifiable
550
# branches, or it supports anonymous branch formats, but not both.
551
anonymous_format = AnonymousTestBranchFormat()
552
identifiable_format = IdentifiableTestBranchFormat()
554
found_transport = dir.get_branch_transport(anonymous_format)
555
self.assertRaises(errors.IncompatibleFormat,
556
dir.get_branch_transport,
558
except errors.IncompatibleFormat:
559
found_transport = dir.get_branch_transport(identifiable_format)
560
self.assertTrue(isinstance(found_transport, transport.Transport))
561
# and the dir which has been initialized for us must exist.
562
found_transport.list_dir('.')
564
def test_get_repository_transport(self):
565
dir = self.make_bzrdir('.')
566
# without a format, get_repository_transport gives use a transport
567
# which -may- point to an existing dir.
568
self.assertTrue(isinstance(dir.get_repository_transport(None),
569
transport.Transport))
570
# with a given format, either the bzr dir supports identifiable
571
# repositories, or it supports anonymous repository formats, but not both.
572
anonymous_format = AnonymousTestRepositoryFormat()
573
identifiable_format = IdentifiableTestRepositoryFormat()
575
found_transport = dir.get_repository_transport(anonymous_format)
576
self.assertRaises(errors.IncompatibleFormat,
577
dir.get_repository_transport,
579
except errors.IncompatibleFormat:
580
found_transport = dir.get_repository_transport(identifiable_format)
581
self.assertTrue(isinstance(found_transport, transport.Transport))
582
# and the dir which has been initialized for us must exist.
583
found_transport.list_dir('.')
585
def test_get_workingtree_transport(self):
586
dir = self.make_bzrdir('.')
587
# without a format, get_workingtree_transport gives use a transport
588
# which -may- point to an existing dir.
589
self.assertTrue(isinstance(dir.get_workingtree_transport(None),
590
transport.Transport))
591
# with a given format, either the bzr dir supports identifiable
592
# trees, or it supports anonymous tree formats, but not both.
593
anonymous_format = AnonymousTestWorkingTreeFormat()
594
identifiable_format = IdentifiableTestWorkingTreeFormat()
596
found_transport = dir.get_workingtree_transport(anonymous_format)
597
self.assertRaises(errors.IncompatibleFormat,
598
dir.get_workingtree_transport,
600
except errors.IncompatibleFormat:
601
found_transport = dir.get_workingtree_transport(identifiable_format)
602
self.assertTrue(isinstance(found_transport, transport.Transport))
603
# and the dir which has been initialized for us must exist.
604
found_transport.list_dir('.')
606
def assertInitializeEx(self, t, need_meta=False, **kwargs):
607
"""Execute initialize_on_transport_ex and check it succeeded correctly.
609
This involves checking that the disk objects were created, open with
610
the same format returned, and had the expected disk format.
612
:param t: The transport to initialize on.
613
:param **kwargs: Additional arguments to pass to
614
initialize_on_transport_ex.
615
:return: the resulting repo, control dir tuple.
617
if not self.bzrdir_format.is_initializable():
618
raise TestNotApplicable("control dir format is not "
620
repo, control, require_stacking, repo_policy = \
621
self.bzrdir_format.initialize_on_transport_ex(t, **kwargs)
623
# Repositories are open write-locked
624
self.assertTrue(repo.is_write_locked())
625
self.addCleanup(repo.unlock)
626
self.assertIsInstance(control, bzrdir.BzrDir)
627
opened = bzrdir.BzrDir.open(t.base)
628
expected_format = self.bzrdir_format
629
if need_meta and expected_format.fixed_components:
630
# Pre-metadir formats change when we are making something that
631
# needs a metaformat, because clone is used for push.
632
expected_format = bzrdir.BzrDirMetaFormat1()
633
if not isinstance(expected_format, RemoteBzrDirFormat):
634
self.assertEqual(control._format.network_name(),
635
expected_format.network_name())
636
self.assertEqual(control._format.network_name(),
637
opened._format.network_name())
638
self.assertEqual(control.__class__, opened.__class__)
641
def test_format_initialize_on_transport_ex_default_stack_on(self):
642
# When initialize_on_transport_ex uses a stacked-on branch because of
643
# a stacking policy on the target, the location of the fallback
644
# repository is the same as the external location of the stacked-on
646
balloon = self.make_bzrdir('balloon')
647
if isinstance(balloon._format, bzrdir.BzrDirMetaFormat1):
648
stack_on = self.make_branch('stack-on', format='1.9')
650
stack_on = self.make_branch('stack-on')
651
if not stack_on.repository._format.supports_nesting_repositories:
652
raise TestNotApplicable("requires nesting repositories")
653
config = self.make_bzrdir('.').get_config()
655
config.set_default_stack_on('stack-on')
656
except errors.BzrError:
657
raise TestNotApplicable('Only relevant for stackable formats.')
658
# Initialize a bzrdir subject to the policy.
659
t = self.get_transport('stacked')
660
repo_fmt = controldir.format_registry.make_bzrdir('1.9')
661
repo_name = repo_fmt.repository_format.network_name()
662
repo, control = self.assertInitializeEx(
663
t, need_meta=True, repo_format_name=repo_name, stacked_on=None)
664
# self.addCleanup(repo.unlock)
665
# There's one fallback repo, with a public location.
666
self.assertLength(1, repo._fallback_repositories)
667
fallback_repo = repo._fallback_repositories[0]
669
stack_on.base, fallback_repo.bzrdir.root_transport.base)
670
# The bzrdir creates a branch in stacking-capable format.
671
new_branch = control.create_branch()
672
self.assertTrue(new_branch._format.supports_stacking())
674
def test_no_leftover_dirs(self):
675
# bug 886196: development-colo uses a branch-lock directory
676
# in the user directory rather than the control directory.
677
if not self.bzrdir_format.colocated_branches:
678
raise TestNotApplicable(
679
"format does not support colocated branches")
680
branch = self.make_branch('.', format='development-colo')
681
branch.bzrdir.create_branch(name="another-colocated-branch")
683
branch.bzrdir.user_transport.list_dir("."),
686
def test_get_branches(self):
687
repo = self.make_repository('branch-1')
688
if not repo.bzrdir._format.colocated_branches:
689
raise TestNotApplicable('Format does not support colocation')
690
target_branch = repo.bzrdir.create_branch(name='foo')
691
repo.bzrdir.set_branch_reference(target_branch)
692
self.assertEqual(set(["", 'foo']),
693
set(repo.bzrdir.get_branches().keys()))