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)
504
def test_sprout_bzrdir_branch_and_repo_shared(self):
505
# sprouting a branch with a repo into a shared repo uses the shared
507
tree = self.make_branch_and_tree('commit_tree')
508
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
510
tree.commit('revision 1', rev_id='1')
511
source = self.make_branch('source')
512
tree.bzrdir.open_repository().copy_content_into(source.repository)
513
tree.bzrdir.open_branch().copy_content_into(source)
516
shared_repo = self.make_repository('target', shared=True)
517
except errors.IncompatibleFormat:
519
target = dir.sprout(self.get_url('target/child'))
520
self.assertTrue(shared_repo.has_revision('1'))
522
def test_sprout_bzrdir_branch_and_repo_shared_force_new_repo(self):
523
# sprouting a branch with a repo into a shared repo uses the shared
525
tree = self.make_branch_and_tree('commit_tree')
526
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
528
tree.commit('revision 1', rev_id='1')
529
source = self.make_branch('source')
530
tree.bzrdir.open_repository().copy_content_into(source.repository)
531
tree.bzrdir.open_branch().copy_content_into(source)
534
shared_repo = self.make_repository('target', shared=True)
535
except errors.IncompatibleFormat:
537
target = dir.sprout(self.get_url('target/child'), force_new_repo=True)
538
self.assertNotEqual(dir.transport.base, target.transport.base)
539
self.assertFalse(shared_repo.has_revision('1'))
541
def test_sprout_bzrdir_branch_reference(self):
542
# sprouting should create a repository if needed and a sprouted branch.
543
referenced_branch = self.make_branch('referencced')
544
dir = self.make_bzrdir('source')
546
reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
548
except errors.IncompatibleFormat:
549
# this is ok too, not all formats have to support references.
551
self.assertRaises(errors.NoRepositoryPresent, dir.open_repository)
552
target = dir.sprout(self.get_url('target'))
553
self.assertNotEqual(dir.transport.base, target.transport.base)
554
# we want target to have a branch that is in-place.
555
self.assertEqual(target, target.open_branch().bzrdir)
556
# and as we dont support repositories being detached yet, a repo in
558
target.open_repository()
560
def test_sprout_bzrdir_branch_reference_shared(self):
561
# sprouting should create a repository if needed and a sprouted branch.
562
referenced_tree = self.make_branch_and_tree('referenced')
563
referenced_tree.commit('1', rev_id='1', allow_pointless=True)
564
dir = self.make_bzrdir('source')
566
reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
567
referenced_tree.branch)
568
except errors.IncompatibleFormat:
569
# this is ok too, not all formats have to support references.
571
self.assertRaises(errors.NoRepositoryPresent, dir.open_repository)
573
shared_repo = self.make_repository('target', shared=True)
574
except errors.IncompatibleFormat:
576
target = dir.sprout(self.get_url('target/child'))
577
self.assertNotEqual(dir.transport.base, target.transport.base)
578
# we want target to have a branch that is in-place.
579
self.assertEqual(target, target.open_branch().bzrdir)
580
# and we want no repository as the target is shared
581
self.assertRaises(errors.NoRepositoryPresent,
582
target.open_repository)
583
# and we want revision '1' in the shared repo
584
self.assertTrue(shared_repo.has_revision('1'))
586
def test_sprout_bzrdir_branch_reference_shared_force_new_repo(self):
587
# sprouting should create a repository if needed and a sprouted branch.
588
referenced_tree = self.make_branch_and_tree('referenced')
589
referenced_tree.commit('1', rev_id='1', allow_pointless=True)
590
dir = self.make_bzrdir('source')
592
reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
593
referenced_tree.branch)
594
except errors.IncompatibleFormat:
595
# this is ok too, not all formats have to support references.
597
self.assertRaises(errors.NoRepositoryPresent, dir.open_repository)
599
shared_repo = self.make_repository('target', shared=True)
600
except errors.IncompatibleFormat:
602
target = dir.sprout(self.get_url('target/child'), force_new_repo=True)
603
self.assertNotEqual(dir.transport.base, target.transport.base)
604
# we want target to have a branch that is in-place.
605
self.assertEqual(target, target.open_branch().bzrdir)
606
# and we want revision '1' in the new repo
607
self.assertTrue(target.open_repository().has_revision('1'))
608
# but not the shared one
609
self.assertFalse(shared_repo.has_revision('1'))
611
def test_sprout_bzrdir_branch_revision(self):
612
# test for revision limiting, [smoke test, not corner case checks].
613
# make a repository with some revisions,
614
# and sprout it with a revision limit.
616
tree = self.make_branch_and_tree('commit_tree')
617
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
619
tree.commit('revision 1', rev_id='1')
620
tree.commit('revision 2', rev_id='2', allow_pointless=True)
621
source = self.make_branch('source')
622
tree.bzrdir.open_repository().copy_content_into(source.repository)
623
tree.bzrdir.open_branch().copy_content_into(source)
625
target = dir.sprout(self.get_url('target'), revision_id='1')
626
self.assertEqual('1', target.open_branch().last_revision())
628
def test_sprout_bzrdir_tree_branch_repo(self):
629
tree = self.make_branch_and_tree('sourcce')
630
self.build_tree(['foo'], transport=tree.bzrdir.transport.clone('..'))
632
tree.commit('revision 1')
634
target = dir.sprout(self.get_url('target'))
635
self.assertNotEqual(dir.transport.base, target.transport.base)
636
self.assertDirectoriesEqual(dir.root_transport, target.root_transport,
637
['./.bzr/stat-cache', './.bzr/checkout/stat-cache'])
639
def test_sprout_bzrdir_tree_branch_reference(self):
640
# sprouting should create a repository if needed and a sprouted branch.
641
# the tree state should be copied.
642
referenced_branch = self.make_branch('referencced')
643
dir = self.make_bzrdir('source')
645
reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
647
except errors.IncompatibleFormat:
648
# this is ok too, not all formats have to support references.
650
self.assertRaises(errors.NoRepositoryPresent, dir.open_repository)
651
dir.create_workingtree()
652
target = dir.sprout(self.get_url('target'))
653
self.assertNotEqual(dir.transport.base, target.transport.base)
654
# we want target to have a branch that is in-place.
655
self.assertEqual(target, target.open_branch().bzrdir)
656
# and as we dont support repositories being detached yet, a repo in
658
target.open_repository()
659
# we trust that the working tree sprouting works via the other tests.
660
target.open_workingtree()
662
def test_sprout_bzrdir_tree_branch_reference_revision(self):
663
# sprouting should create a repository if needed and a sprouted branch.
664
# the tree state should be copied but the revision changed,
665
# and the likewise the new branch should be truncated too
666
referenced_branch = self.make_branch('referencced')
667
dir = self.make_bzrdir('source')
669
reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
671
except errors.IncompatibleFormat:
672
# this is ok too, not all formats have to support references.
674
self.assertRaises(errors.NoRepositoryPresent, dir.open_repository)
675
tree = dir.create_workingtree()
676
self.build_tree(['foo'], transport=dir.root_transport)
678
tree.commit('revision 1', rev_id='1')
679
tree.commit('revision 2', rev_id='2', allow_pointless=True)
680
target = dir.sprout(self.get_url('target'), revision_id='1')
681
self.assertNotEqual(dir.transport.base, target.transport.base)
682
# we want target to have a branch that is in-place.
683
self.assertEqual(target, target.open_branch().bzrdir)
684
# and as we dont support repositories being detached yet, a repo in
686
target.open_repository()
687
# we trust that the working tree sprouting works via the other tests.
688
self.assertEqual('1', target.open_workingtree().last_revision())
689
self.assertEqual('1', target.open_branch().last_revision())
691
def test_sprout_bzrdir_tree_revision(self):
692
# test for revision limiting, [smoke test, not corner case checks].
693
# make a tree with a revision with a last-revision
694
# and sprout it with a revision limit.
695
# This smoke test just checks the revision-id is right. Tree specific
696
# tests will check corner cases.
697
tree = self.make_branch_and_tree('source')
698
self.build_tree(['foo'], transport=tree.bzrdir.root_transport)
700
tree.commit('revision 1', rev_id='1')
701
tree.commit('revision 2', rev_id='2', allow_pointless=True)
703
target = dir.sprout(self.get_url('target'), revision_id='1')
704
self.assertEqual('1', target.open_workingtree().last_revision())
706
def test_sprout_bzrdir_incomplete_source_with_basis(self):
707
# ensure that basis really does grab from the basis by having incomplete source
708
tree = self.make_branch_and_tree('commit_tree')
709
self.build_tree(['foo'], transport=tree.bzrdir.root_transport)
711
tree.commit('revision 1', rev_id='1')
712
source = self.make_branch_and_tree('source')
713
# this gives us an incomplete repository
714
tree.bzrdir.open_repository().copy_content_into(source.branch.repository)
715
tree.commit('revision 2', rev_id='2', allow_pointless=True)
716
tree.bzrdir.open_branch().copy_content_into(source.branch)
717
tree.copy_content_into(source)
718
self.assertFalse(source.branch.repository.has_revision('2'))
720
target = dir.sprout(self.get_url('target'), basis=tree.bzrdir)
721
self.assertEqual('2', target.open_branch().last_revision())
722
self.assertEqual('2', target.open_workingtree().last_revision())
723
self.assertTrue(target.open_branch().repository.has_revision('2'))
725
def test_format_initialize_find_open(self):
726
# loopback test to check the current format initializes to itself.
727
if not self.bzrdir_format.is_supported():
728
# unsupported formats are not loopback testable
729
# because the default open will not open them and
730
# they may not be initializable.
732
# supported formats must be able to init and open
733
t = get_transport(self.get_url())
734
readonly_t = get_transport(self.get_readonly_url())
735
made_control = self.bzrdir_format.initialize(t.base)
736
self.failUnless(isinstance(made_control, bzrdir.BzrDir))
737
self.assertEqual(self.bzrdir_format,
738
bzrdir.BzrDirFormat.find_format(readonly_t))
739
direct_opened_dir = self.bzrdir_format.open(readonly_t)
740
opened_dir = bzrdir.BzrDir.open(t.base)
741
self.assertEqual(made_control._format,
743
self.assertEqual(direct_opened_dir._format,
745
self.failUnless(isinstance(opened_dir, bzrdir.BzrDir))
747
def test_open_not_bzrdir(self):
748
# test the formats specific behaviour for no-content or similar dirs.
749
self.assertRaises(NotBranchError,
750
self.bzrdir_format.open,
751
get_transport(self.get_readonly_url()))
753
def test_create_branch(self):
754
# a bzrdir can construct a branch and repository for itself.
755
if not self.bzrdir_format.is_supported():
756
# unsupported formats are not loopback testable
757
# because the default open will not open them and
758
# they may not be initializable.
760
t = get_transport(self.get_url())
761
made_control = self.bzrdir_format.initialize(t.base)
762
made_repo = made_control.create_repository()
763
made_branch = made_control.create_branch()
764
self.failUnless(isinstance(made_branch, bzrlib.branch.Branch))
765
self.assertEqual(made_control, made_branch.bzrdir)
767
def test_open_branch(self):
768
if not self.bzrdir_format.is_supported():
769
# unsupported formats are not loopback testable
770
# because the default open will not open them and
771
# they may not be initializable.
773
t = get_transport(self.get_url())
774
made_control = self.bzrdir_format.initialize(t.base)
775
made_repo = made_control.create_repository()
776
made_branch = made_control.create_branch()
777
opened_branch = made_control.open_branch()
778
self.assertEqual(made_control, opened_branch.bzrdir)
779
self.failUnless(isinstance(opened_branch, made_branch.__class__))
780
self.failUnless(isinstance(opened_branch._format, made_branch._format.__class__))
782
def test_create_repository(self):
783
# a bzrdir can construct a repository for itself.
784
if not self.bzrdir_format.is_supported():
785
# unsupported formats are not loopback testable
786
# because the default open will not open them and
787
# they may not be initializable.
789
t = get_transport(self.get_url())
790
made_control = self.bzrdir_format.initialize(t.base)
791
made_repo = made_control.create_repository()
792
self.failUnless(isinstance(made_repo, repository.Repository))
793
self.assertEqual(made_control, made_repo.bzrdir)
795
def test_open_repository(self):
796
if not self.bzrdir_format.is_supported():
797
# unsupported formats are not loopback testable
798
# because the default open will not open them and
799
# they may not be initializable.
801
t = get_transport(self.get_url())
802
made_control = self.bzrdir_format.initialize(t.base)
803
made_repo = made_control.create_repository()
804
opened_repo = made_control.open_repository()
805
self.assertEqual(made_control, opened_repo.bzrdir)
806
self.failUnless(isinstance(opened_repo, made_repo.__class__))
807
self.failUnless(isinstance(opened_repo._format, made_repo._format.__class__))
809
def test_create_workingtree(self):
810
# a bzrdir can construct a working tree for itself.
811
if not self.bzrdir_format.is_supported():
812
# unsupported formats are not loopback testable
813
# because the default open will not open them and
814
# they may not be initializable.
816
# this has to be tested with local access as we still support creating
818
t = get_transport('.')
819
made_control = self.bzrdir_format.initialize(t.base)
820
made_repo = made_control.create_repository()
821
made_branch = made_control.create_branch()
822
made_tree = made_control.create_workingtree()
823
self.failUnless(isinstance(made_tree, workingtree.WorkingTree))
824
self.assertEqual(made_control, made_tree.bzrdir)
826
def test_create_workingtree_revision(self):
827
# a bzrdir can construct a working tree for itself @ a specific revision.
828
source = self.make_branch_and_tree('source')
829
source.commit('a', rev_id='a', allow_pointless=True)
830
source.commit('b', rev_id='b', allow_pointless=True)
831
self.build_tree(['new/'])
832
made_control = self.bzrdir_format.initialize('new')
833
source.branch.repository.clone(made_control)
834
source.branch.clone(made_control)
835
made_tree = made_control.create_workingtree(revision_id='a')
836
self.assertEqual('a', made_tree.last_revision())
838
def test_open_workingtree(self):
839
if not self.bzrdir_format.is_supported():
840
# unsupported formats are not loopback testable
841
# because the default open will not open them and
842
# they may not be initializable.
844
# this has to be tested with local access as we still support creating
846
t = get_transport('.')
847
made_control = self.bzrdir_format.initialize(t.base)
848
made_repo = made_control.create_repository()
849
made_branch = made_control.create_branch()
850
made_tree = made_control.create_workingtree()
851
opened_tree = made_control.open_workingtree()
852
self.assertEqual(made_control, opened_tree.bzrdir)
853
self.failUnless(isinstance(opened_tree, made_tree.__class__))
854
self.failUnless(isinstance(opened_tree._format, made_tree._format.__class__))
856
def test_get_branch_transport(self):
857
dir = self.make_bzrdir('.')
858
# without a format, get_branch_transport gives use a transport
859
# which -may- point to an existing dir.
860
self.assertTrue(isinstance(dir.get_branch_transport(None),
861
transport.Transport))
862
# with a given format, either the bzr dir supports identifiable
863
# branches, or it supports anonymous branch formats, but not both.
864
anonymous_format = bzrlib.branch.BzrBranchFormat4()
865
identifiable_format = bzrlib.branch.BzrBranchFormat5()
867
found_transport = dir.get_branch_transport(anonymous_format)
868
self.assertRaises(errors.IncompatibleFormat,
869
dir.get_branch_transport,
871
except errors.IncompatibleFormat:
872
found_transport = dir.get_branch_transport(identifiable_format)
873
self.assertTrue(isinstance(found_transport, transport.Transport))
874
# and the dir which has been initialized for us must be statable.
875
found_transport.stat('.')
877
def test_get_repository_transport(self):
878
dir = self.make_bzrdir('.')
879
# without a format, get_repository_transport gives use a transport
880
# which -may- point to an existing dir.
881
self.assertTrue(isinstance(dir.get_repository_transport(None),
882
transport.Transport))
883
# with a given format, either the bzr dir supports identifiable
884
# repositoryes, or it supports anonymous repository formats, but not both.
885
anonymous_format = repository.RepositoryFormat6()
886
identifiable_format = repository.RepositoryFormat7()
888
found_transport = dir.get_repository_transport(anonymous_format)
889
self.assertRaises(errors.IncompatibleFormat,
890
dir.get_repository_transport,
892
except errors.IncompatibleFormat:
893
found_transport = dir.get_repository_transport(identifiable_format)
894
self.assertTrue(isinstance(found_transport, transport.Transport))
895
# and the dir which has been initialized for us must be statable.
896
found_transport.stat('.')
898
def test_get_workingtree_transport(self):
899
dir = self.make_bzrdir('.')
900
# without a format, get_workingtree_transport gives use a transport
901
# which -may- point to an existing dir.
902
self.assertTrue(isinstance(dir.get_workingtree_transport(None),
903
transport.Transport))
904
# with a given format, either the bzr dir supports identifiable
905
# trees, or it supports anonymous tree formats, but not both.
906
anonymous_format = workingtree.WorkingTreeFormat2()
907
identifiable_format = workingtree.WorkingTreeFormat3()
909
found_transport = dir.get_workingtree_transport(anonymous_format)
910
self.assertRaises(errors.IncompatibleFormat,
911
dir.get_workingtree_transport,
913
except errors.IncompatibleFormat:
914
found_transport = dir.get_workingtree_transport(identifiable_format)
915
self.assertTrue(isinstance(found_transport, transport.Transport))
916
# and the dir which has been initialized for us must be statable.
917
found_transport.stat('.')
919
def test_root_transport(self):
920
dir = self.make_bzrdir('.')
921
self.assertEqual(dir.root_transport.base,
922
get_transport(self.get_url('.')).base)
924
def test_find_repository_no_repo_under_standalone_branch(self):
925
# finding a repo stops at standalone branches even if there is a
926
# higher repository available.
928
repo = self.make_repository('.', shared=True)
929
except errors.IncompatibleFormat:
930
# need a shared repository to test this.
932
url = self.get_url('intermediate')
933
get_transport(self.get_url()).mkdir('intermediate')
934
get_transport(self.get_url()).mkdir('intermediate/child')
935
made_control = self.bzrdir_format.initialize(url)
936
made_control.create_repository()
937
innermost_control = self.bzrdir_format.initialize(
938
self.get_url('intermediate/child'))
940
child_repo = innermost_control.open_repository()
941
# if there is a repository, then the format cannot ever hit this
944
except errors.NoRepositoryPresent:
946
self.assertRaises(errors.NoRepositoryPresent,
947
innermost_control.find_repository)
949
def test_find_repository_containing_shared_repository(self):
950
# find repo inside a shared repo with an empty control dir
951
# returns the shared repo.
953
repo = self.make_repository('.', shared=True)
954
except errors.IncompatibleFormat:
955
# need a shared repository to test this.
957
url = self.get_url('childbzrdir')
958
get_transport(self.get_url()).mkdir('childbzrdir')
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
found_repo = made_control.find_repository()
968
self.assertEqual(repo.bzrdir.root_transport.base,
969
found_repo.bzrdir.root_transport.base)
971
def test_find_repository_standalone_with_containing_shared_repository(self):
972
# find repo inside a standalone repo inside a shared repo finds the standalone repo
974
containing_repo = self.make_repository('.', shared=True)
975
except errors.IncompatibleFormat:
976
# need a shared repository to test this.
978
child_repo = self.make_repository('childrepo')
979
opened_control = bzrdir.BzrDir.open(self.get_url('childrepo'))
980
found_repo = opened_control.find_repository()
981
self.assertEqual(child_repo.bzrdir.root_transport.base,
982
found_repo.bzrdir.root_transport.base)
984
def test_find_repository_shared_within_shared_repository(self):
985
# find repo at a shared repo inside a shared repo finds the inner repo
987
containing_repo = self.make_repository('.', shared=True)
988
except errors.IncompatibleFormat:
989
# need a shared repository to test this.
991
url = self.get_url('childrepo')
992
get_transport(self.get_url()).mkdir('childrepo')
993
child_control = self.bzrdir_format.initialize(url)
994
child_repo = child_control.create_repository(shared=True)
995
opened_control = bzrdir.BzrDir.open(self.get_url('childrepo'))
996
found_repo = opened_control.find_repository()
997
self.assertEqual(child_repo.bzrdir.root_transport.base,
998
found_repo.bzrdir.root_transport.base)
999
self.assertNotEqual(child_repo.bzrdir.root_transport.base,
1000
containing_repo.bzrdir.root_transport.base)
1002
def test_find_repository_with_nested_dirs_works(self):
1003
# find repo inside a bzrdir inside a bzrdir inside a shared repo
1004
# finds the outer shared repo.
1006
repo = self.make_repository('.', shared=True)
1007
except errors.IncompatibleFormat:
1008
# need a shared repository to test this.
1010
url = self.get_url('intermediate')
1011
get_transport(self.get_url()).mkdir('intermediate')
1012
get_transport(self.get_url()).mkdir('intermediate/child')
1013
made_control = self.bzrdir_format.initialize(url)
1015
child_repo = made_control.open_repository()
1016
# if there is a repository, then the format cannot ever hit this
1019
except errors.NoRepositoryPresent:
1021
innermost_control = self.bzrdir_format.initialize(
1022
self.get_url('intermediate/child'))
1024
child_repo = innermost_control.open_repository()
1025
# if there is a repository, then the format cannot ever hit this
1028
except errors.NoRepositoryPresent:
1030
found_repo = innermost_control.find_repository()
1031
self.assertEqual(repo.bzrdir.root_transport.base,
1032
found_repo.bzrdir.root_transport.base)
1034
def test_can_and_needs_format_conversion(self):
1035
# check that we can ask an instance if its upgradable
1036
dir = self.make_bzrdir('.')
1037
if dir.can_convert_format():
1038
# if its updatable there must be an updater
1039
self.assertTrue(isinstance(dir._format.get_converter(),
1041
dir.needs_format_conversion(None)
1043
def test_upgrade_new_instance(self):
1044
"""Does an available updater work ?."""
1045
dir = self.make_bzrdir('.')
1046
if dir.can_convert_format():
1047
dir._format.get_converter(None).convert(dir, ui.ui_factory.progress_bar())
1048
# and it should pass 'check' now.
1049
check(bzrdir.BzrDir.open(self.get_url('.')).open_branch(), False)
1052
class ChrootedBzrDirTests(ChrootedTestCase):
1054
def test_find_repository_no_repository(self):
1055
# loopback test to check the current format fails to find a
1056
# share repository correctly.
1057
if not self.bzrdir_format.is_supported():
1058
# unsupported formats are not loopback testable
1059
# because the default open will not open them and
1060
# they may not be initializable.
1062
# supported formats must be able to init and open
1063
url = self.get_url('subdir')
1064
get_transport(self.get_url()).mkdir('subdir')
1065
made_control = self.bzrdir_format.initialize(url)
1067
repo = made_control.open_repository()
1068
# if there is a repository, then the format cannot ever hit this
1071
except errors.NoRepositoryPresent:
1073
opened_control = bzrdir.BzrDir.open(self.get_readonly_url('subdir'))
1074
self.assertRaises(errors.NoRepositoryPresent,
1075
opened_control.find_repository)