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
tree = self.make_branch_and_tree('commit_tree')
125
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
127
tree.commit('revision 1', rev_id='1')
128
dir = self.make_bzrdir('source')
129
repo = dir.create_repository()
130
repo.fetch(tree.branch.repository)
131
self.assertTrue(repo.has_revision('1'))
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
tree = self.make_branch_and_tree('commit_tree')
138
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
140
tree.commit('revision 1', rev_id='1')
141
dir = self.make_bzrdir('source')
142
repo = dir.create_repository()
143
repo.fetch(tree.branch.repository)
144
self.assertTrue(repo.has_revision('1'))
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_branch_both_under_shared(self):
155
shared_repo = self.make_repository('shared', shared=True)
156
except errors.IncompatibleFormat:
158
tree = self.make_branch_and_tree('commit_tree')
159
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
161
tree.commit('revision 1', rev_id='1')
162
tree.bzrdir.open_branch().set_revision_history([])
163
tree.set_last_revision(None)
164
tree.commit('revision 2', rev_id='2')
165
tree.bzrdir.open_repository().copy_content_into(shared_repo)
166
dir = self.make_bzrdir('shared/source')
168
target = dir.clone(self.get_url('shared/target'))
169
self.assertNotEqual(dir.transport.base, target.transport.base)
170
self.assertNotEqual(dir.transport.base, shared_repo.bzrdir.transport.base)
171
self.assertTrue(shared_repo.has_revision('1'))
173
def test_clone_bzrdir_repository_under_shared_force_new_repo(self):
174
tree = self.make_branch_and_tree('commit_tree')
175
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
177
tree.commit('revision 1', rev_id='1')
178
dir = self.make_bzrdir('source')
179
repo = dir.create_repository()
180
repo.fetch(tree.branch.repository)
181
self.assertTrue(repo.has_revision('1'))
183
self.make_repository('target', shared=True)
184
except errors.IncompatibleFormat:
186
target = dir.clone(self.get_url('target/child'), force_new_repo=True)
187
self.assertNotEqual(dir.transport.base, target.transport.base)
188
self.assertDirectoriesEqual(dir.root_transport, target.root_transport)
190
def test_clone_bzrdir_repository_revision(self):
191
# test for revision limiting, [smoke test, not corner case checks].
192
# make a repository with some revisions,
193
# and clone it with a revision limit.
195
tree = self.make_branch_and_tree('commit_tree')
196
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
198
tree.commit('revision 1', rev_id='1')
199
tree.bzrdir.open_branch().set_revision_history([])
200
tree.set_last_revision(None)
201
tree.commit('revision 2', rev_id='2')
202
source = self.make_repository('source')
203
tree.bzrdir.open_repository().copy_content_into(source)
205
target = dir.clone(self.get_url('target'), revision_id='2')
206
raise TestSkipped('revision limiting not strict yet')
208
def test_clone_bzrdir_branch_and_repo(self):
209
tree = self.make_branch_and_tree('commit_tree')
210
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
212
tree.commit('revision 1')
213
source = self.make_branch('source')
214
tree.bzrdir.open_repository().copy_content_into(source.repository)
215
tree.bzrdir.open_branch().copy_content_into(source)
217
target = dir.clone(self.get_url('target'))
218
self.assertNotEqual(dir.transport.base, target.transport.base)
219
self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
220
['./.bzr/stat-cache', './.bzr/checkout/stat-cache'])
222
def test_clone_bzrdir_branch_and_repo_into_shared_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'))
237
self.assertNotEqual(dir.transport.base, target.transport.base)
238
self.assertRaises(errors.NoRepositoryPresent, target.open_repository)
239
self.assertEqual(source.revision_history(),
240
target.open_branch().revision_history())
242
def test_clone_bzrdir_branch_and_repo_into_shared_repo_force_new_repo(self):
243
# by default cloning into a shared repo uses the shared repo.
244
tree = self.make_branch_and_tree('commit_tree')
245
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
247
tree.commit('revision 1')
248
source = self.make_branch('source')
249
tree.bzrdir.open_repository().copy_content_into(source.repository)
250
tree.bzrdir.open_branch().copy_content_into(source)
252
self.make_repository('target', shared=True)
253
except errors.IncompatibleFormat:
256
target = dir.clone(self.get_url('target/child'), force_new_repo=True)
257
self.assertNotEqual(dir.transport.base, target.transport.base)
258
target.open_repository()
259
self.assertDirectoriesEqual(dir.root_transport, target.root_transport)
261
def test_clone_bzrdir_branch_reference(self):
262
# cloning should preserve the reference status of the branch in a bzrdir
263
referenced_branch = self.make_branch('referencced')
264
dir = self.make_bzrdir('source')
266
reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
268
except errors.IncompatibleFormat:
269
# this is ok too, not all formats have to support references.
271
target = dir.clone(self.get_url('target'))
272
self.assertNotEqual(dir.transport.base, target.transport.base)
273
self.assertDirectoriesEqual(dir.root_transport, target.root_transport)
275
def test_clone_bzrdir_branch_revision(self):
276
# test for revision limiting, [smoke test, not corner case checks].
277
# make a branch with some revisions,
278
# and clone it with a revision limit.
280
tree = self.make_branch_and_tree('commit_tree')
281
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
283
tree.commit('revision 1', rev_id='1')
284
tree.commit('revision 2', rev_id='2', allow_pointless=True)
285
source = self.make_branch('source')
286
tree.bzrdir.open_repository().copy_content_into(source.repository)
287
tree.bzrdir.open_branch().copy_content_into(source)
289
target = dir.clone(self.get_url('target'), revision_id='1')
290
self.assertEqual('1', target.open_branch().last_revision())
292
def test_clone_bzrdir_tree_branch_repo(self):
293
tree = self.make_branch_and_tree('sourcce')
294
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
296
tree.commit('revision 1')
298
target = dir.clone(self.get_url('target'))
299
self.assertNotEqual(dir.transport.base, target.transport.base)
300
self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
301
['./.bzr/stat-cache', './.bzr/checkout/stat-cache'])
302
target.open_workingtree().revert([])
304
def test_revert_inventory(self):
305
tree = self.make_branch_and_tree('sourcce')
306
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
308
tree.commit('revision 1')
310
target = dir.clone(self.get_url('target'))
311
self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
312
['./.bzr/stat-cache', './.bzr/checkout/stat-cache'])
313
target.open_workingtree().revert([])
314
self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
315
['./.bzr/stat-cache', './.bzr/checkout/stat-cache'])
317
def test_clone_bzrdir_tree_branch_reference(self):
318
# a tree with a branch reference (aka a checkout)
319
# should stay a checkout on clone.
320
referenced_branch = self.make_branch('referencced')
321
dir = self.make_bzrdir('source')
323
reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
325
except errors.IncompatibleFormat:
326
# this is ok too, not all formats have to support references.
328
dir.create_workingtree()
329
target = dir.clone(self.get_url('target'))
330
self.assertNotEqual(dir.transport.base, target.transport.base)
331
self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
332
['./.bzr/stat-cache', './.bzr/checkout/stat-cache'])
334
def test_clone_bzrdir_tree_revision(self):
335
# test for revision limiting, [smoke test, not corner case checks].
336
# make a tree with a revision with a last-revision
337
# and clone it with a revision limit.
338
# This smoke test just checks the revision-id is right. Tree specific
339
# tests will check corner cases.
340
tree = self.make_branch_and_tree('source')
341
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
343
tree.commit('revision 1', rev_id='1')
344
tree.commit('revision 2', rev_id='2', allow_pointless=True)
346
target = dir.clone(self.get_url('target'), revision_id='1')
347
self.assertEqual('1', target.open_workingtree().last_revision())
349
def test_clone_bzrdir_incomplete_source_with_basis(self):
350
# ensure that basis really does grab from the basis by having incomplete source
351
tree = self.make_branch_and_tree('commit_tree')
352
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
354
tree.commit('revision 1', rev_id='1')
355
source = self.make_branch_and_tree('source')
356
# this gives us an incomplete repository
357
tree.bzrdir.open_repository().copy_content_into(source.branch.repository)
358
tree.commit('revision 2', rev_id='2', allow_pointless=True)
359
tree.bzrdir.open_branch().copy_content_into(source.branch)
360
tree.copy_content_into(source)
361
self.assertFalse(source.branch.repository.has_revision('2'))
363
target = dir.clone(self.get_url('target'), basis=tree.bzrdir)
364
self.assertEqual('2', target.open_branch().last_revision())
365
self.assertEqual('2', target.open_workingtree().last_revision())
366
self.assertTrue(target.open_branch().repository.has_revision('2'))
368
def test_sprout_bzrdir_empty(self):
369
dir = self.make_bzrdir('source')
370
target = dir.sprout(self.get_url('target'))
371
self.assertNotEqual(dir.transport.base, target.transport.base)
372
# creates a new repository branch and tree
373
target.open_repository()
375
target.open_workingtree()
377
def test_sprout_bzrdir_empty_under_shared_repo(self):
378
# sprouting an empty dir into a repo uses the repo
379
dir = self.make_bzrdir('source')
381
self.make_repository('target', shared=True)
382
except errors.IncompatibleFormat:
384
target = dir.sprout(self.get_url('target/child'))
385
self.assertRaises(errors.NoRepositoryPresent, target.open_repository)
387
target.open_workingtree()
389
def test_sprout_bzrdir_empty_under_shared_repo(self):
390
# the force_new_repo parameter should force use of a new repo in an empty
391
# bzrdir's sprout logic
392
dir = self.make_bzrdir('source')
394
self.make_repository('target', shared=True)
395
except errors.IncompatibleFormat:
397
target = dir.sprout(self.get_url('target/child'), force_new_repo=True)
398
target.open_repository()
400
target.open_workingtree()
402
def test_sprout_bzrdir_repository(self):
403
tree = self.make_branch_and_tree('commit_tree')
404
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
406
tree.commit('revision 1', rev_id='1')
407
dir = self.make_bzrdir('source')
408
repo = dir.create_repository()
409
repo.fetch(tree.branch.repository)
410
self.assertTrue(repo.has_revision('1'))
411
target = dir.sprout(self.get_url('target'))
412
self.assertNotEqual(dir.transport.base, target.transport.base)
413
self.assertDirectoriesEqual(dir.root_transport, target.root_transport)
415
def test_sprout_bzrdir_with_repository_to_shared(self):
416
tree = self.make_branch_and_tree('commit_tree')
417
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
419
tree.commit('revision 1', rev_id='1')
420
tree.bzrdir.open_branch().set_revision_history([])
421
tree.set_last_revision(None)
422
tree.commit('revision 2', rev_id='2')
423
source = self.make_repository('source')
424
tree.bzrdir.open_repository().copy_content_into(source)
427
shared_repo = self.make_repository('target', shared=True)
428
except errors.IncompatibleFormat:
430
target = dir.sprout(self.get_url('target/child'))
431
self.assertNotEqual(dir.transport.base, target.transport.base)
432
self.assertTrue(shared_repo.has_revision('1'))
434
def test_sprout_bzrdir_repository_branch_both_under_shared(self):
436
shared_repo = self.make_repository('shared', shared=True)
437
except errors.IncompatibleFormat:
439
tree = self.make_branch_and_tree('commit_tree')
440
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
442
tree.commit('revision 1', rev_id='1')
443
tree.bzrdir.open_branch().set_revision_history([])
444
tree.set_last_revision(None)
445
tree.commit('revision 2', rev_id='2')
446
tree.bzrdir.open_repository().copy_content_into(shared_repo)
447
dir = self.make_bzrdir('shared/source')
449
target = dir.sprout(self.get_url('shared/target'))
450
self.assertNotEqual(dir.transport.base, target.transport.base)
451
self.assertNotEqual(dir.transport.base, shared_repo.bzrdir.transport.base)
452
self.assertTrue(shared_repo.has_revision('1'))
454
def test_sprout_bzrdir_repository_under_shared_force_new_repo(self):
455
tree = self.make_branch_and_tree('commit_tree')
456
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
458
tree.commit('revision 1', rev_id='1')
459
tree.bzrdir.open_branch().set_revision_history([])
460
tree.set_last_revision(None)
461
tree.commit('revision 2', rev_id='2')
462
source = self.make_repository('source')
463
tree.bzrdir.open_repository().copy_content_into(source)
466
shared_repo = self.make_repository('target', shared=True)
467
except errors.IncompatibleFormat:
469
target = dir.sprout(self.get_url('target/child'), force_new_repo=True)
470
self.assertNotEqual(dir.transport.base, target.transport.base)
471
self.assertFalse(shared_repo.has_revision('1'))
473
def test_sprout_bzrdir_repository_revision(self):
474
# test for revision limiting, [smoke test, not corner case checks].
475
# make a repository with some revisions,
476
# and sprout it with a revision limit.
478
tree = self.make_branch_and_tree('commit_tree')
479
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
481
tree.commit('revision 1', rev_id='1')
482
tree.bzrdir.open_branch().set_revision_history([])
483
tree.set_last_revision(None)
484
tree.commit('revision 2', rev_id='2')
485
source = self.make_repository('source')
486
tree.bzrdir.open_repository().copy_content_into(source)
488
target = dir.sprout(self.get_url('target'), revision_id='2')
489
raise TestSkipped('revision limiting not strict yet')
491
def test_sprout_bzrdir_branch_and_repo(self):
492
tree = self.make_branch_and_tree('commit_tree')
493
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
495
tree.commit('revision 1')
496
source = self.make_branch('source')
497
tree.bzrdir.open_repository().copy_content_into(source.repository)
498
tree.bzrdir.open_branch().copy_content_into(source)
500
target = dir.sprout(self.get_url('target'))
501
self.assertNotEqual(dir.transport.base, target.transport.base)
502
self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
503
['./.bzr/stat-cache',
504
'./.bzr/checkout/stat-cache',
506
'./.bzr/checkout/inventory',
509
def test_sprout_bzrdir_branch_and_repo_shared(self):
510
# sprouting a branch with a repo into a shared repo uses the shared
512
tree = self.make_branch_and_tree('commit_tree')
513
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
515
tree.commit('revision 1', rev_id='1')
516
source = self.make_branch('source')
517
tree.bzrdir.open_repository().copy_content_into(source.repository)
518
tree.bzrdir.open_branch().copy_content_into(source)
521
shared_repo = self.make_repository('target', shared=True)
522
except errors.IncompatibleFormat:
524
target = dir.sprout(self.get_url('target/child'))
525
self.assertTrue(shared_repo.has_revision('1'))
527
def test_sprout_bzrdir_branch_and_repo_shared_force_new_repo(self):
528
# sprouting a branch with a repo into a shared repo uses the shared
530
tree = self.make_branch_and_tree('commit_tree')
531
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
533
tree.commit('revision 1', rev_id='1')
534
source = self.make_branch('source')
535
tree.bzrdir.open_repository().copy_content_into(source.repository)
536
tree.bzrdir.open_branch().copy_content_into(source)
539
shared_repo = self.make_repository('target', shared=True)
540
except errors.IncompatibleFormat:
542
target = dir.sprout(self.get_url('target/child'), force_new_repo=True)
543
self.assertNotEqual(dir.transport.base, target.transport.base)
544
self.assertFalse(shared_repo.has_revision('1'))
546
def test_sprout_bzrdir_branch_reference(self):
547
# sprouting should create a repository if needed and a sprouted branch.
548
referenced_branch = self.make_branch('referencced')
549
dir = self.make_bzrdir('source')
551
reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
553
except errors.IncompatibleFormat:
554
# this is ok too, not all formats have to support references.
556
self.assertRaises(errors.NoRepositoryPresent, dir.open_repository)
557
target = dir.sprout(self.get_url('target'))
558
self.assertNotEqual(dir.transport.base, target.transport.base)
559
# we want target to have a branch that is in-place.
560
self.assertEqual(target, target.open_branch().bzrdir)
561
# and as we dont support repositories being detached yet, a repo in
563
target.open_repository()
565
def test_sprout_bzrdir_branch_reference_shared(self):
566
# sprouting should create a repository if needed and a sprouted branch.
567
referenced_tree = self.make_branch_and_tree('referenced')
568
referenced_tree.commit('1', rev_id='1', allow_pointless=True)
569
dir = self.make_bzrdir('source')
571
reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
572
referenced_tree.branch)
573
except errors.IncompatibleFormat:
574
# this is ok too, not all formats have to support references.
576
self.assertRaises(errors.NoRepositoryPresent, dir.open_repository)
578
shared_repo = self.make_repository('target', shared=True)
579
except errors.IncompatibleFormat:
581
target = dir.sprout(self.get_url('target/child'))
582
self.assertNotEqual(dir.transport.base, target.transport.base)
583
# we want target to have a branch that is in-place.
584
self.assertEqual(target, target.open_branch().bzrdir)
585
# and we want no repository as the target is shared
586
self.assertRaises(errors.NoRepositoryPresent,
587
target.open_repository)
588
# and we want revision '1' in the shared repo
589
self.assertTrue(shared_repo.has_revision('1'))
591
def test_sprout_bzrdir_branch_reference_shared_force_new_repo(self):
592
# sprouting should create a repository if needed and a sprouted branch.
593
referenced_tree = self.make_branch_and_tree('referenced')
594
referenced_tree.commit('1', rev_id='1', allow_pointless=True)
595
dir = self.make_bzrdir('source')
597
reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
598
referenced_tree.branch)
599
except errors.IncompatibleFormat:
600
# this is ok too, not all formats have to support references.
602
self.assertRaises(errors.NoRepositoryPresent, dir.open_repository)
604
shared_repo = self.make_repository('target', shared=True)
605
except errors.IncompatibleFormat:
607
target = dir.sprout(self.get_url('target/child'), force_new_repo=True)
608
self.assertNotEqual(dir.transport.base, target.transport.base)
609
# we want target to have a branch that is in-place.
610
self.assertEqual(target, target.open_branch().bzrdir)
611
# and we want revision '1' in the new repo
612
self.assertTrue(target.open_repository().has_revision('1'))
613
# but not the shared one
614
self.assertFalse(shared_repo.has_revision('1'))
616
def test_sprout_bzrdir_branch_revision(self):
617
# test for revision limiting, [smoke test, not corner case checks].
618
# make a repository with some revisions,
619
# and sprout it with a revision limit.
621
tree = self.make_branch_and_tree('commit_tree')
622
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
624
tree.commit('revision 1', rev_id='1')
625
tree.commit('revision 2', rev_id='2', allow_pointless=True)
626
source = self.make_branch('source')
627
tree.bzrdir.open_repository().copy_content_into(source.repository)
628
tree.bzrdir.open_branch().copy_content_into(source)
630
target = dir.sprout(self.get_url('target'), revision_id='1')
631
self.assertEqual('1', target.open_branch().last_revision())
633
def test_sprout_bzrdir_tree_branch_repo(self):
634
tree = self.make_branch_and_tree('sourcce')
635
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
637
tree.commit('revision 1')
639
target = dir.sprout(self.get_url('target'))
640
self.assertNotEqual(dir.transport.base, target.transport.base)
641
self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
642
['./.bzr/stat-cache',
643
'./.bzr/checkout/stat-cache',
645
'./.bzr/checkout/inventory',
648
def test_sprout_bzrdir_tree_branch_reference(self):
649
# sprouting should create a repository if needed and a sprouted branch.
650
# the tree state should not be copied.
651
referenced_branch = self.make_branch('referencced')
652
dir = self.make_bzrdir('source')
654
reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
656
except errors.IncompatibleFormat:
657
# this is ok too, not all formats have to support references.
659
self.assertRaises(errors.NoRepositoryPresent, dir.open_repository)
660
tree = dir.create_workingtree()
661
tree.bzrdir.root_transport.mkdir('subdir')
663
target = dir.sprout(self.get_url('target'))
664
self.assertNotEqual(dir.transport.base, target.transport.base)
665
# we want target to have a branch that is in-place.
666
self.assertEqual(target, target.open_branch().bzrdir)
667
# and as we dont support repositories being detached yet, a repo in
669
target.open_repository()
670
result_tree = target.open_workingtree()
671
self.assertFalse(result_tree.has_filename('subdir'))
673
def test_sprout_bzrdir_tree_branch_reference_revision(self):
674
# sprouting should create a repository if needed and a sprouted branch.
675
# the tree state should not be copied but the revision changed,
676
# and the likewise the new branch should be truncated too
677
referenced_branch = self.make_branch('referencced')
678
dir = self.make_bzrdir('source')
680
reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
682
except errors.IncompatibleFormat:
683
# this is ok too, not all formats have to support references.
685
self.assertRaises(errors.NoRepositoryPresent, dir.open_repository)
686
tree = dir.create_workingtree()
687
self.build_tree(['foo'], transport=dir.root_transport)
689
tree.commit('revision 1', rev_id='1')
690
tree.commit('revision 2', rev_id='2', allow_pointless=True)
691
target = dir.sprout(self.get_url('target'), revision_id='1')
692
self.assertNotEqual(dir.transport.base, target.transport.base)
693
# we want target to have a branch that is in-place.
694
self.assertEqual(target, target.open_branch().bzrdir)
695
# and as we dont support repositories being detached yet, a repo in
697
target.open_repository()
698
# we trust that the working tree sprouting works via the other tests.
699
self.assertEqual('1', target.open_workingtree().last_revision())
700
self.assertEqual('1', target.open_branch().last_revision())
702
def test_sprout_bzrdir_tree_revision(self):
703
# test for revision limiting, [smoke test, not corner case checks].
704
# make a tree with a revision with a last-revision
705
# and sprout it with a revision limit.
706
# This smoke test just checks the revision-id is right. Tree specific
707
# tests will check corner cases.
708
tree = self.make_branch_and_tree('source')
709
self.build_tree(['foo'], transport=tree.bzrdir.root_transport)
711
tree.commit('revision 1', rev_id='1')
712
tree.commit('revision 2', rev_id='2', allow_pointless=True)
714
target = dir.sprout(self.get_url('target'), revision_id='1')
715
self.assertEqual('1', target.open_workingtree().last_revision())
717
def test_sprout_bzrdir_incomplete_source_with_basis(self):
718
# ensure that basis really does grab from the basis by having incomplete source
719
tree = self.make_branch_and_tree('commit_tree')
720
self.build_tree(['foo'], transport=tree.bzrdir.root_transport)
722
tree.commit('revision 1', rev_id='1')
723
source = self.make_branch_and_tree('source')
724
# this gives us an incomplete repository
725
tree.bzrdir.open_repository().copy_content_into(source.branch.repository)
726
tree.commit('revision 2', rev_id='2', allow_pointless=True)
727
tree.bzrdir.open_branch().copy_content_into(source.branch)
728
tree.copy_content_into(source)
729
self.assertFalse(source.branch.repository.has_revision('2'))
731
target = dir.sprout(self.get_url('target'), basis=tree.bzrdir)
732
self.assertEqual('2', target.open_branch().last_revision())
733
self.assertEqual('2', target.open_workingtree().last_revision())
734
self.assertTrue(target.open_branch().repository.has_revision('2'))
736
def test_format_initialize_find_open(self):
737
# loopback test to check the current format initializes to itself.
738
if not self.bzrdir_format.is_supported():
739
# unsupported formats are not loopback testable
740
# because the default open will not open them and
741
# they may not be initializable.
743
# supported formats must be able to init and open
744
t = get_transport(self.get_url())
745
readonly_t = get_transport(self.get_readonly_url())
746
made_control = self.bzrdir_format.initialize(t.base)
747
self.failUnless(isinstance(made_control, bzrdir.BzrDir))
748
self.assertEqual(self.bzrdir_format,
749
bzrdir.BzrDirFormat.find_format(readonly_t))
750
direct_opened_dir = self.bzrdir_format.open(readonly_t)
751
opened_dir = bzrdir.BzrDir.open(t.base)
752
self.assertEqual(made_control._format,
754
self.assertEqual(direct_opened_dir._format,
756
self.failUnless(isinstance(opened_dir, bzrdir.BzrDir))
758
def test_open_not_bzrdir(self):
759
# test the formats specific behaviour for no-content or similar dirs.
760
self.assertRaises(NotBranchError,
761
self.bzrdir_format.open,
762
get_transport(self.get_readonly_url()))
764
def test_create_branch(self):
765
# a bzrdir can construct a branch and repository for itself.
766
if not self.bzrdir_format.is_supported():
767
# unsupported formats are not loopback testable
768
# because the default open will not open them and
769
# they may not be initializable.
771
t = get_transport(self.get_url())
772
made_control = self.bzrdir_format.initialize(t.base)
773
made_repo = made_control.create_repository()
774
made_branch = made_control.create_branch()
775
self.failUnless(isinstance(made_branch, bzrlib.branch.Branch))
776
self.assertEqual(made_control, made_branch.bzrdir)
778
def test_open_branch(self):
779
if not self.bzrdir_format.is_supported():
780
# unsupported formats are not loopback testable
781
# because the default open will not open them and
782
# they may not be initializable.
784
t = get_transport(self.get_url())
785
made_control = self.bzrdir_format.initialize(t.base)
786
made_repo = made_control.create_repository()
787
made_branch = made_control.create_branch()
788
opened_branch = made_control.open_branch()
789
self.assertEqual(made_control, opened_branch.bzrdir)
790
self.failUnless(isinstance(opened_branch, made_branch.__class__))
791
self.failUnless(isinstance(opened_branch._format, made_branch._format.__class__))
793
def test_create_repository(self):
794
# a bzrdir can construct a repository for itself.
795
if not self.bzrdir_format.is_supported():
796
# unsupported formats are not loopback testable
797
# because the default open will not open them and
798
# they may not be initializable.
800
t = get_transport(self.get_url())
801
made_control = self.bzrdir_format.initialize(t.base)
802
made_repo = made_control.create_repository()
803
self.failUnless(isinstance(made_repo, repository.Repository))
804
self.assertEqual(made_control, made_repo.bzrdir)
806
def test_open_repository(self):
807
if not self.bzrdir_format.is_supported():
808
# unsupported formats are not loopback testable
809
# because the default open will not open them and
810
# they may not be initializable.
812
t = get_transport(self.get_url())
813
made_control = self.bzrdir_format.initialize(t.base)
814
made_repo = made_control.create_repository()
815
opened_repo = made_control.open_repository()
816
self.assertEqual(made_control, opened_repo.bzrdir)
817
self.failUnless(isinstance(opened_repo, made_repo.__class__))
818
self.failUnless(isinstance(opened_repo._format, made_repo._format.__class__))
820
def test_create_workingtree(self):
821
# a bzrdir can construct a working tree for itself.
822
if not self.bzrdir_format.is_supported():
823
# unsupported formats are not loopback testable
824
# because the default open will not open them and
825
# they may not be initializable.
827
# this has to be tested with local access as we still support creating
829
t = get_transport('.')
830
made_control = self.bzrdir_format.initialize(t.base)
831
made_repo = made_control.create_repository()
832
made_branch = made_control.create_branch()
833
made_tree = made_control.create_workingtree()
834
self.failUnless(isinstance(made_tree, workingtree.WorkingTree))
835
self.assertEqual(made_control, made_tree.bzrdir)
837
def test_create_workingtree_revision(self):
838
# a bzrdir can construct a working tree for itself @ a specific revision.
839
source = self.make_branch_and_tree('source')
840
source.commit('a', rev_id='a', allow_pointless=True)
841
source.commit('b', rev_id='b', allow_pointless=True)
842
self.build_tree(['new/'])
843
made_control = self.bzrdir_format.initialize('new')
844
source.branch.repository.clone(made_control)
845
source.branch.clone(made_control)
846
made_tree = made_control.create_workingtree(revision_id='a')
847
self.assertEqual('a', made_tree.last_revision())
849
def test_open_workingtree(self):
850
if not self.bzrdir_format.is_supported():
851
# unsupported formats are not loopback testable
852
# because the default open will not open them and
853
# they may not be initializable.
855
# this has to be tested with local access as we still support creating
857
t = get_transport('.')
858
made_control = self.bzrdir_format.initialize(t.base)
859
made_repo = made_control.create_repository()
860
made_branch = made_control.create_branch()
861
made_tree = made_control.create_workingtree()
862
opened_tree = made_control.open_workingtree()
863
self.assertEqual(made_control, opened_tree.bzrdir)
864
self.failUnless(isinstance(opened_tree, made_tree.__class__))
865
self.failUnless(isinstance(opened_tree._format, made_tree._format.__class__))
867
def test_get_branch_transport(self):
868
dir = self.make_bzrdir('.')
869
# without a format, get_branch_transport gives use a transport
870
# which -may- point to an existing dir.
871
self.assertTrue(isinstance(dir.get_branch_transport(None),
872
transport.Transport))
873
# with a given format, either the bzr dir supports identifiable
874
# branches, or it supports anonymous branch formats, but not both.
875
anonymous_format = bzrlib.branch.BzrBranchFormat4()
876
identifiable_format = bzrlib.branch.BzrBranchFormat5()
878
found_transport = dir.get_branch_transport(anonymous_format)
879
self.assertRaises(errors.IncompatibleFormat,
880
dir.get_branch_transport,
882
except errors.IncompatibleFormat:
883
found_transport = dir.get_branch_transport(identifiable_format)
884
self.assertTrue(isinstance(found_transport, transport.Transport))
885
# and the dir which has been initialized for us must be statable.
886
found_transport.stat('.')
888
def test_get_repository_transport(self):
889
dir = self.make_bzrdir('.')
890
# without a format, get_repository_transport gives use a transport
891
# which -may- point to an existing dir.
892
self.assertTrue(isinstance(dir.get_repository_transport(None),
893
transport.Transport))
894
# with a given format, either the bzr dir supports identifiable
895
# repositoryes, or it supports anonymous repository formats, but not both.
896
anonymous_format = repository.RepositoryFormat6()
897
identifiable_format = repository.RepositoryFormat7()
899
found_transport = dir.get_repository_transport(anonymous_format)
900
self.assertRaises(errors.IncompatibleFormat,
901
dir.get_repository_transport,
903
except errors.IncompatibleFormat:
904
found_transport = dir.get_repository_transport(identifiable_format)
905
self.assertTrue(isinstance(found_transport, transport.Transport))
906
# and the dir which has been initialized for us must be statable.
907
found_transport.stat('.')
909
def test_get_workingtree_transport(self):
910
dir = self.make_bzrdir('.')
911
# without a format, get_workingtree_transport gives use a transport
912
# which -may- point to an existing dir.
913
self.assertTrue(isinstance(dir.get_workingtree_transport(None),
914
transport.Transport))
915
# with a given format, either the bzr dir supports identifiable
916
# trees, or it supports anonymous tree formats, but not both.
917
anonymous_format = workingtree.WorkingTreeFormat2()
918
identifiable_format = workingtree.WorkingTreeFormat3()
920
found_transport = dir.get_workingtree_transport(anonymous_format)
921
self.assertRaises(errors.IncompatibleFormat,
922
dir.get_workingtree_transport,
924
except errors.IncompatibleFormat:
925
found_transport = dir.get_workingtree_transport(identifiable_format)
926
self.assertTrue(isinstance(found_transport, transport.Transport))
927
# and the dir which has been initialized for us must be statable.
928
found_transport.stat('.')
930
def test_root_transport(self):
931
dir = self.make_bzrdir('.')
932
self.assertEqual(dir.root_transport.base,
933
get_transport(self.get_url('.')).base)
935
def test_find_repository_no_repo_under_standalone_branch(self):
936
# finding a repo stops at standalone branches even if there is a
937
# higher repository available.
939
repo = self.make_repository('.', shared=True)
940
except errors.IncompatibleFormat:
941
# need a shared repository to test this.
943
url = self.get_url('intermediate')
944
get_transport(self.get_url()).mkdir('intermediate')
945
get_transport(self.get_url()).mkdir('intermediate/child')
946
made_control = self.bzrdir_format.initialize(url)
947
made_control.create_repository()
948
innermost_control = self.bzrdir_format.initialize(
949
self.get_url('intermediate/child'))
951
child_repo = innermost_control.open_repository()
952
# if there is a repository, then the format cannot ever hit this
955
except errors.NoRepositoryPresent:
957
self.assertRaises(errors.NoRepositoryPresent,
958
innermost_control.find_repository)
960
def test_find_repository_containing_shared_repository(self):
961
# find repo inside a shared repo with an empty control dir
962
# returns the shared repo.
964
repo = self.make_repository('.', shared=True)
965
except errors.IncompatibleFormat:
966
# need a shared repository to test this.
968
url = self.get_url('childbzrdir')
969
get_transport(self.get_url()).mkdir('childbzrdir')
970
made_control = self.bzrdir_format.initialize(url)
972
child_repo = made_control.open_repository()
973
# if there is a repository, then the format cannot ever hit this
976
except errors.NoRepositoryPresent:
978
found_repo = made_control.find_repository()
979
self.assertEqual(repo.bzrdir.root_transport.base,
980
found_repo.bzrdir.root_transport.base)
982
def test_find_repository_standalone_with_containing_shared_repository(self):
983
# find repo inside a standalone repo inside a shared repo finds the standalone repo
985
containing_repo = self.make_repository('.', shared=True)
986
except errors.IncompatibleFormat:
987
# need a shared repository to test this.
989
child_repo = self.make_repository('childrepo')
990
opened_control = bzrdir.BzrDir.open(self.get_url('childrepo'))
991
found_repo = opened_control.find_repository()
992
self.assertEqual(child_repo.bzrdir.root_transport.base,
993
found_repo.bzrdir.root_transport.base)
995
def test_find_repository_shared_within_shared_repository(self):
996
# find repo at a shared repo inside a shared repo finds the inner repo
998
containing_repo = self.make_repository('.', shared=True)
999
except errors.IncompatibleFormat:
1000
# need a shared repository to test this.
1002
url = self.get_url('childrepo')
1003
get_transport(self.get_url()).mkdir('childrepo')
1004
child_control = self.bzrdir_format.initialize(url)
1005
child_repo = child_control.create_repository(shared=True)
1006
opened_control = bzrdir.BzrDir.open(self.get_url('childrepo'))
1007
found_repo = opened_control.find_repository()
1008
self.assertEqual(child_repo.bzrdir.root_transport.base,
1009
found_repo.bzrdir.root_transport.base)
1010
self.assertNotEqual(child_repo.bzrdir.root_transport.base,
1011
containing_repo.bzrdir.root_transport.base)
1013
def test_find_repository_with_nested_dirs_works(self):
1014
# find repo inside a bzrdir inside a bzrdir inside a shared repo
1015
# finds the outer shared repo.
1017
repo = self.make_repository('.', shared=True)
1018
except errors.IncompatibleFormat:
1019
# need a shared repository to test this.
1021
url = self.get_url('intermediate')
1022
get_transport(self.get_url()).mkdir('intermediate')
1023
get_transport(self.get_url()).mkdir('intermediate/child')
1024
made_control = self.bzrdir_format.initialize(url)
1026
child_repo = made_control.open_repository()
1027
# if there is a repository, then the format cannot ever hit this
1030
except errors.NoRepositoryPresent:
1032
innermost_control = self.bzrdir_format.initialize(
1033
self.get_url('intermediate/child'))
1035
child_repo = innermost_control.open_repository()
1036
# if there is a repository, then the format cannot ever hit this
1039
except errors.NoRepositoryPresent:
1041
found_repo = innermost_control.find_repository()
1042
self.assertEqual(repo.bzrdir.root_transport.base,
1043
found_repo.bzrdir.root_transport.base)
1045
def test_can_and_needs_format_conversion(self):
1046
# check that we can ask an instance if its upgradable
1047
dir = self.make_bzrdir('.')
1048
if dir.can_convert_format():
1049
# if its default updatable there must be an updater
1050
# (we change the default to match the lastest known format
1051
# as downgrades may not be available
1052
old_format = bzrdir.BzrDirFormat.get_default_format()
1053
bzrdir.BzrDirFormat.set_default_format(dir._format)
1055
self.assertTrue(isinstance(dir._format.get_converter(),
1058
bzrdir.BzrDirFormat.set_default_format(old_format)
1059
dir.needs_format_conversion(None)
1061
def test_upgrade_new_instance(self):
1062
"""Does an available updater work ?."""
1063
dir = self.make_bzrdir('.')
1064
# for now, check is not ready for partial bzrdirs.
1065
dir.create_repository()
1067
dir.create_workingtree()
1068
if dir.can_convert_format():
1069
# if its default updatable there must be an updater
1070
# (we change the default to match the lastest known format
1071
# as downgrades may not be available
1072
old_format = bzrdir.BzrDirFormat.get_default_format()
1073
bzrdir.BzrDirFormat.set_default_format(dir._format)
1074
pb = ui.ui_factory.nested_progress_bar()
1076
dir._format.get_converter(None).convert(dir, pb)
1078
bzrdir.BzrDirFormat.set_default_format(old_format)
1080
# and it should pass 'check' now.
1081
check(bzrdir.BzrDir.open(self.get_url('.')).open_branch(), False)
1084
class ChrootedBzrDirTests(ChrootedTestCase):
1086
def test_find_repository_no_repository(self):
1087
# loopback test to check the current format fails to find a
1088
# share repository correctly.
1089
if not self.bzrdir_format.is_supported():
1090
# unsupported formats are not loopback testable
1091
# because the default open will not open them and
1092
# they may not be initializable.
1094
# supported formats must be able to init and open
1095
url = self.get_url('subdir')
1096
get_transport(self.get_url()).mkdir('subdir')
1097
made_control = self.bzrdir_format.initialize(url)
1099
repo = made_control.open_repository()
1100
# if there is a repository, then the format cannot ever hit this
1103
except errors.NoRepositoryPresent:
1105
opened_control = bzrdir.BzrDir.open(self.get_readonly_url('subdir'))
1106
self.assertRaises(errors.NoRepositoryPresent,
1107
opened_control.find_repository)