19
19
from cStringIO import StringIO
23
22
from bzrlib import (
23
branch as _mod_branch,
34
revision as _mod_revision,
34
from bzrlib.branch import BzrBranchFormat6
35
from bzrlib.delta import TreeDelta
36
from bzrlib.inventory import CommonInventory, Inventory, InventoryDirectory
37
from bzrlib.repofmt.pack_repo import (
38
RepositoryFormatKnitPack5RichRootBroken,
40
from bzrlib.repofmt.weaverepo import (
45
from bzrlib.revision import NULL_REVISION, Revision
42
from bzrlib.repofmt import (
46
46
from bzrlib.smart import server
47
from bzrlib.tests import (
49
TestCaseWithTransport,
53
from bzrlib.tests.per_repository import TestCaseWithRepository
54
from bzrlib.transport import get_transport
47
from bzrlib.tests import per_repository
55
48
from bzrlib.transport.fakevfat import FakeVFATServer
56
from bzrlib.upgrade import upgrade
57
from bzrlib.workingtree import WorkingTree
60
class TestRepositoryMakeBranchAndTree(TestCaseWithRepository):
51
class TestRepositoryMakeBranchAndTree(per_repository.TestCaseWithRepository):
62
53
def test_repository_format(self):
63
54
# make sure the repository on tree.branch is of the desired format,
69
60
self.repository_format.__class__)
72
class TestRepository(TestCaseWithRepository):
63
class TestRepository(per_repository.TestCaseWithRepository):
74
65
def assertFormatAttribute(self, attribute, allowed_values):
75
66
"""Assert that the format has an attribute 'attribute'."""
99
90
"""Test the existence of the inventories attribute."""
100
91
tree = self.make_branch_and_tree('tree')
101
92
repo = tree.branch.repository
102
self.assertIsInstance(repo.inventories,
103
bzrlib.versionedfile.VersionedFiles)
93
self.assertIsInstance(repo.inventories, versionedfile.VersionedFiles)
105
95
def test_attribute_inventories_basics(self):
106
96
"""Test basic aspects of the inventories attribute."""
116
106
tree = self.make_branch_and_tree('tree')
117
107
repo = tree.branch.repository
118
108
self.assertIsInstance(repo.revisions,
119
bzrlib.versionedfile.VersionedFiles)
109
versionedfile.VersionedFiles)
121
111
def test_attribute_revision_store_basics(self):
122
112
"""Test the basic behaviour of the revisions attribute."""
150
140
tree = self.make_branch_and_tree('tree')
151
141
repo = tree.branch.repository
152
142
self.assertIsInstance(repo.signatures,
153
bzrlib.versionedfile.VersionedFiles)
143
versionedfile.VersionedFiles)
155
145
def test_attribute_text_store_basics(self):
156
146
"""Test the basic behaviour of the text store."""
167
157
rev_key = (tree.commit("foo"),)
168
158
except errors.IllegalPath:
169
raise TestNotApplicable('file_id %r cannot be stored on this'
159
raise tests.TestNotApplicable(
160
'file_id %r cannot be stored on this'
170
161
' platform for this repo format' % (file_id,))
171
162
if repo._format.rich_root_data:
172
163
root_commit = (tree.get_root_id(),) + rev_key
212
203
tree = self.make_branch_and_tree('tree')
213
204
repo = tree.branch.repository
214
205
self.assertIsInstance(repo.texts,
215
bzrlib.versionedfile.VersionedFiles)
206
versionedfile.VersionedFiles)
217
208
def test_exposed_versioned_files_are_marked_dirty(self):
218
209
repo = self.make_repository('.')
261
252
invs = tree.branch.repository.iter_inventories(revs)
262
253
for rev_id, inv in zip(revs, invs):
263
254
self.assertEqual(rev_id, inv.revision_id)
264
self.assertIsInstance(inv, CommonInventory)
255
self.assertIsInstance(inv, inventory.CommonInventory)
266
257
def test_supports_rich_root(self):
267
258
tree = self.make_branch_and_tree('a')
286
277
# they may not be initializable.
288
279
# supported formats must be able to init and open
289
t = get_transport(self.get_url())
290
readonly_t = get_transport(self.get_readonly_url())
280
t = transport.get_transport(self.get_url())
281
readonly_t = transport.get_transport(self.get_readonly_url())
291
282
made_control = self.bzrdir_format.initialize(t.base)
292
283
made_repo = self.repository_format.initialize(made_control)
293
284
self.assertEqual(made_control, made_repo.bzrdir)
346
337
# because the default open will not open them and
347
338
# they may not be initializable.
349
t = get_transport(self.get_url())
340
t = transport.get_transport(self.get_url())
350
341
made_control = self.bzrdir_format.initialize(t.base)
351
342
made_repo = made_control.create_repository()
352
343
# Check that we have a repository object.
360
351
# because the default open will not open them and
361
352
# they may not be initializable.
363
t = get_transport(self.get_url())
354
t = transport.get_transport(self.get_url())
364
355
made_control = self.bzrdir_format.initialize(t.base)
366
357
made_repo = made_control.create_repository(shared=True)
383
374
self.assertEqual('revision-1', tree.inventory.root.revision)
384
expected = InventoryDirectory('fixed-root', '', None)
375
expected = inventory.InventoryDirectory('fixed-root', '', None)
385
376
expected.revision = 'revision-1'
386
377
self.assertEqual([('', 'V', 'directory', 'fixed-root', expected)],
387
378
list(tree.list_files(include_root=True)))
412
403
tree_a.commit('rev2', rev_id='rev2')
414
405
delta = tree_a.branch.repository.get_revision_delta('rev1')
415
self.assertIsInstance(delta, TreeDelta)
406
self.assertIsInstance(delta, _mod_delta.TreeDelta)
416
407
self.assertEqual([('foo', 'file1', 'file')], delta.added)
417
408
delta = tree_a.branch.repository.get_revision_delta('rev2')
418
self.assertIsInstance(delta, TreeDelta)
409
self.assertIsInstance(delta, _mod_delta.TreeDelta)
419
410
self.assertEqual([('vla', 'file2', 'file')], delta.added)
421
412
def test_get_revision_delta_filtered(self):
431
422
# Test multiple files
432
423
delta = tree_a.branch.repository.get_revision_delta('rev1',
433
424
specific_fileids=['foo-id', 'baz-id'])
434
self.assertIsInstance(delta, TreeDelta)
425
self.assertIsInstance(delta, _mod_delta.TreeDelta)
435
426
self.assertEqual([
436
427
('baz', 'baz-id', 'file'),
437
428
('foo', 'foo-id', 'file'),
439
430
# Test a directory
440
431
delta = tree_a.branch.repository.get_revision_delta('rev1',
441
432
specific_fileids=['bar-id'])
442
self.assertIsInstance(delta, TreeDelta)
433
self.assertIsInstance(delta, _mod_delta.TreeDelta)
443
434
self.assertEqual([
444
435
('bar', 'bar-id', 'directory'),
445
436
('bar/b1', 'b1-id', 'file'),
448
439
# Test a file in a directory
449
440
delta = tree_a.branch.repository.get_revision_delta('rev1',
450
441
specific_fileids=['b2-id'])
451
self.assertIsInstance(delta, TreeDelta)
442
self.assertIsInstance(delta, _mod_delta.TreeDelta)
452
443
self.assertEqual([
453
444
('bar', 'bar-id', 'directory'),
454
445
('bar/b2', 'b2-id', 'file'),
456
447
# Try another revision
457
448
delta = tree_a.branch.repository.get_revision_delta('rev2',
458
449
specific_fileids=['b3-id'])
459
self.assertIsInstance(delta, TreeDelta)
450
self.assertIsInstance(delta, _mod_delta.TreeDelta)
460
451
self.assertEqual([
461
452
('bar', 'bar-id', 'directory'),
462
453
('bar/b3', 'b3-id', 'file'),
464
455
delta = tree_a.branch.repository.get_revision_delta('rev2',
465
456
specific_fileids=['foo-id'])
466
self.assertIsInstance(delta, TreeDelta)
457
self.assertIsInstance(delta, _mod_delta.TreeDelta)
467
458
self.assertEqual([], delta.added)
469
460
def test_clone_bzrdir_repository_revision(self):
470
461
# make a repository with some revisions,
471
462
# and clone it, this should not have unreferenced revisions.
472
463
# also: test cloning with a revision id of NULL_REVISION -> empty repo.
473
raise TestSkipped('revision limiting is not implemented yet.')
464
raise tests.TestSkipped('revision limiting is not implemented yet.')
475
466
def test_clone_repository_basis_revision(self):
476
raise TestSkipped('the use of a basis should not add noise data to the result.')
467
raise tests.TestSkipped(
468
'the use of a basis should not add noise data to the result.')
478
470
def test_clone_shared_no_tree(self):
479
471
# cloning a shared repository keeps it shared
514
506
# This gives metadir branches something they can convert to.
515
507
# it would be nice to have a 'latest' vs 'default' concept.
516
508
format = bzrdir.format_registry.make_bzrdir('dirstate-with-subtree')
517
upgrade(repo.bzrdir.root_transport.base, format=format)
509
upgrade.upgrade(repo.bzrdir.root_transport.base, format=format)
518
510
except errors.UpToDateFormat:
519
511
# this is in the most current format already.
521
513
except errors.BadConversionTarget, e:
522
raise TestSkipped(str(e))
523
wt = WorkingTree.open(wt.basedir)
514
raise tests.TestSkipped(str(e))
515
wt = workingtree.WorkingTree.open(wt.basedir)
524
516
new_signature = wt.branch.repository.get_signature_text('A')
525
517
self.assertEqual(old_signature, new_signature)
608
600
return # local conversion to/from RemoteObjects is irrelevant.
609
601
if self.repository_format.get_format_description() \
610
602
== "Repository format 4":
611
raise TestSkipped('Cannot convert format-4 to itself')
603
raise tests.TestSkipped('Cannot convert format-4 to itself')
612
604
self.build_tree_contents(_upgrade_dir_template)
613
old_repodir = bzrlib.bzrdir.BzrDir.open_unsupported('.')
605
old_repodir = bzrdir.BzrDir.open_unsupported('.')
614
606
old_repo_format = old_repodir.open_repository()._format
615
607
format = self.repository_format._matchingbzrdir
617
609
format.repository_format = self.repository_format
618
610
except AttributeError:
612
upgrade.upgrade('.', format)
622
614
def test_pointless_commit(self):
623
615
tree = self.make_branch_and_tree('.')
735
727
tree.commit('initial commit', rev_id='rev1')
736
728
tree.commit('next commit', rev_id='rev2')
737
729
graph = tree.branch.repository.get_graph()
738
parents = graph.get_parent_map([NULL_REVISION, 'rev1', 'rev2'])
730
parents = graph.get_parent_map(
731
[_mod_revision.NULL_REVISION, 'rev1', 'rev2'])
739
732
for value in parents.values():
740
733
self.assertIsInstance(value, tuple)
763
756
self.addCleanup(repo.unlock)
764
757
repo.start_write_group()
765
758
self.addCleanup(repo.abort_write_group)
766
inv = Inventory(revision_id='A')
759
inv = inventory.Inventory(revision_id='A')
767
760
inv.root.revision = 'A'
768
761
repo.add_inventory('A', inv, [])
769
repo.add_revision('A', Revision('A', committer='A', timestamp=0,
770
inventory_sha1='', timezone=0, message='A'))
762
repo.add_revision('A', _mod_revision.Revision(
763
'A', committer='A', timestamp=0,
764
inventory_sha1='', timezone=0, message='A'))
771
765
repo.add_signature_text('A', 'This might be a signature')
772
766
self.assertEqual('This might be a signature',
773
767
repo.get_signature_text('A'))
775
769
def test_add_revision_inventory_sha1(self):
776
inv = Inventory(revision_id='A')
770
inv = inventory.Inventory(revision_id='A')
777
771
inv.root.revision = 'A'
778
772
inv.root.file_id = 'fixed-root'
779
773
# Insert the inventory on its own to an identical repository, to get
791
785
repo.start_write_group()
792
786
root_id = inv.root.file_id
793
787
repo.texts.add_lines(('fixed-root', 'A'), [], [])
794
repo.add_revision('A', Revision('A', committer='B', timestamp=0,
795
timezone=0, message='C'), inv=inv)
788
repo.add_revision('A', _mod_revision.Revision(
789
'A', committer='B', timestamp=0,
790
timezone=0, message='C'), inv=inv)
796
791
repo.commit_write_group()
827
822
repo = self.make_repository(path, shared=shared)
828
823
smart_server = server.SmartTCPServer_for_testing()
829
824
self.start_server(smart_server, self.get_server())
830
remote_transport = get_transport(smart_server.get_url()).clone(path)
825
remote_transport = transport.get_transport(
826
smart_server.get_url()).clone(path)
831
827
remote_bzrdir = bzrdir.BzrDir.open_from_transport(remote_transport)
832
828
remote_repo = remote_bzrdir.open_repository()
833
829
return remote_repo
835
831
def test_sprout_from_hpss_preserves_format(self):
836
832
"""repo.sprout from a smart server preserves the repository format."""
837
if self.repository_format == RepositoryFormat7():
838
raise TestNotApplicable(
833
if self.repository_format == weaverepo.RepositoryFormat7():
834
raise tests.TestNotApplicable(
839
835
"Cannot fetch weaves over smart protocol.")
840
836
remote_repo = self.make_remote_repository('remote')
841
837
local_bzrdir = self.make_bzrdir('local')
843
839
local_repo = remote_repo.sprout(local_bzrdir)
844
840
except errors.TransportNotPossible:
845
raise TestNotApplicable(
841
raise tests.TestNotApplicable(
846
842
"Cannot lock_read old formats like AllInOne over HPSS.")
847
843
remote_backing_repo = bzrdir.BzrDir.open(
848
844
self.get_vfs_only_url('remote')).open_repository()
851
847
def test_sprout_branch_from_hpss_preserves_repo_format(self):
852
848
"""branch.sprout from a smart server preserves the repository format.
854
weave_formats = [RepositoryFormat5(), RepositoryFormat6(),
850
weave_formats = [weaverepo.RepositoryFormat5(),
851
weaverepo.RepositoryFormat6(),
852
weaverepo.RepositoryFormat7()]
856
853
if self.repository_format in weave_formats:
857
raise TestNotApplicable(
854
raise tests.TestNotApplicable(
858
855
"Cannot fetch weaves over smart protocol.")
859
856
remote_repo = self.make_remote_repository('remote')
860
857
remote_branch = remote_repo.bzrdir.create_branch()
862
859
local_bzrdir = remote_branch.bzrdir.sprout('local')
863
860
except errors.TransportNotPossible:
864
raise TestNotApplicable(
861
raise tests.TestNotApplicable(
865
862
"Cannot lock_read old formats like AllInOne over HPSS.")
866
863
local_repo = local_bzrdir.open_repository()
867
864
remote_backing_repo = bzrdir.BzrDir.open(
872
869
"""branch.sprout from a smart server preserves the repository format of
873
870
a branch from a shared repository.
875
weave_formats = [RepositoryFormat5(), RepositoryFormat6(),
872
weave_formats = [weaverepo.RepositoryFormat5(),
873
weaverepo.RepositoryFormat6(),
874
weaverepo.RepositoryFormat7()]
877
875
if self.repository_format in weave_formats:
878
raise TestNotApplicable(
876
raise tests.TestNotApplicable(
879
877
"Cannot fetch weaves over smart protocol.")
880
878
# Make a shared repo
881
879
remote_repo = self.make_remote_repository('remote', shared=True)
895
893
local_bzrdir = remote_branch.bzrdir.sprout('local')
896
894
except errors.TransportNotPossible:
897
raise TestNotApplicable(
895
raise tests.TestNotApplicable(
898
896
"Cannot lock_read old formats like AllInOne over HPSS.")
899
897
local_repo = local_bzrdir.open_repository()
900
898
self.assertEqual(remote_backing_repo._format, local_repo._format)
902
900
def test_clone_to_hpss(self):
903
pre_metadir_formats = [RepositoryFormat5(), RepositoryFormat6()]
901
pre_metadir_formats = [weaverepo.RepositoryFormat5(),
902
weaverepo.RepositoryFormat6()]
904
903
if self.repository_format in pre_metadir_formats:
905
raise TestNotApplicable(
904
raise tests.TestNotApplicable(
906
905
"Cannot lock pre_metadir_formats remotely.")
907
906
remote_transport = self.make_smart_server('remote')
908
907
local_branch = self.make_branch('local')
920
919
repo = self.make_repository('repo', shared=True)
921
920
except errors.IncompatibleFormat:
922
raise TestNotApplicable('Cannot make a shared repository')
921
raise tests.TestNotApplicable('Cannot make a shared repository')
923
922
if isinstance(repo.bzrdir, bzrdir.BzrDirPreSplitOut):
924
raise KnownFailure("pre metadir branches do not upgrade on push "
923
raise tests.KnownFailure(
924
"pre metadir branches do not upgrade on push "
925
925
"with stacking policy")
926
if isinstance(repo._format, RepositoryFormatKnitPack5RichRootBroken):
927
raise TestNotApplicable("unsupported format")
926
if isinstance(repo._format,
927
pack_repo.RepositoryFormatKnitPack5RichRootBroken):
928
raise tests.TestNotApplicable("unsupported format")
928
929
# Make a source branch in 'repo' in an unstackable branch format
929
930
bzrdir_format = self.repository_format._matchingbzrdir
930
931
transport = self.get_transport('repo/branch')
931
932
transport.mkdir('.')
932
933
target_bzrdir = bzrdir_format.initialize_on_transport(transport)
933
branch = BzrBranchFormat6().initialize(target_bzrdir)
934
branch = _mod_branch.BzrBranchFormat6().initialize(target_bzrdir)
934
935
# Ensure that stack_on will be stackable and match the serializer of
936
937
if isinstance(repo, remote.RemoteRepository):
1012
1013
repo = self.make_repository_and_foo_bar(shared=True)
1013
1014
except errors.IncompatibleFormat:
1014
raise TestNotApplicable
1015
raise tests.TestNotApplicable
1015
1016
branches = repo.find_branches(using=True)
1016
1017
self.assertContainsRe(branches[-1].base, 'repository/foo/$')
1017
1018
# in some formats, creating a repo creates a branch
1046
1047
repo.set_make_working_trees(True)
1047
1048
except errors.RepositoryUpgradeRequired, e:
1048
raise TestNotApplicable('Format does not support this flag.')
1049
raise tests.TestNotApplicable('Format does not support this flag.')
1049
1050
self.assertTrue(repo.make_working_trees())
1051
1052
def test_set_get_make_working_trees_false(self):
1054
1055
repo.set_make_working_trees(False)
1055
1056
except errors.RepositoryUpgradeRequired, e:
1056
raise TestNotApplicable('Format does not support this flag.')
1057
raise tests.TestNotApplicable('Format does not support this flag.')
1057
1058
self.assertFalse(repo.make_working_trees())
1060
class TestRepositoryLocking(TestCaseWithRepository):
1061
class TestRepositoryLocking(per_repository.TestCaseWithRepository):
1062
1063
def test_leave_lock_in_place(self):
1063
1064
repo = self.make_repository('r')
1149
1150
tree_a.commit('rev3', rev_id='rev3', allow_pointless=True)
1150
1151
except errors.RevisionNotPresent:
1151
raise TestNotApplicable("Cannot test with ghosts for this format.")
1152
raise tests.TestNotApplicable(
1153
"Cannot test with ghosts for this format.")
1152
1154
# add another reference to a ghost, and a second ghost.
1153
1155
tree_a.add_parent_tree_id('ghost1')
1154
1156
tree_a.add_parent_tree_id('ghost2')
1217
1219
repo = self.make_repository('inventory_with_unnecessary_ghost')
1218
1220
repo.lock_write()
1219
1221
repo.start_write_group()
1220
inv = Inventory(revision_id = 'ghost')
1222
inv = inventory.Inventory(revision_id = 'ghost')
1221
1223
inv.root.revision = 'ghost'
1222
1224
if repo.supports_rich_root():
1223
1225
root_id = inv.root.file_id
1224
1226
repo.texts.add_lines((root_id, 'ghost'), [], [])
1225
1227
sha1 = repo.add_inventory('ghost', inv, [])
1226
rev = bzrlib.revision.Revision(timestamp=0,
1228
committer="Foo Bar <foo@example.com>",
1230
inventory_sha1=sha1,
1231
revision_id='ghost')
1228
rev = _mod_revision.Revision(
1229
timestamp=0, timezone=None, committer="Foo Bar <foo@example.com>",
1230
message="Message", inventory_sha1=sha1, revision_id='ghost')
1232
1231
rev.parent_ids = ['the_ghost']
1234
1233
repo.add_revision('ghost', rev)
1235
1234
except (errors.NoSuchRevision, errors.RevisionNotPresent):
1236
raise TestNotApplicable("Cannot test with ghosts for this format.")
1235
raise tests.TestNotApplicable(
1236
"Cannot test with ghosts for this format.")
1238
inv = Inventory(revision_id = 'the_ghost')
1238
inv = inventory.Inventory(revision_id = 'the_ghost')
1239
1239
inv.root.revision = 'the_ghost'
1240
1240
if repo.supports_rich_root():
1241
1241
root_id = inv.root.file_id
1242
1242
repo.texts.add_lines((root_id, 'the_ghost'), [], [])
1243
1243
sha1 = repo.add_inventory('the_ghost', inv, [])
1244
rev = bzrlib.revision.Revision(timestamp=0,
1246
committer="Foo Bar <foo@example.com>",
1248
inventory_sha1=sha1,
1249
revision_id='the_ghost')
1244
rev = _mod_revision.Revision(
1245
timestamp=0, timezone=None, committer="Foo Bar <foo@example.com>",
1246
message="Message", inventory_sha1=sha1, revision_id='the_ghost')
1250
1247
rev.parent_ids = []
1251
1248
repo.add_revision('the_ghost', rev)
1252
1249
# check its setup usefully
1280
1277
# FIXME: document why this is a TestCaseWithTransport rather than a
1281
1278
# TestCaseWithRepository
1282
class TestEscaping(TestCaseWithTransport):
1279
class TestEscaping(tests.TestCaseWithTransport):
1283
1280
"""Test that repositories can be stored correctly on VFAT transports.
1285
1282
Makes sure we have proper escaping of invalid characters, etc.
1293
1290
def test_on_vfat(self):
1294
1291
# dont bother with remote repository testing, because this test is
1295
1292
# about local disk layout/support.
1296
from bzrlib.remote import RemoteRepositoryFormat
1297
if isinstance(self.repository_format, RemoteRepositoryFormat):
1293
if isinstance(self.repository_format, remote.RemoteRepositoryFormat):
1299
1295
self.transport_server = FakeVFATServer
1300
1296
FOO_ID = 'foo<:>ID'
1321
1317
wt.add('file1')
1322
1318
wt.commit('file1', rev_id='rev1')
1323
1319
fileobj = StringIO()
1324
wt.branch.repository.create_bundle('rev1', NULL_REVISION, fileobj)
1320
wt.branch.repository.create_bundle(
1321
'rev1', _mod_revision.NULL_REVISION, fileobj)