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
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
17
"""Tests for the BzrDir facility and any format specific tests.
19
For interface contract tests, see tests/per_bzr_dir.
19
For interface contract tests, see tests/bzr_dir_implementations.
24
from StringIO import StringIO
45
46
TestCaseWithMemoryTransport,
46
47
TestCaseWithTransport,
49
51
from bzrlib.tests import(
53
55
from bzrlib.tests.test_http import TestWithTransport_pycurl
54
from bzrlib.transport import (
56
from bzrlib.transport import get_transport
58
57
from bzrlib.transport.http._urllib import HttpTransport_urllib
58
from bzrlib.transport.memory import MemoryServer
59
59
from bzrlib.transport.nosmart import NoSmartTransportDecorator
60
60
from bzrlib.transport.readonly import ReadonlyTransportDecorator
61
from bzrlib.repofmt import knitrepo, weaverepo, pack_repo
61
from bzrlib.repofmt import knitrepo, weaverepo
64
64
class TestDefaultFormat(TestCase):
84
84
my_format_registry.register('weave', bzrdir.BzrDirFormat6,
85
85
'Pre-0.8 format. Slower and does not support checkouts or shared'
86
86
' repositories', deprecated=True)
87
my_format_registry.register_lazy('lazy', 'bzrlib.bzrdir',
87
my_format_registry.register_lazy('lazy', 'bzrlib.bzrdir',
88
88
'BzrDirFormat6', 'Format registered lazily', deprecated=True)
89
89
my_format_registry.register_metadir('knit',
90
90
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
117
117
my_bzrdir = my_format_registry.make_bzrdir('weave')
118
118
self.assertIsInstance(my_bzrdir, bzrdir.BzrDirFormat6)
119
119
my_bzrdir = my_format_registry.make_bzrdir('default')
120
self.assertIsInstance(my_bzrdir.repository_format,
120
self.assertIsInstance(my_bzrdir.repository_format,
121
121
knitrepo.RepositoryFormatKnit1)
122
122
my_bzrdir = my_format_registry.make_bzrdir('knit')
123
self.assertIsInstance(my_bzrdir.repository_format,
123
self.assertIsInstance(my_bzrdir.repository_format,
124
124
knitrepo.RepositoryFormatKnit1)
125
125
my_bzrdir = my_format_registry.make_bzrdir('branch6')
126
126
self.assertIsInstance(my_bzrdir.get_branch_format(),
130
130
my_format_registry = self.make_format_registry()
131
131
self.assertEqual('Format registered lazily',
132
132
my_format_registry.get_help('lazy'))
133
self.assertEqual('Format using knits',
133
self.assertEqual('Format using knits',
134
134
my_format_registry.get_help('knit'))
135
self.assertEqual('Format using knits',
135
self.assertEqual('Format using knits',
136
136
my_format_registry.get_help('default'))
137
137
self.assertEqual('Pre-0.8 format. Slower and does not support'
138
' checkouts or shared repositories',
138
' checkouts or shared repositories',
139
139
my_format_registry.get_help('weave'))
141
141
def test_help_topic(self):
142
142
topics = help_topics.HelpTopicRegistry()
143
143
registry = self.make_format_registry()
144
topics.register('current-formats', registry.help_topic,
144
topics.register('current-formats', registry.help_topic,
145
145
'Current formats')
146
topics.register('other-formats', registry.help_topic,
146
topics.register('other-formats', registry.help_topic,
148
148
new = topics.get_detail('current-formats')
149
149
rest = topics.get_detail('other-formats')
150
150
experimental, deprecated = rest.split('Deprecated formats')
151
self.assertContainsRe(new, 'formats-help')
152
self.assertContainsRe(new,
151
self.assertContainsRe(new, 'bzr help formats')
152
self.assertContainsRe(new,
153
153
':knit:\n \(native\) \(default\) Format using knits\n')
154
self.assertContainsRe(experimental,
154
self.assertContainsRe(experimental,
155
155
':branch6:\n \(native\) Experimental successor to knit')
156
self.assertContainsRe(deprecated,
156
self.assertContainsRe(deprecated,
157
157
':lazy:\n \(native\) Format registered lazily\n')
158
158
self.assertNotContainsRe(new, 'hidden')
180
180
'Pre-0.8 format. Slower and does not support checkouts or shared'
181
181
' repositories', deprecated=True, alias=True)
182
182
self.assertEqual(frozenset(['weavealias']), a_registry.aliases())
185
185
class SampleBranch(bzrlib.branch.Branch):
186
186
"""A dummy branch for guess what, dummy use."""
206
199
def open_repository(self):
207
200
"""See BzrDir.open_repository."""
208
return SampleRepository(self)
201
return "A repository"
210
def create_branch(self, name=None):
203
def create_branch(self):
211
204
"""See BzrDir.create_branch."""
213
raise NoColocatedBranchSupport(self)
214
205
return SampleBranch(self)
216
207
def create_workingtree(self):
248
239
def test_find_format(self):
249
240
# is the right format object found for a branch?
250
241
# create a branch with a few known format objects.
251
# this is not quite the same as
242
# this is not quite the same as
252
243
t = get_transport(self.get_url())
253
244
self.build_tree(["foo/", "bar/"], transport=t)
254
245
def check_format(format, url):
258
249
self.failUnless(isinstance(found_format, format.__class__))
259
250
check_format(bzrdir.BzrDirFormat5(), "foo")
260
251
check_format(bzrdir.BzrDirFormat6(), "bar")
262
253
def test_find_format_nothing_there(self):
263
254
self.assertRaises(NotBranchError,
264
255
bzrdir.BzrDirFormat.find_format,
308
299
branch.bzrdir.open_repository)
310
301
def test_create_branch_and_repo_under_shared_force_new(self):
311
# creating a branch and repo in a shared repo can be forced to
302
# creating a branch and repo in a shared repo can be forced to
312
303
# make a new repo
313
304
format = bzrdir.format_registry.make_bzrdir('knit')
314
305
self.make_repository('.', shared=True, format=format)
320
311
def test_create_standalone_working_tree(self):
321
312
format = SampleBzrDirFormat()
322
# note this is deliberately readonly, as this failure should
313
# note this is deliberately readonly, as this failure should
323
314
# occur before any writes.
324
315
self.assertRaises(errors.NotLocalUrl,
325
316
bzrdir.BzrDir.create_standalone_workingtree,
326
317
self.get_readonly_url(), format=format)
327
tree = bzrdir.BzrDir.create_standalone_workingtree('.',
318
tree = bzrdir.BzrDir.create_standalone_workingtree('.',
329
320
self.assertEqual('A tree', tree)
332
323
# create standalone working tree always makes a repo.
333
324
format = bzrdir.format_registry.make_bzrdir('knit')
334
325
self.make_repository('.', shared=True, format=format)
335
# note this is deliberately readonly, as this failure should
326
# note this is deliberately readonly, as this failure should
336
327
# occur before any writes.
337
328
self.assertRaises(errors.NotLocalUrl,
338
329
bzrdir.BzrDir.create_standalone_workingtree,
339
330
self.get_readonly_url('child'), format=format)
340
tree = bzrdir.BzrDir.create_standalone_workingtree('child',
331
tree = bzrdir.BzrDir.create_standalone_workingtree('child',
342
333
tree.bzrdir.open_repository()
360
351
def test_create_branch_convenience_root(self):
361
352
"""Creating a branch at the root of a fs should work."""
362
self.vfs_transport_factory = memory.MemoryServer
353
self.vfs_transport_factory = MemoryServer
363
354
# outside a repo the default convenience output is a repo+branch_tree
364
355
format = bzrdir.format_registry.make_bzrdir('knit')
365
branch = bzrdir.BzrDir.create_branch_convenience(self.get_url(),
356
branch = bzrdir.BzrDir.create_branch_convenience(self.get_url(),
367
358
self.assertRaises(errors.NoWorkingTree,
368
359
branch.bzrdir.open_workingtree)
378
369
branch.bzrdir.open_workingtree()
379
370
self.assertRaises(errors.NoRepositoryPresent,
380
371
branch.bzrdir.open_repository)
382
373
def test_create_branch_convenience_under_shared_repo_force_no_tree(self):
383
374
# inside a repo the default convenience output is a branch+ follow the
384
375
# repo tree policy but we can override that
390
381
branch.bzrdir.open_workingtree)
391
382
self.assertRaises(errors.NoRepositoryPresent,
392
383
branch.bzrdir.open_repository)
394
385
def test_create_branch_convenience_under_shared_repo_no_tree_policy(self):
395
386
# inside a repo the default convenience output is a branch+ follow the
396
387
# repo tree policy
397
388
format = bzrdir.format_registry.make_bzrdir('knit')
398
389
repo = self.make_repository('.', shared=True, format=format)
399
390
repo.set_make_working_trees(False)
400
branch = bzrdir.BzrDir.create_branch_convenience('child',
391
branch = bzrdir.BzrDir.create_branch_convenience('child',
402
393
self.assertRaises(errors.NoWorkingTree,
403
394
branch.bzrdir.open_workingtree)
433
424
"""The default acquisition policy should create a standalone branch."""
434
425
my_bzrdir = self.make_bzrdir('.')
435
426
repo_policy = my_bzrdir.determine_repository_policy()
436
repo, is_new = repo_policy.acquire_repository()
427
repo = repo_policy.acquire_repository()
437
428
self.assertEqual(repo.bzrdir.root_transport.base,
438
429
my_bzrdir.root_transport.base)
439
430
self.assertFalse(repo.is_shared())
441
433
def test_determine_stacking_policy(self):
442
434
parent_bzrdir = self.make_bzrdir('.')
443
435
child_bzrdir = self.make_bzrdir('child')
467
459
self.assertEqual(child_branch.base,
468
460
new_child.open_branch().get_stacked_on_url())
470
def test_default_stacking_with_stackable_branch_unstackable_repo(self):
471
# Make stackable source branch with an unstackable repo format.
472
source_bzrdir = self.make_bzrdir('source')
473
pack_repo.RepositoryFormatKnitPack1().initialize(source_bzrdir)
474
source_branch = bzrlib.branch.BzrBranchFormat7().initialize(
476
# Make a directory with a default stacking policy
477
parent_bzrdir = self.make_bzrdir('parent')
478
stacked_on = self.make_branch('parent/stacked-on', format='pack-0.92')
479
parent_bzrdir.get_config().set_default_stack_on(stacked_on.base)
480
# Clone source into directory
481
target = source_bzrdir.clone(self.get_url('parent/target'))
483
462
def test_sprout_obeys_stacking_policy(self):
484
463
child_branch, new_child_transport = self.prepare_default_stacking()
485
464
new_child = child_branch.bzrdir.sprout(new_child_transport.base)
573
552
super(ChrootedTests, self).setUp()
574
if not self.vfs_transport_factory == memory.MemoryServer:
553
if not self.vfs_transport_factory == MemoryServer:
575
554
self.transport_readonly_server = http_server.HttpServer
577
556
def local_branch_path(self, branch):
739
718
opened_bzrdir = bzrdir.BzrDir.open_from_transport(transport)
740
719
self.assertEqual(transport.base, opened_bzrdir.root_transport.base)
741
720
self.assertIsInstance(opened_bzrdir, bzrdir.BzrDir)
743
722
def test_open_from_transport_no_bzrdir(self):
744
723
transport = get_transport(self.get_url())
745
724
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport,
756
735
def test_sprout_recursive(self):
757
tree = self.make_branch_and_tree('tree1',
758
format='dirstate-with-subtree')
736
tree = self.make_branch_and_tree('tree1', format='dirstate-with-subtree')
759
737
sub_tree = self.make_branch_and_tree('tree1/subtree',
760
738
format='dirstate-with-subtree')
761
sub_tree.set_root_id('subtree-root')
762
739
tree.add_reference(sub_tree)
763
740
self.build_tree(['tree1/subtree/file'])
764
741
sub_tree.add('file')
765
742
tree.commit('Initial commit')
766
tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
768
self.addCleanup(tree2.unlock)
743
tree.bzrdir.sprout('tree2')
769
744
self.failUnlessExists('tree2/subtree/file')
770
self.assertEqual('tree-reference', tree2.kind('subtree-root'))
772
746
def test_cloning_metadir(self):
773
747
"""Ensure that cloning metadir is suitable"""
900
874
def test_needs_conversion_different_working_tree(self):
901
875
# meta1dirs need an conversion if any element is not the default.
902
new_format = bzrdir.format_registry.make_bzrdir('dirstate')
903
tree = self.make_branch_and_tree('tree', format='knit')
904
self.assertTrue(tree.bzrdir.needs_format_conversion(
907
def test_initialize_on_format_uses_smart_transport(self):
908
self.setup_smart_server_with_call_log()
909
new_format = bzrdir.format_registry.make_bzrdir('dirstate')
910
transport = self.get_transport('target')
911
transport.ensure_base()
912
self.reset_smart_call_log()
913
instance = new_format.initialize_on_transport(transport)
914
self.assertIsInstance(instance, remote.RemoteBzrDir)
915
rpc_count = len(self.hpss_calls)
916
# This figure represent the amount of work to perform this use case. It
917
# is entirely ok to reduce this number if a test fails due to rpc_count
918
# being too low. If rpc_count increases, more network roundtrips have
919
# become necessary for this use case. Please do not adjust this number
920
# upwards without agreement from bzr's network support maintainers.
921
self.assertEqual(2, rpc_count)
876
old_format = bzrdir.BzrDirFormat.get_default_format()
878
new_default = bzrdir.format_registry.make_bzrdir('dirstate')
879
bzrdir.BzrDirFormat._set_default_format(new_default)
881
tree = self.make_branch_and_tree('tree', format='knit')
882
self.assertTrue(tree.bzrdir.needs_format_conversion())
884
bzrdir.BzrDirFormat._set_default_format(old_format)
924
887
class TestFormat5(TestCaseWithTransport):
925
888
"""Tests specific to the version 5 bzrdir format."""
927
890
def test_same_lockfiles_between_tree_repo_branch(self):
928
# this checks that only a single lockfiles instance is created
891
# this checks that only a single lockfiles instance is created
929
892
# for format 5 objects
930
893
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
931
894
def check_dir_components_use_same_lock(dir):
938
901
# and if we open it normally.
939
902
dir = bzrdir.BzrDir.open(self.get_url())
940
903
check_dir_components_use_same_lock(dir)
942
905
def test_can_convert(self):
943
906
# format 5 dirs are convertable
944
907
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
945
908
self.assertTrue(dir.can_convert_format())
947
910
def test_needs_conversion(self):
948
# format 5 dirs need a conversion if they are not the default,
950
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
951
# don't need to convert it to itself
952
self.assertFalse(dir.needs_format_conversion(bzrdir.BzrDirFormat5()))
953
# do need to convert it to the current default
954
self.assertTrue(dir.needs_format_conversion(
955
bzrdir.BzrDirFormat.get_default_format()))
911
# format 5 dirs need a conversion if they are not the default.
912
# and they start of not the default.
913
old_format = bzrdir.BzrDirFormat.get_default_format()
914
bzrdir.BzrDirFormat._set_default_format(bzrdir.BzrDirFormat5())
916
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
917
self.assertFalse(dir.needs_format_conversion())
919
bzrdir.BzrDirFormat._set_default_format(old_format)
920
self.assertTrue(dir.needs_format_conversion())
958
923
class TestFormat6(TestCaseWithTransport):
959
924
"""Tests specific to the version 6 bzrdir format."""
961
926
def test_same_lockfiles_between_tree_repo_branch(self):
962
# this checks that only a single lockfiles instance is created
927
# this checks that only a single lockfiles instance is created
963
928
# for format 6 objects
964
929
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
965
930
def check_dir_components_use_same_lock(dir):
972
937
# and if we open it normally.
973
938
dir = bzrdir.BzrDir.open(self.get_url())
974
939
check_dir_components_use_same_lock(dir)
976
941
def test_can_convert(self):
977
942
# format 6 dirs are convertable
978
943
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
979
944
self.assertTrue(dir.can_convert_format())
981
946
def test_needs_conversion(self):
982
947
# format 6 dirs need an conversion if they are not the default.
983
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
984
self.assertTrue(dir.needs_format_conversion(
985
bzrdir.BzrDirFormat.get_default_format()))
948
old_format = bzrdir.BzrDirFormat.get_default_format()
949
bzrdir.BzrDirFormat._set_default_format(bzrdir.BzrDirMetaFormat1())
951
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
952
self.assertTrue(dir.needs_format_conversion())
954
bzrdir.BzrDirFormat._set_default_format(old_format)
988
957
class NotBzrDir(bzrlib.bzrdir.BzrDir):
1020
989
class TestNotBzrDir(TestCaseWithTransport):
1021
990
"""Tests for using the bzrdir api with a non .bzr based disk format.
1023
992
If/when one of these is in the core, we can let the implementation tests
1024
993
verify this works.
1027
996
def test_create_and_find_format(self):
1028
# create a .notbzr dir
997
# create a .notbzr dir
1029
998
format = NotBzrDirFormat()
1030
999
dir = format.initialize(self.get_url())
1031
1000
self.assertIsInstance(dir, NotBzrDir)
1056
1025
def setUp(self):
1057
1026
super(NonLocalTests, self).setUp()
1058
self.vfs_transport_factory = memory.MemoryServer
1027
self.vfs_transport_factory = MemoryServer
1060
1029
def test_create_branch_convenience(self):
1061
1030
# outside a repo the default convenience output is a repo+branch_tree
1062
1031
format = bzrdir.format_registry.make_bzrdir('knit')
1108
1077
We can't inherit directly from TestCaseWithTwoWebservers or the
1109
1078
test framework will try to create an instance which cannot
1110
run, its implementation being incomplete.
1079
run, its implementation being incomplete.
1113
1082
def create_transport_readonly_server(self):
1170
1137
"""Tests redirections for pycurl implementation"""
1172
1139
def _qualified_url(self, host, port):
1173
result = 'http+pycurl://%s:%s' % (host, port)
1174
self.permit_url(result)
1140
return 'http+pycurl://%s:%s' % (host, port)
1178
1143
class TestHTTPRedirections_nosmart(TestHTTPRedirections,
1182
1147
_transport = NoSmartTransportDecorator
1184
1149
def _qualified_url(self, host, port):
1185
result = 'nosmart+http://%s:%s' % (host, port)
1186
self.permit_url(result)
1150
return 'nosmart+http://%s:%s' % (host, port)
1190
1153
class TestHTTPRedirections_readonly(TestHTTPRedirections,
1194
1157
_transport = ReadonlyTransportDecorator
1196
1159
def _qualified_url(self, host, port):
1197
result = 'readonly+http://%s:%s' % (host, port)
1198
self.permit_url(result)
1160
return 'readonly+http://%s:%s' % (host, port)
1202
1163
class TestDotBzrHidden(TestCaseWithTransport):
1254
1215
return _TestBzrDirFormat()
1257
class _TestBranchFormat(bzrlib.branch.BranchFormat):
1258
"""Test Branch format for TestBzrDirSprout."""
1261
1218
class _TestBranch(bzrlib.branch.Branch):
1262
1219
"""Test Branch implementation for TestBzrDirSprout."""
1264
1221
def __init__(self, *args, **kwargs):
1265
self._format = _TestBranchFormat()
1266
1222
super(_TestBranch, self).__init__(*args, **kwargs)
1267
1223
self.calls = []
1268
1224
self._parent = None
1289
1245
Usually, BzrDir.sprout should delegate to the branch's sprout method
1290
1246
for part of the work. This allows the source branch to control the
1291
1247
choice of format for the new branch.
1293
1249
There are exceptions, but this tests avoids them:
1294
1250
- if there's no branch in the source bzrdir,
1295
1251
- or if the stacking has been requested and the format needs to be
1316
1272
parent = grandparent_tree.bzrdir.sprout('parent').open_branch()
1317
1273
branch_tree = parent.bzrdir.sprout('branch').open_branch()
1318
1274
self.assertContainsRe(branch_tree.get_parent(), '/parent/$')
1321
class TestBzrDirHooks(TestCaseWithMemoryTransport):
1323
def test_pre_open_called(self):
1325
bzrdir.BzrDir.hooks.install_named_hook('pre_open', calls.append, None)
1326
transport = self.get_transport('foo')
1327
url = transport.base
1328
self.assertRaises(errors.NotBranchError, bzrdir.BzrDir.open, url)
1329
self.assertEqual([transport.base], [t.base for t in calls])
1331
def test_pre_open_actual_exceptions_raised(self):
1333
def fail_once(transport):
1336
raise errors.BzrError("fail")
1337
bzrdir.BzrDir.hooks.install_named_hook('pre_open', fail_once, None)
1338
transport = self.get_transport('foo')
1339
url = transport.base
1340
err = self.assertRaises(errors.BzrError, bzrdir.BzrDir.open, url)
1341
self.assertEqual('fail', err._preformatted_string)
1343
def test_post_repo_init(self):
1344
from bzrlib.bzrdir import RepoInitHookParams
1346
bzrdir.BzrDir.hooks.install_named_hook('post_repo_init',
1348
self.make_repository('foo')
1349
self.assertLength(1, calls)
1351
self.assertIsInstance(params, RepoInitHookParams)
1352
self.assertTrue(hasattr(params, 'bzrdir'))
1353
self.assertTrue(hasattr(params, 'repository'))