1
# (C) 2005, 2006 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 bzrdir implementations - tests a bzrdir format."""
24
import bzrlib.bzrdir as bzrdir
25
from bzrlib.branch import Branch, needs_read_lock, needs_write_lock
26
from bzrlib.check import check
27
from bzrlib.commit import commit
28
import bzrlib.errors as errors
29
from bzrlib.errors import (FileExists,
32
UninitializableFormat,
35
import bzrlib.repository as repository
36
from bzrlib.tests import (
39
TestCaseWithTransport,
42
from bzrlib.trace import mutter
43
import bzrlib.transactions as transactions
44
import bzrlib.transport as transport
45
from bzrlib.transport import get_transport
46
import bzrlib.ui as ui
47
from bzrlib.upgrade import upgrade
48
import bzrlib.workingtree as workingtree
51
class TestCaseWithBzrDir(TestCaseWithTransport):
54
super(TestCaseWithBzrDir, self).setUp()
58
if self.bzrdir is None:
59
self.bzrdir = self.make_bzrdir(None)
62
def make_bzrdir(self, relpath):
64
url = self.get_url(relpath)
65
segments = url.split('/')
66
if segments and segments[-1] not in ('', '.'):
67
parent = '/'.join(segments[:-1])
68
t = get_transport(parent)
73
return self.bzrdir_format.initialize(url)
74
except UninitializableFormat:
75
raise TestSkipped("Format %s is not initializable.")
78
class TestBzrDir(TestCaseWithBzrDir):
79
# Many of these tests test for disk equality rather than checking
80
# for semantic equivalence. This works well for some tests but
81
# is not good at handling changes in representation or the addition
82
# or removal of control data. It would be nice to for instance:
83
# sprout a new branch, check that the nickname has been reset by hand
84
# and then set the nickname to match the source branch, at which point
85
# a semantic equivalence should pass
87
def assertDirectoriesEqual(self, source, target, ignore_list=[]):
88
"""Assert that the content of source and target are identical.
90
paths in ignore list will be completely ignored.
95
dir = directories.pop()
96
for path in source.list_dir(dir):
97
path = dir + '/' + path
98
if path in ignore_list:
100
stat = source.stat(path)
101
if S_ISDIR(stat.st_mode):
102
self.assertTrue(S_ISDIR(target.stat(path).st_mode))
103
directories.append(path)
105
self.assertEqualDiff(source.get(path).read(),
106
target.get(path).read(),
107
"text for file %r differs:\n" % path)
109
def test_clone_bzrdir_empty(self):
110
dir = self.make_bzrdir('source')
111
target = dir.clone(self.get_url('target'))
112
self.assertNotEqual(dir.transport.base, target.transport.base)
113
self.assertDirectoriesEqual(dir.root_transport, target.root_transport)
115
def test_clone_bzrdir_empty_force_new_ignored(self):
116
# the force_new_repo parameter should have no effect on an empty
117
# bzrdir's clone logic
118
dir = self.make_bzrdir('source')
119
target = dir.clone(self.get_url('target'), force_new_repo=True)
120
self.assertNotEqual(dir.transport.base, target.transport.base)
121
self.assertDirectoriesEqual(dir.root_transport, target.root_transport)
123
def test_clone_bzrdir_repository(self):
124
dir = self.make_bzrdir('source')
125
repo = dir.create_repository()
126
# add some content to differentiate from an empty repository.
127
repo.control_weaves.add_text('inventory',
131
repo.get_transaction())
132
target = dir.clone(self.get_url('target'))
133
self.assertNotEqual(dir.transport.base, target.transport.base)
134
self.assertDirectoriesEqual(dir.root_transport, target.root_transport)
136
def test_clone_bzrdir_repository_under_shared(self):
137
dir = self.make_bzrdir('source')
138
repo = dir.create_repository()
139
# add some content to differentiate from an empty repository.
140
repo.control_weaves.add_text('inventory',
144
repo.get_transaction())
146
self.make_repository('target', shared=True)
147
except errors.IncompatibleFormat:
149
target = dir.clone(self.get_url('target/child'))
150
self.assertNotEqual(dir.transport.base, target.transport.base)
151
self.assertRaises(errors.NoRepositoryPresent, target.open_repository)
153
def test_clone_bzrdir_repository_under_shared_force_new_repo(self):
154
dir = self.make_bzrdir('source')
155
repo = dir.create_repository()
156
# add some content to differentiate from an empty repository.
157
repo.control_weaves.add_text('inventory',
161
repo.get_transaction())
163
self.make_repository('target', shared=True)
164
except errors.IncompatibleFormat:
166
target = dir.clone(self.get_url('target/child'), force_new_repo=True)
167
self.assertNotEqual(dir.transport.base, target.transport.base)
168
self.assertDirectoriesEqual(dir.root_transport, target.root_transport)
170
def test_clone_bzrdir_repository_revision(self):
171
# test for revision limiting, [smoke test, not corner case checks].
172
# make a repository with some revisions,
173
# and clone it with a revision limit.
175
tree = self.make_branch_and_tree('commit_tree')
176
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
178
tree.commit('revision 1', rev_id='1')
179
tree.bzrdir.open_branch().set_revision_history([])
180
tree.set_last_revision(None)
181
tree.commit('revision 2', rev_id='2')
182
source = self.make_repository('source')
183
tree.bzrdir.open_repository().copy_content_into(source)
185
target = dir.clone(self.get_url('target'), revision_id='2')
186
raise TestSkipped('revision limiting not strict yet')
188
def test_clone_bzrdir_branch_and_repo(self):
189
tree = self.make_branch_and_tree('commit_tree')
190
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
192
tree.commit('revision 1')
193
source = self.make_branch('source')
194
tree.bzrdir.open_repository().copy_content_into(source.repository)
195
tree.bzrdir.open_branch().copy_content_into(source)
197
target = dir.clone(self.get_url('target'))
198
self.assertNotEqual(dir.transport.base, target.transport.base)
199
self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
200
['./.bzr/stat-cache', './.bzr/checkout/stat-cache'])
202
def test_clone_bzrdir_branch_and_repo_into_shared_repo(self):
203
# by default cloning into a shared repo uses the shared repo.
204
tree = self.make_branch_and_tree('commit_tree')
205
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
207
tree.commit('revision 1')
208
source = self.make_branch('source')
209
tree.bzrdir.open_repository().copy_content_into(source.repository)
210
tree.bzrdir.open_branch().copy_content_into(source)
212
self.make_repository('target', shared=True)
213
except errors.IncompatibleFormat:
216
target = dir.clone(self.get_url('target/child'))
217
self.assertNotEqual(dir.transport.base, target.transport.base)
218
self.assertRaises(errors.NoRepositoryPresent, target.open_repository)
219
self.assertEqual(source.revision_history(),
220
target.open_branch().revision_history())
222
def test_clone_bzrdir_branch_and_repo_into_shared_repo_force_new_repo(self):
223
# by default cloning into a shared repo uses the shared repo.
224
tree = self.make_branch_and_tree('commit_tree')
225
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
227
tree.commit('revision 1')
228
source = self.make_branch('source')
229
tree.bzrdir.open_repository().copy_content_into(source.repository)
230
tree.bzrdir.open_branch().copy_content_into(source)
232
self.make_repository('target', shared=True)
233
except errors.IncompatibleFormat:
236
target = dir.clone(self.get_url('target/child'), force_new_repo=True)
237
self.assertNotEqual(dir.transport.base, target.transport.base)
238
target.open_repository()
239
self.assertDirectoriesEqual(dir.root_transport, target.root_transport)
241
def test_clone_bzrdir_branch_reference(self):
242
# cloning should preserve the reference status of the branch in a bzrdir
243
referenced_branch = self.make_branch('referencced')
244
dir = self.make_bzrdir('source')
246
reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
248
except errors.IncompatibleFormat:
249
# this is ok too, not all formats have to support references.
251
target = dir.clone(self.get_url('target'))
252
self.assertNotEqual(dir.transport.base, target.transport.base)
253
self.assertDirectoriesEqual(dir.root_transport, target.root_transport)
255
def test_clone_bzrdir_branch_revision(self):
256
# test for revision limiting, [smoke test, not corner case checks].
257
# make a branch with some revisions,
258
# and clone it with a revision limit.
260
tree = self.make_branch_and_tree('commit_tree')
261
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
263
tree.commit('revision 1', rev_id='1')
264
tree.commit('revision 2', rev_id='2', allow_pointless=True)
265
source = self.make_branch('source')
266
tree.bzrdir.open_repository().copy_content_into(source.repository)
267
tree.bzrdir.open_branch().copy_content_into(source)
269
target = dir.clone(self.get_url('target'), revision_id='1')
270
self.assertEqual('1', target.open_branch().last_revision())
272
def test_clone_bzrdir_tree_branch_repo(self):
273
tree = self.make_branch_and_tree('sourcce')
274
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
276
tree.commit('revision 1')
278
target = dir.clone(self.get_url('target'))
279
self.assertNotEqual(dir.transport.base, target.transport.base)
280
self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
281
['./.bzr/stat-cache', './.bzr/checkout/stat-cache'])
283
def test_clone_bzrdir_tree_branch_reference(self):
284
# a tree with a branch reference (aka a checkout)
285
# should stay a checkout on clone.
286
referenced_branch = self.make_branch('referencced')
287
dir = self.make_bzrdir('source')
289
reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
291
except errors.IncompatibleFormat:
292
# this is ok too, not all formats have to support references.
294
dir.create_workingtree()
295
target = dir.clone(self.get_url('target'))
296
self.assertNotEqual(dir.transport.base, target.transport.base)
297
self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
298
['./.bzr/stat-cache', './.bzr/checkout/stat-cache'])
300
def test_clone_bzrdir_tree_revision(self):
301
# test for revision limiting, [smoke test, not corner case checks].
302
# make a tree with a revision with a last-revision
303
# and clone it with a revision limit.
304
# This smoke test just checks the revision-id is right. Tree specific
305
# tests will check corner cases.
306
tree = self.make_branch_and_tree('source')
307
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
309
tree.commit('revision 1', rev_id='1')
310
tree.commit('revision 2', rev_id='2', allow_pointless=True)
312
target = dir.clone(self.get_url('target'), revision_id='1')
313
self.assertEqual('1', target.open_workingtree().last_revision())
315
def test_clone_bzrdir_incomplete_source_with_basis(self):
316
# ensure that basis really does grab from the basis by having incomplete source
317
tree = self.make_branch_and_tree('commit_tree')
318
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
320
tree.commit('revision 1', rev_id='1')
321
source = self.make_branch_and_tree('source')
322
# this gives us an incomplete repository
323
tree.bzrdir.open_repository().copy_content_into(source.branch.repository)
324
tree.commit('revision 2', rev_id='2', allow_pointless=True)
325
tree.bzrdir.open_branch().copy_content_into(source.branch)
326
tree.copy_content_into(source)
327
self.assertFalse(source.branch.repository.has_revision('2'))
329
target = dir.clone(self.get_url('target'), basis=tree.bzrdir)
330
self.assertEqual('2', target.open_branch().last_revision())
331
self.assertEqual('2', target.open_workingtree().last_revision())
332
self.assertTrue(target.open_branch().repository.has_revision('2'))
334
def test_sprout_bzrdir_empty(self):
335
dir = self.make_bzrdir('source')
336
target = dir.sprout(self.get_url('target'))
337
self.assertNotEqual(dir.transport.base, target.transport.base)
338
# creates a new repository branch and tree
339
target.open_repository()
341
target.open_workingtree()
343
def test_sprout_bzrdir_empty_under_shared_repo(self):
344
# sprouting an empty dir into a repo uses the repo
345
dir = self.make_bzrdir('source')
347
self.make_repository('target', shared=True)
348
except errors.IncompatibleFormat:
350
target = dir.sprout(self.get_url('target/child'))
351
self.assertRaises(errors.NoRepositoryPresent, target.open_repository)
353
target.open_workingtree()
355
def test_sprout_bzrdir_empty_under_shared_repo(self):
356
# the force_new_repo parameter should force use of a new repo in an empty
357
# bzrdir's sprout logic
358
dir = self.make_bzrdir('source')
360
self.make_repository('target', shared=True)
361
except errors.IncompatibleFormat:
363
target = dir.sprout(self.get_url('target/child'), force_new_repo=True)
364
target.open_repository()
366
target.open_workingtree()
368
def test_sprout_bzrdir_repository(self):
369
dir = self.make_bzrdir('source')
370
repo = dir.create_repository()
371
# add some content to differentiate from an empty repository.
372
repo.control_weaves.add_text('inventory',
376
repo.get_transaction())
377
target = dir.sprout(self.get_url('target'))
378
self.assertNotEqual(dir.transport.base, target.transport.base)
379
self.assertDirectoriesEqual(dir.root_transport, target.root_transport)
381
def test_sprout_bzrdir_repository_under_shared(self):
382
tree = self.make_branch_and_tree('commit_tree')
383
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
385
tree.commit('revision 1', rev_id='1')
386
tree.bzrdir.open_branch().set_revision_history([])
387
tree.set_last_revision(None)
388
tree.commit('revision 2', rev_id='2')
389
source = self.make_repository('source')
390
tree.bzrdir.open_repository().copy_content_into(source)
393
shared_repo = self.make_repository('target', shared=True)
394
except errors.IncompatibleFormat:
396
target = dir.sprout(self.get_url('target/child'))
397
self.assertNotEqual(dir.transport.base, target.transport.base)
398
self.assertTrue(shared_repo.has_revision('1'))
400
def test_sprout_bzrdir_repository_under_shared_force_new_repo(self):
401
tree = self.make_branch_and_tree('commit_tree')
402
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
404
tree.commit('revision 1', rev_id='1')
405
tree.bzrdir.open_branch().set_revision_history([])
406
tree.set_last_revision(None)
407
tree.commit('revision 2', rev_id='2')
408
source = self.make_repository('source')
409
tree.bzrdir.open_repository().copy_content_into(source)
412
shared_repo = self.make_repository('target', shared=True)
413
except errors.IncompatibleFormat:
415
target = dir.sprout(self.get_url('target/child'), force_new_repo=True)
416
self.assertNotEqual(dir.transport.base, target.transport.base)
417
self.assertFalse(shared_repo.has_revision('1'))
419
def test_sprout_bzrdir_repository_revision(self):
420
# test for revision limiting, [smoke test, not corner case checks].
421
# make a repository with some revisions,
422
# and sprout it with a revision limit.
424
tree = self.make_branch_and_tree('commit_tree')
425
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
427
tree.commit('revision 1', rev_id='1')
428
tree.bzrdir.open_branch().set_revision_history([])
429
tree.set_last_revision(None)
430
tree.commit('revision 2', rev_id='2')
431
source = self.make_repository('source')
432
tree.bzrdir.open_repository().copy_content_into(source)
434
target = dir.sprout(self.get_url('target'), revision_id='2')
435
raise TestSkipped('revision limiting not strict yet')
437
def test_sprout_bzrdir_branch_and_repo(self):
438
tree = self.make_branch_and_tree('commit_tree')
439
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
441
tree.commit('revision 1')
442
source = self.make_branch('source')
443
tree.bzrdir.open_repository().copy_content_into(source.repository)
444
tree.bzrdir.open_branch().copy_content_into(source)
446
target = dir.sprout(self.get_url('target'))
447
self.assertNotEqual(dir.transport.base, target.transport.base)
448
self.assertDirectoriesEqual(dir.root_transport, target.root_transport)
450
def test_sprout_bzrdir_branch_and_repo_shared(self):
451
# sprouting a branch with a repo into a shared repo uses the shared
453
tree = self.make_branch_and_tree('commit_tree')
454
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
456
tree.commit('revision 1', rev_id='1')
457
source = self.make_branch('source')
458
tree.bzrdir.open_repository().copy_content_into(source.repository)
459
tree.bzrdir.open_branch().copy_content_into(source)
462
shared_repo = self.make_repository('target', shared=True)
463
except errors.IncompatibleFormat:
465
target = dir.sprout(self.get_url('target/child'))
466
self.assertTrue(shared_repo.has_revision('1'))
468
def test_sprout_bzrdir_branch_and_repo_shared_force_new_repo(self):
469
# sprouting a branch with a repo into a shared repo uses the shared
471
tree = self.make_branch_and_tree('commit_tree')
472
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
474
tree.commit('revision 1', rev_id='1')
475
source = self.make_branch('source')
476
tree.bzrdir.open_repository().copy_content_into(source.repository)
477
tree.bzrdir.open_branch().copy_content_into(source)
480
shared_repo = self.make_repository('target', shared=True)
481
except errors.IncompatibleFormat:
483
target = dir.sprout(self.get_url('target/child'), force_new_repo=True)
484
self.assertNotEqual(dir.transport.base, target.transport.base)
485
self.assertFalse(shared_repo.has_revision('1'))
487
def test_sprout_bzrdir_branch_reference(self):
488
# sprouting should create a repository if needed and a sprouted branch.
489
referenced_branch = self.make_branch('referencced')
490
dir = self.make_bzrdir('source')
492
reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
494
except errors.IncompatibleFormat:
495
# this is ok too, not all formats have to support references.
497
self.assertRaises(errors.NoRepositoryPresent, dir.open_repository)
498
target = dir.sprout(self.get_url('target'))
499
self.assertNotEqual(dir.transport.base, target.transport.base)
500
# we want target to have a branch that is in-place.
501
self.assertEqual(target, target.open_branch().bzrdir)
502
# and as we dont support repositories being detached yet, a repo in
504
target.open_repository()
506
def test_sprout_bzrdir_branch_reference_shared(self):
507
# sprouting should create a repository if needed and a sprouted branch.
508
referenced_tree = self.make_branch_and_tree('referenced')
509
referenced_tree.commit('1', rev_id='1', allow_pointless=True)
510
dir = self.make_bzrdir('source')
512
reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
513
referenced_tree.branch)
514
except errors.IncompatibleFormat:
515
# this is ok too, not all formats have to support references.
517
self.assertRaises(errors.NoRepositoryPresent, dir.open_repository)
519
shared_repo = self.make_repository('target', shared=True)
520
except errors.IncompatibleFormat:
522
target = dir.sprout(self.get_url('target/child'))
523
self.assertNotEqual(dir.transport.base, target.transport.base)
524
# we want target to have a branch that is in-place.
525
self.assertEqual(target, target.open_branch().bzrdir)
526
# and we want no repository as the target is shared
527
self.assertRaises(errors.NoRepositoryPresent,
528
target.open_repository)
529
# and we want revision '1' in the shared repo
530
self.assertTrue(shared_repo.has_revision('1'))
532
def test_sprout_bzrdir_branch_reference_shared_force_new_repo(self):
533
# sprouting should create a repository if needed and a sprouted branch.
534
referenced_tree = self.make_branch_and_tree('referenced')
535
referenced_tree.commit('1', rev_id='1', allow_pointless=True)
536
dir = self.make_bzrdir('source')
538
reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
539
referenced_tree.branch)
540
except errors.IncompatibleFormat:
541
# this is ok too, not all formats have to support references.
543
self.assertRaises(errors.NoRepositoryPresent, dir.open_repository)
545
shared_repo = self.make_repository('target', shared=True)
546
except errors.IncompatibleFormat:
548
target = dir.sprout(self.get_url('target/child'), force_new_repo=True)
549
self.assertNotEqual(dir.transport.base, target.transport.base)
550
# we want target to have a branch that is in-place.
551
self.assertEqual(target, target.open_branch().bzrdir)
552
# and we want revision '1' in the new repo
553
self.assertTrue(target.open_repository().has_revision('1'))
554
# but not the shared one
555
self.assertFalse(shared_repo.has_revision('1'))
557
def test_sprout_bzrdir_branch_revision(self):
558
# test for revision limiting, [smoke test, not corner case checks].
559
# make a repository with some revisions,
560
# and sprout it with a revision limit.
562
tree = self.make_branch_and_tree('commit_tree')
563
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
565
tree.commit('revision 1', rev_id='1')
566
tree.commit('revision 2', rev_id='2', allow_pointless=True)
567
source = self.make_branch('source')
568
tree.bzrdir.open_repository().copy_content_into(source.repository)
569
tree.bzrdir.open_branch().copy_content_into(source)
571
target = dir.sprout(self.get_url('target'), revision_id='1')
572
self.assertEqual('1', target.open_branch().last_revision())
574
def test_sprout_bzrdir_tree_branch_repo(self):
575
tree = self.make_branch_and_tree('sourcce')
576
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
578
tree.commit('revision 1')
580
target = dir.sprout(self.get_url('target'))
581
self.assertNotEqual(dir.transport.base, target.transport.base)
582
self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
583
['./.bzr/stat-cache', './.bzr/checkout/stat-cache'])
585
def test_sprout_bzrdir_tree_branch_reference(self):
586
# sprouting should create a repository if needed and a sprouted branch.
587
# the tree state should be copied.
588
referenced_branch = self.make_branch('referencced')
589
dir = self.make_bzrdir('source')
591
reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
593
except errors.IncompatibleFormat:
594
# this is ok too, not all formats have to support references.
596
self.assertRaises(errors.NoRepositoryPresent, dir.open_repository)
597
dir.create_workingtree()
598
target = dir.sprout(self.get_url('target'))
599
self.assertNotEqual(dir.transport.base, target.transport.base)
600
# we want target to have a branch that is in-place.
601
self.assertEqual(target, target.open_branch().bzrdir)
602
# and as we dont support repositories being detached yet, a repo in
604
target.open_repository()
605
# we trust that the working tree sprouting works via the other tests.
606
target.open_workingtree()
608
def test_sprout_bzrdir_tree_branch_reference_revision(self):
609
# sprouting should create a repository if needed and a sprouted branch.
610
# the tree state should be copied but the revision changed,
611
# and the likewise the new branch should be truncated too
612
referenced_branch = self.make_branch('referencced')
613
dir = self.make_bzrdir('source')
615
reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
617
except errors.IncompatibleFormat:
618
# this is ok too, not all formats have to support references.
620
self.assertRaises(errors.NoRepositoryPresent, dir.open_repository)
621
tree = dir.create_workingtree()
622
self.build_tree(['foo'], transport=dir.root_transport)
624
tree.commit('revision 1', rev_id='1')
625
tree.commit('revision 2', rev_id='2', allow_pointless=True)
626
target = dir.sprout(self.get_url('target'), revision_id='1')
627
self.assertNotEqual(dir.transport.base, target.transport.base)
628
# we want target to have a branch that is in-place.
629
self.assertEqual(target, target.open_branch().bzrdir)
630
# and as we dont support repositories being detached yet, a repo in
632
target.open_repository()
633
# we trust that the working tree sprouting works via the other tests.
634
self.assertEqual('1', target.open_workingtree().last_revision())
635
self.assertEqual('1', target.open_branch().last_revision())
637
def test_sprout_bzrdir_tree_revision(self):
638
# test for revision limiting, [smoke test, not corner case checks].
639
# make a tree with a revision with a last-revision
640
# and sprout it with a revision limit.
641
# This smoke test just checks the revision-id is right. Tree specific
642
# tests will check corner cases.
643
tree = self.make_branch_and_tree('source')
644
self.build_tree(['foo'], transport=tree.bzrdir.root_transport)
646
tree.commit('revision 1', rev_id='1')
647
tree.commit('revision 2', rev_id='2', allow_pointless=True)
649
target = dir.sprout(self.get_url('target'), revision_id='1')
650
self.assertEqual('1', target.open_workingtree().last_revision())
652
def test_sprout_bzrdir_incomplete_source_with_basis(self):
653
# ensure that basis really does grab from the basis by having incomplete source
654
tree = self.make_branch_and_tree('commit_tree')
655
self.build_tree(['foo'], transport=tree.bzrdir.root_transport)
657
tree.commit('revision 1', rev_id='1')
658
source = self.make_branch_and_tree('source')
659
# this gives us an incomplete repository
660
tree.bzrdir.open_repository().copy_content_into(source.branch.repository)
661
tree.commit('revision 2', rev_id='2', allow_pointless=True)
662
tree.bzrdir.open_branch().copy_content_into(source.branch)
663
tree.copy_content_into(source)
664
self.assertFalse(source.branch.repository.has_revision('2'))
666
target = dir.sprout(self.get_url('target'), basis=tree.bzrdir)
667
self.assertEqual('2', target.open_branch().last_revision())
668
self.assertEqual('2', target.open_workingtree().last_revision())
669
self.assertTrue(target.open_branch().repository.has_revision('2'))
671
def test_format_initialize_find_open(self):
672
# loopback test to check the current format initializes to itself.
673
if not self.bzrdir_format.is_supported():
674
# unsupported formats are not loopback testable
675
# because the default open will not open them and
676
# they may not be initializable.
678
# supported formats must be able to init and open
679
t = get_transport(self.get_url())
680
readonly_t = get_transport(self.get_readonly_url())
681
made_control = self.bzrdir_format.initialize(t.base)
682
self.failUnless(isinstance(made_control, bzrdir.BzrDir))
683
self.assertEqual(self.bzrdir_format,
684
bzrdir.BzrDirFormat.find_format(readonly_t))
685
direct_opened_dir = self.bzrdir_format.open(readonly_t)
686
opened_dir = bzrdir.BzrDir.open(t.base)
687
self.assertEqual(made_control._format,
689
self.assertEqual(direct_opened_dir._format,
691
self.failUnless(isinstance(opened_dir, bzrdir.BzrDir))
693
def test_open_not_bzrdir(self):
694
# test the formats specific behaviour for no-content or similar dirs.
695
self.assertRaises(NotBranchError,
696
self.bzrdir_format.open,
697
get_transport(self.get_readonly_url()))
699
def test_create_branch(self):
700
# a bzrdir can construct a branch and repository for itself.
701
if not self.bzrdir_format.is_supported():
702
# unsupported formats are not loopback testable
703
# because the default open will not open them and
704
# they may not be initializable.
706
t = get_transport(self.get_url())
707
made_control = self.bzrdir_format.initialize(t.base)
708
made_repo = made_control.create_repository()
709
made_branch = made_control.create_branch()
710
self.failUnless(isinstance(made_branch, bzrlib.branch.Branch))
711
self.assertEqual(made_control, made_branch.bzrdir)
713
def test_open_branch(self):
714
if not self.bzrdir_format.is_supported():
715
# unsupported formats are not loopback testable
716
# because the default open will not open them and
717
# they may not be initializable.
719
t = get_transport(self.get_url())
720
made_control = self.bzrdir_format.initialize(t.base)
721
made_repo = made_control.create_repository()
722
made_branch = made_control.create_branch()
723
opened_branch = made_control.open_branch()
724
self.assertEqual(made_control, opened_branch.bzrdir)
725
self.failUnless(isinstance(opened_branch, made_branch.__class__))
726
self.failUnless(isinstance(opened_branch._format, made_branch._format.__class__))
728
def test_create_repository(self):
729
# a bzrdir can construct a repository for itself.
730
if not self.bzrdir_format.is_supported():
731
# unsupported formats are not loopback testable
732
# because the default open will not open them and
733
# they may not be initializable.
735
t = get_transport(self.get_url())
736
made_control = self.bzrdir_format.initialize(t.base)
737
made_repo = made_control.create_repository()
738
self.failUnless(isinstance(made_repo, repository.Repository))
739
self.assertEqual(made_control, made_repo.bzrdir)
741
def test_open_repository(self):
742
if not self.bzrdir_format.is_supported():
743
# unsupported formats are not loopback testable
744
# because the default open will not open them and
745
# they may not be initializable.
747
t = get_transport(self.get_url())
748
made_control = self.bzrdir_format.initialize(t.base)
749
made_repo = made_control.create_repository()
750
opened_repo = made_control.open_repository()
751
self.assertEqual(made_control, opened_repo.bzrdir)
752
self.failUnless(isinstance(opened_repo, made_repo.__class__))
753
self.failUnless(isinstance(opened_repo._format, made_repo._format.__class__))
755
def test_create_workingtree(self):
756
# a bzrdir can construct a working tree for itself.
757
if not self.bzrdir_format.is_supported():
758
# unsupported formats are not loopback testable
759
# because the default open will not open them and
760
# they may not be initializable.
762
# this has to be tested with local access as we still support creating
764
t = get_transport('.')
765
made_control = self.bzrdir_format.initialize(t.base)
766
made_repo = made_control.create_repository()
767
made_branch = made_control.create_branch()
768
made_tree = made_control.create_workingtree()
769
self.failUnless(isinstance(made_tree, workingtree.WorkingTree))
770
self.assertEqual(made_control, made_tree.bzrdir)
772
def test_create_workingtree_revision(self):
773
# a bzrdir can construct a working tree for itself @ a specific revision.
774
source = self.make_branch_and_tree('source')
775
source.commit('a', rev_id='a', allow_pointless=True)
776
source.commit('b', rev_id='b', allow_pointless=True)
777
self.build_tree(['new/'])
778
made_control = self.bzrdir_format.initialize('new')
779
source.branch.repository.clone(made_control)
780
source.branch.clone(made_control)
781
made_tree = made_control.create_workingtree(revision_id='a')
782
self.assertEqual('a', made_tree.last_revision())
784
def test_open_workingtree(self):
785
if not self.bzrdir_format.is_supported():
786
# unsupported formats are not loopback testable
787
# because the default open will not open them and
788
# they may not be initializable.
790
# this has to be tested with local access as we still support creating
792
t = get_transport('.')
793
made_control = self.bzrdir_format.initialize(t.base)
794
made_repo = made_control.create_repository()
795
made_branch = made_control.create_branch()
796
made_tree = made_control.create_workingtree()
797
opened_tree = made_control.open_workingtree()
798
self.assertEqual(made_control, opened_tree.bzrdir)
799
self.failUnless(isinstance(opened_tree, made_tree.__class__))
800
self.failUnless(isinstance(opened_tree._format, made_tree._format.__class__))
802
def test_get_branch_transport(self):
803
dir = self.make_bzrdir('.')
804
# without a format, get_branch_transport gives use a transport
805
# which -may- point to an existing dir.
806
self.assertTrue(isinstance(dir.get_branch_transport(None),
807
transport.Transport))
808
# with a given format, either the bzr dir supports identifiable
809
# branches, or it supports anonymous branch formats, but not both.
810
anonymous_format = bzrlib.branch.BzrBranchFormat4()
811
identifiable_format = bzrlib.branch.BzrBranchFormat5()
813
found_transport = dir.get_branch_transport(anonymous_format)
814
self.assertRaises(errors.IncompatibleFormat,
815
dir.get_branch_transport,
817
except errors.IncompatibleFormat:
818
found_transport = dir.get_branch_transport(identifiable_format)
819
self.assertTrue(isinstance(found_transport, transport.Transport))
820
# and the dir which has been initialized for us must be statable.
821
found_transport.stat('.')
823
def test_get_repository_transport(self):
824
dir = self.make_bzrdir('.')
825
# without a format, get_repository_transport gives use a transport
826
# which -may- point to an existing dir.
827
self.assertTrue(isinstance(dir.get_repository_transport(None),
828
transport.Transport))
829
# with a given format, either the bzr dir supports identifiable
830
# repositoryes, or it supports anonymous repository formats, but not both.
831
anonymous_format = repository.RepositoryFormat6()
832
identifiable_format = repository.RepositoryFormat7()
834
found_transport = dir.get_repository_transport(anonymous_format)
835
self.assertRaises(errors.IncompatibleFormat,
836
dir.get_repository_transport,
838
except errors.IncompatibleFormat:
839
found_transport = dir.get_repository_transport(identifiable_format)
840
self.assertTrue(isinstance(found_transport, transport.Transport))
841
# and the dir which has been initialized for us must be statable.
842
found_transport.stat('.')
844
def test_get_workingtree_transport(self):
845
dir = self.make_bzrdir('.')
846
# without a format, get_workingtree_transport gives use a transport
847
# which -may- point to an existing dir.
848
self.assertTrue(isinstance(dir.get_workingtree_transport(None),
849
transport.Transport))
850
# with a given format, either the bzr dir supports identifiable
851
# trees, or it supports anonymous tree formats, but not both.
852
anonymous_format = workingtree.WorkingTreeFormat2()
853
identifiable_format = workingtree.WorkingTreeFormat3()
855
found_transport = dir.get_workingtree_transport(anonymous_format)
856
self.assertRaises(errors.IncompatibleFormat,
857
dir.get_workingtree_transport,
859
except errors.IncompatibleFormat:
860
found_transport = dir.get_workingtree_transport(identifiable_format)
861
self.assertTrue(isinstance(found_transport, transport.Transport))
862
# and the dir which has been initialized for us must be statable.
863
found_transport.stat('.')
865
def test_root_transport(self):
866
dir = self.make_bzrdir('.')
867
self.assertEqual(dir.root_transport.base,
868
get_transport(self.get_url('.')).base)
870
def test_find_repository_no_repo_under_standalone_branch(self):
871
# finding a repo stops at standalone branches even if there is a
872
# higher repository available.
874
repo = self.make_repository('.', shared=True)
875
except errors.IncompatibleFormat:
876
# need a shared repository to test this.
878
url = self.get_url('intermediate')
879
get_transport(self.get_url()).mkdir('intermediate')
880
get_transport(self.get_url()).mkdir('intermediate/child')
881
made_control = self.bzrdir_format.initialize(url)
882
made_control.create_repository()
883
innermost_control = self.bzrdir_format.initialize(
884
self.get_url('intermediate/child'))
886
child_repo = innermost_control.open_repository()
887
# if there is a repository, then the format cannot ever hit this
890
except errors.NoRepositoryPresent:
892
self.assertRaises(errors.NoRepositoryPresent,
893
innermost_control.find_repository)
895
def test_find_repository_containing_shared_repository(self):
896
# find repo inside a shared repo with an empty control dir
897
# returns the shared repo.
899
repo = self.make_repository('.', shared=True)
900
except errors.IncompatibleFormat:
901
# need a shared repository to test this.
903
url = self.get_url('childbzrdir')
904
get_transport(self.get_url()).mkdir('childbzrdir')
905
made_control = self.bzrdir_format.initialize(url)
907
child_repo = made_control.open_repository()
908
# if there is a repository, then the format cannot ever hit this
911
except errors.NoRepositoryPresent:
913
found_repo = made_control.find_repository()
914
self.assertEqual(repo.bzrdir.root_transport.base,
915
found_repo.bzrdir.root_transport.base)
917
def test_find_repository_standalone_with_containing_shared_repository(self):
918
# find repo inside a standalone repo inside a shared repo finds the standalone repo
920
containing_repo = self.make_repository('.', shared=True)
921
except errors.IncompatibleFormat:
922
# need a shared repository to test this.
924
child_repo = self.make_repository('childrepo')
925
opened_control = bzrdir.BzrDir.open(self.get_url('childrepo'))
926
found_repo = opened_control.find_repository()
927
self.assertEqual(child_repo.bzrdir.root_transport.base,
928
found_repo.bzrdir.root_transport.base)
930
def test_find_repository_shared_within_shared_repository(self):
931
# find repo at a shared repo inside a shared repo finds the inner repo
933
containing_repo = self.make_repository('.', shared=True)
934
except errors.IncompatibleFormat:
935
# need a shared repository to test this.
937
url = self.get_url('childrepo')
938
get_transport(self.get_url()).mkdir('childrepo')
939
child_control = self.bzrdir_format.initialize(url)
940
child_repo = child_control.create_repository(shared=True)
941
opened_control = bzrdir.BzrDir.open(self.get_url('childrepo'))
942
found_repo = opened_control.find_repository()
943
self.assertEqual(child_repo.bzrdir.root_transport.base,
944
found_repo.bzrdir.root_transport.base)
945
self.assertNotEqual(child_repo.bzrdir.root_transport.base,
946
containing_repo.bzrdir.root_transport.base)
948
def test_find_repository_with_nested_dirs_works(self):
949
# find repo inside a bzrdir inside a bzrdir inside a shared repo
950
# finds the outer shared repo.
952
repo = self.make_repository('.', shared=True)
953
except errors.IncompatibleFormat:
954
# need a shared repository to test this.
956
url = self.get_url('intermediate')
957
get_transport(self.get_url()).mkdir('intermediate')
958
get_transport(self.get_url()).mkdir('intermediate/child')
959
made_control = self.bzrdir_format.initialize(url)
961
child_repo = made_control.open_repository()
962
# if there is a repository, then the format cannot ever hit this
965
except errors.NoRepositoryPresent:
967
innermost_control = self.bzrdir_format.initialize(
968
self.get_url('intermediate/child'))
970
child_repo = innermost_control.open_repository()
971
# if there is a repository, then the format cannot ever hit this
974
except errors.NoRepositoryPresent:
976
found_repo = innermost_control.find_repository()
977
self.assertEqual(repo.bzrdir.root_transport.base,
978
found_repo.bzrdir.root_transport.base)
980
def test_can_and_needs_format_conversion(self):
981
# check that we can ask an instance if its upgradable
982
dir = self.make_bzrdir('.')
983
if dir.can_convert_format():
984
# if its updatable there must be an updater
985
self.assertTrue(isinstance(dir._format.get_converter(),
987
dir.needs_format_conversion(None)
989
def test_upgrade_new_instance(self):
990
"""Does an available updater work ?."""
991
dir = self.make_bzrdir('.')
992
if dir.can_convert_format():
993
dir._format.get_converter(None).convert(dir, ui.ui_factory.progress_bar())
994
# and it should pass 'check' now.
995
check(bzrdir.BzrDir.open(self.get_url('.')).open_branch(), False)
998
class ChrootedBzrDirTests(ChrootedTestCase):
1000
def test_find_repository_no_repository(self):
1001
# loopback test to check the current format fails to find a
1002
# share repository correctly.
1003
if not self.bzrdir_format.is_supported():
1004
# unsupported formats are not loopback testable
1005
# because the default open will not open them and
1006
# they may not be initializable.
1008
# supported formats must be able to init and open
1009
url = self.get_url('subdir')
1010
get_transport(self.get_url()).mkdir('subdir')
1011
made_control = self.bzrdir_format.initialize(url)
1013
repo = made_control.open_repository()
1014
# if there is a repository, then the format cannot ever hit this
1017
except errors.NoRepositoryPresent:
1019
opened_control = bzrdir.BzrDir.open(self.get_readonly_url('subdir'))
1020
self.assertRaises(errors.NoRepositoryPresent,
1021
opened_control.find_repository)