1
# (C) 2006 Canonical Ltd
1
# Copyright (C) 2006, 2007 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
11
# GNU General Public License for more details.
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33
34
UnknownFormatError,
34
35
UnsupportedFormatError,
36
import bzrlib.repository as repository
37
from bzrlib.tests import TestCase, TestCaseWithTransport
37
from bzrlib.repository import RepositoryFormat
38
from bzrlib.tests import (
40
TestCaseWithTransport,
38
43
from bzrlib.transport import get_transport
39
from bzrlib.transport.http import HttpServer
40
44
from bzrlib.transport.memory import MemoryServer
45
from bzrlib.util import bencode
51
from bzrlib.repofmt import knitrepo, weaverepo
43
54
class TestDefaultFormat(TestCase):
45
56
def test_get_set_default_format(self):
57
old_default = bzrdir.format_registry.get('default')
58
private_default = old_default().repository_format.__class__
46
59
old_format = repository.RepositoryFormat.get_default_format()
47
self.assertTrue(isinstance(old_format, repository.RepositoryFormatKnit1))
48
repository.RepositoryFormat.set_default_format(SampleRepositoryFormat())
60
self.assertTrue(isinstance(old_format, private_default))
61
def make_sample_bzrdir():
62
my_bzrdir = bzrdir.BzrDirMetaFormat1()
63
my_bzrdir.repository_format = SampleRepositoryFormat()
65
bzrdir.format_registry.remove('default')
66
bzrdir.format_registry.register('sample', make_sample_bzrdir, '')
67
bzrdir.format_registry.set_default('sample')
49
68
# creating a repository should now create an instrumented dir.
51
70
# the default branch format is used by the meta dir format
52
71
# which is not the default bzrdir format at this point
53
dir = bzrdir.BzrDirMetaFormat1().initialize('memory:/')
72
dir = bzrdir.BzrDirMetaFormat1().initialize('memory:///')
54
73
result = dir.create_repository()
55
74
self.assertEqual(result, 'A bzr repository dir')
57
repository.RepositoryFormat.set_default_format(old_format)
58
self.assertEqual(old_format, repository.RepositoryFormat.get_default_format())
76
bzrdir.format_registry.remove('default')
77
bzrdir.format_registry.remove('sample')
78
bzrdir.format_registry.register('default', old_default, '')
79
self.assertIsInstance(repository.RepositoryFormat.get_default_format(),
61
83
class SampleRepositoryFormat(repository.RepositoryFormat):
321
343
self.check_knits(t)
324
class InterString(repository.InterRepository):
325
"""An inter-repository optimised code path for strings.
327
This is for use during testing where we use strings as repositories
346
class KnitRepositoryStreamTests(test_knit.KnitTests):
347
"""Tests for knitrepo._get_stream_as_bytes."""
349
def test_get_stream_as_bytes(self):
351
k1 = self.make_test_knit()
352
k1.add_lines('text-a', [], test_knit.split_lines(test_knit.TEXT_1))
354
# Serialise it, check the output.
355
bytes = knitrepo._get_stream_as_bytes(k1, ['text-a'])
356
data = bencode.bdecode(bytes)
357
format, record = data
358
self.assertEqual('knit-plain', format)
359
self.assertEqual(['text-a', ['fulltext'], []], record[:3])
360
self.assertRecordContentEqual(k1, 'text-a', record[3])
362
def test_get_stream_as_bytes_all(self):
363
"""Get a serialised data stream for all the records in a knit.
365
Much like test_get_stream_all, except for get_stream_as_bytes.
367
k1 = self.make_test_knit()
368
# Insert the same data as BasicKnitTests.test_knit_join, as they seem
369
# to cover a range of cases (no parents, one parent, multiple parents).
371
('text-a', [], test_knit.TEXT_1),
372
('text-b', ['text-a'], test_knit.TEXT_1),
373
('text-c', [], test_knit.TEXT_1),
374
('text-d', ['text-c'], test_knit.TEXT_1),
375
('text-m', ['text-b', 'text-d'], test_knit.TEXT_1),
377
expected_data_list = [
378
# version, options, parents
379
('text-a', ['fulltext'], []),
380
('text-b', ['line-delta'], ['text-a']),
381
('text-c', ['fulltext'], []),
382
('text-d', ['line-delta'], ['text-c']),
383
('text-m', ['line-delta'], ['text-b', 'text-d']),
385
for version_id, parents, lines in test_data:
386
k1.add_lines(version_id, parents, test_knit.split_lines(lines))
388
bytes = knitrepo._get_stream_as_bytes(
389
k1, ['text-a', 'text-b', 'text-c', 'text-d', 'text-m'])
391
data = bencode.bdecode(bytes)
393
self.assertEqual('knit-plain', format)
395
for expected, actual in zip(expected_data_list, data):
396
expected_version = expected[0]
397
expected_options = expected[1]
398
expected_parents = expected[2]
399
version, options, parents, bytes = actual
400
self.assertEqual(expected_version, version)
401
self.assertEqual(expected_options, options)
402
self.assertEqual(expected_parents, parents)
403
self.assertRecordContentEqual(k1, version, bytes)
406
class DummyRepository(object):
407
"""A dummy repository for testing."""
411
def supports_rich_root(self):
415
class InterDummy(repository.InterRepository):
416
"""An inter-repository optimised code path for DummyRepository.
418
This is for use during testing where we use DummyRepository as repositories
328
419
so that none of the default regsitered inter-repository classes will
333
424
def is_compatible(repo_source, repo_target):
334
"""InterString is compatible with strings-as-repos."""
335
return isinstance(repo_source, str) and isinstance(repo_target, str)
425
"""InterDummy is compatible with DummyRepository."""
426
return (isinstance(repo_source, DummyRepository) and
427
isinstance(repo_target, DummyRepository))
338
430
class TestInterRepository(TestCaseWithTransport):
344
436
# This also tests that the default registered optimised interrepository
345
437
# classes do not barf inappropriately when a surprising repository type
346
438
# is handed to them.
347
dummy_a = "Repository 1."
348
dummy_b = "Repository 2."
439
dummy_a = DummyRepository()
440
dummy_b = DummyRepository()
349
441
self.assertGetsDefaultInterRepository(dummy_a, dummy_b)
351
443
def assertGetsDefaultInterRepository(self, repo_a, repo_b):
352
"""Asserts that InterRepository.get(repo_a, repo_b) -> the default."""
444
"""Asserts that InterRepository.get(repo_a, repo_b) -> the default.
446
The effective default is now InterSameDataRepository because there is
447
no actual sane default in the presence of incompatible data models.
353
449
inter_repo = repository.InterRepository.get(repo_a, repo_b)
354
self.assertEqual(repository.InterRepository,
450
self.assertEqual(repository.InterSameDataRepository,
355
451
inter_repo.__class__)
356
452
self.assertEqual(repo_a, inter_repo.source)
357
453
self.assertEqual(repo_b, inter_repo.target)
362
458
# and that it is correctly selected when given a repository
363
459
# pair that it returns true on for the is_compatible static method
365
dummy_a = "Repository 1."
366
dummy_b = "Repository 2."
367
repository.InterRepository.register_optimiser(InterString)
461
dummy_a = DummyRepository()
462
dummy_b = DummyRepository()
463
repo = self.make_repository('.')
464
# hack dummies to look like repo somewhat.
465
dummy_a._serializer = repo._serializer
466
dummy_b._serializer = repo._serializer
467
repository.InterRepository.register_optimiser(InterDummy)
369
# we should get the default for something InterString returns False
469
# we should get the default for something InterDummy returns False
371
self.assertFalse(InterString.is_compatible(dummy_a, None))
372
self.assertGetsDefaultInterRepository(dummy_a, None)
373
# and we should get an InterString for a pair it 'likes'
374
self.assertTrue(InterString.is_compatible(dummy_a, dummy_b))
471
self.assertFalse(InterDummy.is_compatible(dummy_a, repo))
472
self.assertGetsDefaultInterRepository(dummy_a, repo)
473
# and we should get an InterDummy for a pair it 'likes'
474
self.assertTrue(InterDummy.is_compatible(dummy_a, dummy_b))
375
475
inter_repo = repository.InterRepository.get(dummy_a, dummy_b)
376
self.assertEqual(InterString, inter_repo.__class__)
476
self.assertEqual(InterDummy, inter_repo.__class__)
377
477
self.assertEqual(dummy_a, inter_repo.source)
378
478
self.assertEqual(dummy_b, inter_repo.target)
380
repository.InterRepository.unregister_optimiser(InterString)
480
repository.InterRepository.unregister_optimiser(InterDummy)
381
481
# now we should get the default InterRepository object again.
382
482
self.assertGetsDefaultInterRepository(dummy_a, dummy_b)
387
487
def test_is_compatible_and_registered(self):
388
488
# InterWeaveRepo is compatible when either side
389
489
# is a format 5/6/7 branch
390
formats = [repository.RepositoryFormat5(),
391
repository.RepositoryFormat6(),
392
repository.RepositoryFormat7()]
393
incompatible_formats = [repository.RepositoryFormat4(),
394
repository.RepositoryFormatKnit1(),
490
from bzrlib.repofmt import knitrepo, weaverepo
491
formats = [weaverepo.RepositoryFormat5(),
492
weaverepo.RepositoryFormat6(),
493
weaverepo.RepositoryFormat7()]
494
incompatible_formats = [weaverepo.RepositoryFormat4(),
495
knitrepo.RepositoryFormatKnit1(),
396
497
repo_a = self.make_repository('a')
397
498
repo_b = self.make_repository('b')
429
530
repo = repo_dir.open_repository()
430
531
self.assertTrue(isinstance(target_format, repo._format.__class__))
534
class TestMisc(TestCase):
536
def test_unescape_xml(self):
537
"""We get some kind of error when malformed entities are passed"""
538
self.assertRaises(KeyError, repository._unescape_xml, 'foo&bar;')
541
class TestRepositoryFormatKnit3(TestCaseWithTransport):
543
def test_convert(self):
544
"""Ensure the upgrade adds weaves for roots"""
545
format = bzrdir.BzrDirMetaFormat1()
546
format.repository_format = knitrepo.RepositoryFormatKnit1()
547
tree = self.make_branch_and_tree('.', format)
548
tree.commit("Dull commit", rev_id="dull")
549
revision_tree = tree.branch.repository.revision_tree('dull')
550
self.assertRaises(errors.NoSuchFile, revision_tree.get_file_lines,
551
revision_tree.inventory.root.file_id)
552
format = bzrdir.BzrDirMetaFormat1()
553
format.repository_format = knitrepo.RepositoryFormatKnit3()
554
upgrade.Convert('.', format)
555
tree = workingtree.WorkingTree.open('.')
556
revision_tree = tree.branch.repository.revision_tree('dull')
557
revision_tree.get_file_lines(revision_tree.inventory.root.file_id)
558
tree.commit("Another dull commit", rev_id='dull2')
559
revision_tree = tree.branch.repository.revision_tree('dull2')
560
self.assertEqual('dull', revision_tree.inventory.root.revision)