1
# Copyright (C) 2005, 2006, 2007 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 the BzrDir facility and any format specific tests.
19
For interface contract tests, see tests/bzr_dir_implementations.
24
from StringIO import StringIO
39
from bzrlib.errors import (NotBranchError,
41
UnsupportedFormatError,
43
from bzrlib.tests import (
45
TestCaseWithTransport,
49
from bzrlib.tests.http_server import HttpServer
50
from bzrlib.tests.http_utils import (
51
TestCaseWithTwoWebservers,
52
HTTPServerRedirecting,
54
from bzrlib.tests.test_http import TestWithTransport_pycurl
55
from bzrlib.transport import get_transport
56
from bzrlib.transport.http._urllib import HttpTransport_urllib
57
from bzrlib.transport.memory import MemoryServer
58
from bzrlib.repofmt import knitrepo, weaverepo
61
class TestDefaultFormat(TestCase):
63
def test_get_set_default_format(self):
64
old_format = bzrdir.BzrDirFormat.get_default_format()
65
# default is BzrDirFormat6
66
self.failUnless(isinstance(old_format, bzrdir.BzrDirMetaFormat1))
67
bzrdir.BzrDirFormat._set_default_format(SampleBzrDirFormat())
68
# creating a bzr dir should now create an instrumented dir.
70
result = bzrdir.BzrDir.create('memory:///')
71
self.failUnless(isinstance(result, SampleBzrDir))
73
bzrdir.BzrDirFormat._set_default_format(old_format)
74
self.assertEqual(old_format, bzrdir.BzrDirFormat.get_default_format())
77
class TestFormatRegistry(TestCase):
79
def make_format_registry(self):
80
my_format_registry = bzrdir.BzrDirFormatRegistry()
81
my_format_registry.register('weave', bzrdir.BzrDirFormat6,
82
'Pre-0.8 format. Slower and does not support checkouts or shared'
83
' repositories', deprecated=True)
84
my_format_registry.register_lazy('lazy', 'bzrlib.bzrdir',
85
'BzrDirFormat6', 'Format registered lazily', deprecated=True)
86
my_format_registry.register_metadir('knit',
87
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
90
my_format_registry.set_default('knit')
91
my_format_registry.register_metadir(
93
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
94
'Experimental successor to knit. Use at your own risk.',
95
branch_format='bzrlib.branch.BzrBranchFormat6',
97
my_format_registry.register_metadir(
99
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
100
'Experimental successor to knit. Use at your own risk.',
101
branch_format='bzrlib.branch.BzrBranchFormat6', hidden=True)
102
my_format_registry.register('hiddenweave', bzrdir.BzrDirFormat6,
103
'Pre-0.8 format. Slower and does not support checkouts or shared'
104
' repositories', hidden=True)
105
my_format_registry.register_lazy('hiddenlazy', 'bzrlib.bzrdir',
106
'BzrDirFormat6', 'Format registered lazily', deprecated=True,
108
return my_format_registry
110
def test_format_registry(self):
111
my_format_registry = self.make_format_registry()
112
my_bzrdir = my_format_registry.make_bzrdir('lazy')
113
self.assertIsInstance(my_bzrdir, bzrdir.BzrDirFormat6)
114
my_bzrdir = my_format_registry.make_bzrdir('weave')
115
self.assertIsInstance(my_bzrdir, bzrdir.BzrDirFormat6)
116
my_bzrdir = my_format_registry.make_bzrdir('default')
117
self.assertIsInstance(my_bzrdir.repository_format,
118
knitrepo.RepositoryFormatKnit1)
119
my_bzrdir = my_format_registry.make_bzrdir('knit')
120
self.assertIsInstance(my_bzrdir.repository_format,
121
knitrepo.RepositoryFormatKnit1)
122
my_bzrdir = my_format_registry.make_bzrdir('branch6')
123
self.assertIsInstance(my_bzrdir.get_branch_format(),
124
bzrlib.branch.BzrBranchFormat6)
126
def test_get_help(self):
127
my_format_registry = self.make_format_registry()
128
self.assertEqual('Format registered lazily',
129
my_format_registry.get_help('lazy'))
130
self.assertEqual('Format using knits',
131
my_format_registry.get_help('knit'))
132
self.assertEqual('Format using knits',
133
my_format_registry.get_help('default'))
134
self.assertEqual('Pre-0.8 format. Slower and does not support'
135
' checkouts or shared repositories',
136
my_format_registry.get_help('weave'))
138
def test_help_topic(self):
139
topics = help_topics.HelpTopicRegistry()
140
topics.register('formats', self.make_format_registry().help_topic,
142
topic = topics.get_detail('formats')
143
new, rest = topic.split('Experimental formats')
144
experimental, deprecated = rest.split('Deprecated formats')
145
self.assertContainsRe(new, 'These formats can be used')
146
self.assertContainsRe(new,
147
':knit:\n \(native\) \(default\) Format using knits\n')
148
self.assertContainsRe(experimental,
149
':branch6:\n \(native\) Experimental successor to knit')
150
self.assertContainsRe(deprecated,
151
':lazy:\n \(native\) Format registered lazily\n')
152
self.assertNotContainsRe(new, 'hidden')
154
def test_set_default_repository(self):
155
default_factory = bzrdir.format_registry.get('default')
156
old_default = [k for k, v in bzrdir.format_registry.iteritems()
157
if v == default_factory and k != 'default'][0]
158
bzrdir.format_registry.set_default_repository('dirstate-with-subtree')
160
self.assertIs(bzrdir.format_registry.get('dirstate-with-subtree'),
161
bzrdir.format_registry.get('default'))
163
repository.RepositoryFormat.get_default_format().__class__,
164
knitrepo.RepositoryFormatKnit3)
166
bzrdir.format_registry.set_default_repository(old_default)
168
def test_aliases(self):
169
a_registry = bzrdir.BzrDirFormatRegistry()
170
a_registry.register('weave', bzrdir.BzrDirFormat6,
171
'Pre-0.8 format. Slower and does not support checkouts or shared'
172
' repositories', deprecated=True)
173
a_registry.register('weavealias', bzrdir.BzrDirFormat6,
174
'Pre-0.8 format. Slower and does not support checkouts or shared'
175
' repositories', deprecated=True, alias=True)
176
self.assertEqual(frozenset(['weavealias']), a_registry.aliases())
179
class SampleBranch(bzrlib.branch.Branch):
180
"""A dummy branch for guess what, dummy use."""
182
def __init__(self, dir):
186
class SampleBzrDir(bzrdir.BzrDir):
187
"""A sample BzrDir implementation to allow testing static methods."""
189
def create_repository(self, shared=False):
190
"""See BzrDir.create_repository."""
191
return "A repository"
193
def open_repository(self):
194
"""See BzrDir.open_repository."""
195
return "A repository"
197
def create_branch(self):
198
"""See BzrDir.create_branch."""
199
return SampleBranch(self)
201
def create_workingtree(self):
202
"""See BzrDir.create_workingtree."""
206
class SampleBzrDirFormat(bzrdir.BzrDirFormat):
209
this format is initializable, unsupported to aid in testing the
210
open and open_downlevel routines.
213
def get_format_string(self):
214
"""See BzrDirFormat.get_format_string()."""
215
return "Sample .bzr dir format."
217
def initialize_on_transport(self, t):
218
"""Create a bzr dir."""
220
t.put_bytes('.bzr/branch-format', self.get_format_string())
221
return SampleBzrDir(t, self)
223
def is_supported(self):
226
def open(self, transport, _found=None):
227
return "opened branch."
230
class TestBzrDirFormat(TestCaseWithTransport):
231
"""Tests for the BzrDirFormat facility."""
233
def test_find_format(self):
234
# is the right format object found for a branch?
235
# create a branch with a few known format objects.
236
# this is not quite the same as
237
t = get_transport(self.get_url())
238
self.build_tree(["foo/", "bar/"], transport=t)
239
def check_format(format, url):
240
format.initialize(url)
241
t = get_transport(url)
242
found_format = bzrdir.BzrDirFormat.find_format(t)
243
self.failUnless(isinstance(found_format, format.__class__))
244
check_format(bzrdir.BzrDirFormat5(), "foo")
245
check_format(bzrdir.BzrDirFormat6(), "bar")
247
def test_find_format_nothing_there(self):
248
self.assertRaises(NotBranchError,
249
bzrdir.BzrDirFormat.find_format,
252
def test_find_format_unknown_format(self):
253
t = get_transport(self.get_url())
255
t.put_bytes('.bzr/branch-format', '')
256
self.assertRaises(UnknownFormatError,
257
bzrdir.BzrDirFormat.find_format,
260
def test_register_unregister_format(self):
261
format = SampleBzrDirFormat()
264
format.initialize(url)
265
# register a format for it.
266
bzrdir.BzrDirFormat.register_format(format)
267
# which bzrdir.Open will refuse (not supported)
268
self.assertRaises(UnsupportedFormatError, bzrdir.BzrDir.open, url)
269
# which bzrdir.open_containing will refuse (not supported)
270
self.assertRaises(UnsupportedFormatError, bzrdir.BzrDir.open_containing, url)
271
# but open_downlevel will work
272
t = get_transport(url)
273
self.assertEqual(format.open(t), bzrdir.BzrDir.open_unsupported(url))
274
# unregister the format
275
bzrdir.BzrDirFormat.unregister_format(format)
276
# now open_downlevel should fail too.
277
self.assertRaises(UnknownFormatError, bzrdir.BzrDir.open_unsupported, url)
279
def test_create_branch_and_repo_uses_default(self):
280
format = SampleBzrDirFormat()
281
branch = bzrdir.BzrDir.create_branch_and_repo(self.get_url(),
283
self.assertTrue(isinstance(branch, SampleBranch))
285
def test_create_branch_and_repo_under_shared(self):
286
# creating a branch and repo in a shared repo uses the
288
format = bzrdir.format_registry.make_bzrdir('knit')
289
self.make_repository('.', shared=True, format=format)
290
branch = bzrdir.BzrDir.create_branch_and_repo(
291
self.get_url('child'), format=format)
292
self.assertRaises(errors.NoRepositoryPresent,
293
branch.bzrdir.open_repository)
295
def test_create_branch_and_repo_under_shared_force_new(self):
296
# creating a branch and repo in a shared repo can be forced to
298
format = bzrdir.format_registry.make_bzrdir('knit')
299
self.make_repository('.', shared=True, format=format)
300
branch = bzrdir.BzrDir.create_branch_and_repo(self.get_url('child'),
303
branch.bzrdir.open_repository()
305
def test_create_standalone_working_tree(self):
306
format = SampleBzrDirFormat()
307
# note this is deliberately readonly, as this failure should
308
# occur before any writes.
309
self.assertRaises(errors.NotLocalUrl,
310
bzrdir.BzrDir.create_standalone_workingtree,
311
self.get_readonly_url(), format=format)
312
tree = bzrdir.BzrDir.create_standalone_workingtree('.',
314
self.assertEqual('A tree', tree)
316
def test_create_standalone_working_tree_under_shared_repo(self):
317
# create standalone working tree always makes a repo.
318
format = bzrdir.format_registry.make_bzrdir('knit')
319
self.make_repository('.', shared=True, format=format)
320
# note this is deliberately readonly, as this failure should
321
# occur before any writes.
322
self.assertRaises(errors.NotLocalUrl,
323
bzrdir.BzrDir.create_standalone_workingtree,
324
self.get_readonly_url('child'), format=format)
325
tree = bzrdir.BzrDir.create_standalone_workingtree('child',
327
tree.bzrdir.open_repository()
329
def test_create_branch_convenience(self):
330
# outside a repo the default convenience output is a repo+branch_tree
331
format = bzrdir.format_registry.make_bzrdir('knit')
332
branch = bzrdir.BzrDir.create_branch_convenience('.', format=format)
333
branch.bzrdir.open_workingtree()
334
branch.bzrdir.open_repository()
336
def test_create_branch_convenience_possible_transports(self):
337
"""Check that the optional 'possible_transports' is recognized"""
338
format = bzrdir.format_registry.make_bzrdir('knit')
339
t = self.get_transport()
340
branch = bzrdir.BzrDir.create_branch_convenience(
341
'.', format=format, possible_transports=[t])
342
branch.bzrdir.open_workingtree()
343
branch.bzrdir.open_repository()
345
def test_create_branch_convenience_root(self):
346
"""Creating a branch at the root of a fs should work."""
347
self.vfs_transport_factory = MemoryServer
348
# outside a repo the default convenience output is a repo+branch_tree
349
format = bzrdir.format_registry.make_bzrdir('knit')
350
branch = bzrdir.BzrDir.create_branch_convenience(self.get_url(),
352
self.assertRaises(errors.NoWorkingTree,
353
branch.bzrdir.open_workingtree)
354
branch.bzrdir.open_repository()
356
def test_create_branch_convenience_under_shared_repo(self):
357
# inside a repo the default convenience output is a branch+ follow the
359
format = bzrdir.format_registry.make_bzrdir('knit')
360
self.make_repository('.', shared=True, format=format)
361
branch = bzrdir.BzrDir.create_branch_convenience('child',
363
branch.bzrdir.open_workingtree()
364
self.assertRaises(errors.NoRepositoryPresent,
365
branch.bzrdir.open_repository)
367
def test_create_branch_convenience_under_shared_repo_force_no_tree(self):
368
# inside a repo the default convenience output is a branch+ follow the
369
# repo tree policy but we can override that
370
format = bzrdir.format_registry.make_bzrdir('knit')
371
self.make_repository('.', shared=True, format=format)
372
branch = bzrdir.BzrDir.create_branch_convenience('child',
373
force_new_tree=False, format=format)
374
self.assertRaises(errors.NoWorkingTree,
375
branch.bzrdir.open_workingtree)
376
self.assertRaises(errors.NoRepositoryPresent,
377
branch.bzrdir.open_repository)
379
def test_create_branch_convenience_under_shared_repo_no_tree_policy(self):
380
# inside a repo the default convenience output is a branch+ follow the
382
format = bzrdir.format_registry.make_bzrdir('knit')
383
repo = self.make_repository('.', shared=True, format=format)
384
repo.set_make_working_trees(False)
385
branch = bzrdir.BzrDir.create_branch_convenience('child',
387
self.assertRaises(errors.NoWorkingTree,
388
branch.bzrdir.open_workingtree)
389
self.assertRaises(errors.NoRepositoryPresent,
390
branch.bzrdir.open_repository)
392
def test_create_branch_convenience_under_shared_repo_no_tree_policy_force_tree(self):
393
# inside a repo the default convenience output is a branch+ follow the
394
# repo tree policy but we can override that
395
format = bzrdir.format_registry.make_bzrdir('knit')
396
repo = self.make_repository('.', shared=True, format=format)
397
repo.set_make_working_trees(False)
398
branch = bzrdir.BzrDir.create_branch_convenience('child',
399
force_new_tree=True, format=format)
400
branch.bzrdir.open_workingtree()
401
self.assertRaises(errors.NoRepositoryPresent,
402
branch.bzrdir.open_repository)
404
def test_create_branch_convenience_under_shared_repo_force_new_repo(self):
405
# inside a repo the default convenience output is overridable to give
407
format = bzrdir.format_registry.make_bzrdir('knit')
408
self.make_repository('.', shared=True, format=format)
409
branch = bzrdir.BzrDir.create_branch_convenience('child',
410
force_new_repo=True, format=format)
411
branch.bzrdir.open_repository()
412
branch.bzrdir.open_workingtree()
415
class TestRepositoryAcquisitionPolicy(TestCaseWithTransport):
417
def test_acquire_repository_standalone(self):
418
"""The default acquisition policy should create a standalone branch."""
419
my_bzrdir = self.make_bzrdir('.')
420
repo_policy = my_bzrdir.determine_repository_policy()
421
repo = repo_policy.acquire_repository()
422
self.assertEqual(repo.bzrdir.root_transport.base,
423
my_bzrdir.root_transport.base)
424
self.assertFalse(repo.is_shared())
427
def test_determine_stacking_policy(self):
428
parent_bzrdir = self.make_bzrdir('.')
429
child_bzrdir = self.make_bzrdir('child')
430
parent_bzrdir.get_config().set_default_stack_on('http://example.org')
431
repo_policy = child_bzrdir.determine_repository_policy()
432
self.assertEqual('http://example.org', repo_policy._stack_on)
434
def test_determine_stacking_policy_relative(self):
435
parent_bzrdir = self.make_bzrdir('.')
436
child_bzrdir = self.make_bzrdir('child')
437
parent_bzrdir.get_config().set_default_stack_on('child2')
438
repo_policy = child_bzrdir.determine_repository_policy()
439
self.assertEqual('child2', repo_policy._stack_on)
440
self.assertEqual(parent_bzrdir.root_transport.base,
441
repo_policy._stack_on_pwd)
443
def prepare_default_stacking(self):
444
parent_bzrdir = self.make_bzrdir('.')
445
child_branch = self.make_branch('child', format='development1')
446
parent_bzrdir.get_config().set_default_stack_on(child_branch.base)
447
new_child_transport = parent_bzrdir.transport.clone('child2')
448
return child_branch, new_child_transport
450
def test_clone_on_transport_obeys_stacking_policy(self):
451
child_branch, new_child_transport = self.prepare_default_stacking()
452
new_child = child_branch.bzrdir.clone_on_transport(new_child_transport)
453
self.assertEqual(child_branch.base,
454
new_child.open_branch().get_stacked_on_url())
456
def test_sprout_obeys_stacking_policy(self):
457
child_branch, new_child_transport = self.prepare_default_stacking()
458
new_child = child_branch.bzrdir.sprout(new_child_transport.base)
459
self.assertEqual(child_branch.base,
460
new_child.open_branch().get_stacked_on_url())
462
def test_add_fallback_repo_handles_absolute_urls(self):
463
stack_on = self.make_branch('stack_on', format='development1')
464
repo = self.make_repository('repo', format='development1')
465
policy = bzrdir.UseExistingRepository(repo, stack_on.base)
466
policy._add_fallback(repo)
468
def test_add_fallback_repo_handles_relative_urls(self):
469
stack_on = self.make_branch('stack_on', format='development1')
470
repo = self.make_repository('repo', format='development1')
471
policy = bzrdir.UseExistingRepository(repo, '.', stack_on.base)
472
policy._add_fallback(repo)
474
def test_configure_relative_branch_stacking_url(self):
475
stack_on = self.make_branch('stack_on', format='development1')
476
stacked = self.make_branch('stack_on/stacked', format='development1')
477
policy = bzrdir.UseExistingRepository(stacked.repository,
479
policy.configure_branch(stacked)
480
self.assertEqual('..', stacked.get_stacked_on_url())
482
def test_relative_branch_stacking_to_absolute(self):
483
stack_on = self.make_branch('stack_on', format='development1')
484
stacked = self.make_branch('stack_on/stacked', format='development1')
485
policy = bzrdir.UseExistingRepository(stacked.repository,
486
'.', self.get_readonly_url('stack_on'))
487
policy.configure_branch(stacked)
488
self.assertEqual(self.get_readonly_url('stack_on'),
489
stacked.get_stacked_on_url())
492
class ChrootedTests(TestCaseWithTransport):
493
"""A support class that provides readonly urls outside the local namespace.
495
This is done by checking if self.transport_server is a MemoryServer. if it
496
is then we are chrooted already, if it is not then an HttpServer is used
501
super(ChrootedTests, self).setUp()
502
if not self.vfs_transport_factory == MemoryServer:
503
self.transport_readonly_server = HttpServer
505
def local_branch_path(self, branch):
506
return os.path.realpath(urlutils.local_path_from_url(branch.base))
508
def test_open_containing(self):
509
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing,
510
self.get_readonly_url(''))
511
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing,
512
self.get_readonly_url('g/p/q'))
513
control = bzrdir.BzrDir.create(self.get_url())
514
branch, relpath = bzrdir.BzrDir.open_containing(self.get_readonly_url(''))
515
self.assertEqual('', relpath)
516
branch, relpath = bzrdir.BzrDir.open_containing(self.get_readonly_url('g/p/q'))
517
self.assertEqual('g/p/q', relpath)
519
def test_open_containing_tree_branch_or_repository_empty(self):
520
self.assertRaises(errors.NotBranchError,
521
bzrdir.BzrDir.open_containing_tree_branch_or_repository,
522
self.get_readonly_url(''))
524
def test_open_containing_tree_branch_or_repository_all(self):
525
self.make_branch_and_tree('topdir')
526
tree, branch, repo, relpath = \
527
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
529
self.assertEqual(os.path.realpath('topdir'),
530
os.path.realpath(tree.basedir))
531
self.assertEqual(os.path.realpath('topdir'),
532
self.local_branch_path(branch))
534
os.path.realpath(os.path.join('topdir', '.bzr', 'repository')),
535
repo.bzrdir.transport.local_abspath('repository'))
536
self.assertEqual(relpath, 'foo')
538
def test_open_containing_tree_branch_or_repository_no_tree(self):
539
self.make_branch('branch')
540
tree, branch, repo, relpath = \
541
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
543
self.assertEqual(tree, None)
544
self.assertEqual(os.path.realpath('branch'),
545
self.local_branch_path(branch))
547
os.path.realpath(os.path.join('branch', '.bzr', 'repository')),
548
repo.bzrdir.transport.local_abspath('repository'))
549
self.assertEqual(relpath, 'foo')
551
def test_open_containing_tree_branch_or_repository_repo(self):
552
self.make_repository('repo')
553
tree, branch, repo, relpath = \
554
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
556
self.assertEqual(tree, None)
557
self.assertEqual(branch, None)
559
os.path.realpath(os.path.join('repo', '.bzr', 'repository')),
560
repo.bzrdir.transport.local_abspath('repository'))
561
self.assertEqual(relpath, '')
563
def test_open_containing_tree_branch_or_repository_shared_repo(self):
564
self.make_repository('shared', shared=True)
565
bzrdir.BzrDir.create_branch_convenience('shared/branch',
566
force_new_tree=False)
567
tree, branch, repo, relpath = \
568
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
570
self.assertEqual(tree, None)
571
self.assertEqual(os.path.realpath('shared/branch'),
572
self.local_branch_path(branch))
574
os.path.realpath(os.path.join('shared', '.bzr', 'repository')),
575
repo.bzrdir.transport.local_abspath('repository'))
576
self.assertEqual(relpath, '')
578
def test_open_containing_tree_branch_or_repository_branch_subdir(self):
579
self.make_branch_and_tree('foo')
580
self.build_tree(['foo/bar/'])
581
tree, branch, repo, relpath = \
582
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
584
self.assertEqual(os.path.realpath('foo'),
585
os.path.realpath(tree.basedir))
586
self.assertEqual(os.path.realpath('foo'),
587
self.local_branch_path(branch))
589
os.path.realpath(os.path.join('foo', '.bzr', 'repository')),
590
repo.bzrdir.transport.local_abspath('repository'))
591
self.assertEqual(relpath, 'bar')
593
def test_open_containing_tree_branch_or_repository_repo_subdir(self):
594
self.make_repository('bar')
595
self.build_tree(['bar/baz/'])
596
tree, branch, repo, relpath = \
597
bzrdir.BzrDir.open_containing_tree_branch_or_repository(
599
self.assertEqual(tree, None)
600
self.assertEqual(branch, None)
602
os.path.realpath(os.path.join('bar', '.bzr', 'repository')),
603
repo.bzrdir.transport.local_abspath('repository'))
604
self.assertEqual(relpath, 'baz')
606
def test_open_containing_from_transport(self):
607
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing_from_transport,
608
get_transport(self.get_readonly_url('')))
609
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_containing_from_transport,
610
get_transport(self.get_readonly_url('g/p/q')))
611
control = bzrdir.BzrDir.create(self.get_url())
612
branch, relpath = bzrdir.BzrDir.open_containing_from_transport(
613
get_transport(self.get_readonly_url('')))
614
self.assertEqual('', relpath)
615
branch, relpath = bzrdir.BzrDir.open_containing_from_transport(
616
get_transport(self.get_readonly_url('g/p/q')))
617
self.assertEqual('g/p/q', relpath)
619
def test_open_containing_tree_or_branch(self):
620
self.make_branch_and_tree('topdir')
621
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
623
self.assertEqual(os.path.realpath('topdir'),
624
os.path.realpath(tree.basedir))
625
self.assertEqual(os.path.realpath('topdir'),
626
self.local_branch_path(branch))
627
self.assertIs(tree.bzrdir, branch.bzrdir)
628
self.assertEqual('foo', relpath)
629
# opening from non-local should not return the tree
630
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
631
self.get_readonly_url('topdir/foo'))
632
self.assertEqual(None, tree)
633
self.assertEqual('foo', relpath)
635
self.make_branch('topdir/foo')
636
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
638
self.assertIs(tree, None)
639
self.assertEqual(os.path.realpath('topdir/foo'),
640
self.local_branch_path(branch))
641
self.assertEqual('', relpath)
643
def test_open_tree_or_branch(self):
644
self.make_branch_and_tree('topdir')
645
tree, branch = bzrdir.BzrDir.open_tree_or_branch('topdir')
646
self.assertEqual(os.path.realpath('topdir'),
647
os.path.realpath(tree.basedir))
648
self.assertEqual(os.path.realpath('topdir'),
649
self.local_branch_path(branch))
650
self.assertIs(tree.bzrdir, branch.bzrdir)
651
# opening from non-local should not return the tree
652
tree, branch = bzrdir.BzrDir.open_tree_or_branch(
653
self.get_readonly_url('topdir'))
654
self.assertEqual(None, tree)
656
self.make_branch('topdir/foo')
657
tree, branch = bzrdir.BzrDir.open_tree_or_branch('topdir/foo')
658
self.assertIs(tree, None)
659
self.assertEqual(os.path.realpath('topdir/foo'),
660
self.local_branch_path(branch))
662
def test_open_from_transport(self):
663
# transport pointing at bzrdir should give a bzrdir with root transport
664
# set to the given transport
665
control = bzrdir.BzrDir.create(self.get_url())
666
transport = get_transport(self.get_url())
667
opened_bzrdir = bzrdir.BzrDir.open_from_transport(transport)
668
self.assertEqual(transport.base, opened_bzrdir.root_transport.base)
669
self.assertIsInstance(opened_bzrdir, bzrdir.BzrDir)
671
def test_open_from_transport_no_bzrdir(self):
672
transport = get_transport(self.get_url())
673
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport,
676
def test_open_from_transport_bzrdir_in_parent(self):
677
control = bzrdir.BzrDir.create(self.get_url())
678
transport = get_transport(self.get_url())
679
transport.mkdir('subdir')
680
transport = transport.clone('subdir')
681
self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport,
684
def test_sprout_recursive(self):
685
tree = self.make_branch_and_tree('tree1', format='dirstate-with-subtree')
686
sub_tree = self.make_branch_and_tree('tree1/subtree',
687
format='dirstate-with-subtree')
688
tree.add_reference(sub_tree)
689
self.build_tree(['tree1/subtree/file'])
691
tree.commit('Initial commit')
692
tree.bzrdir.sprout('tree2')
693
self.failUnlessExists('tree2/subtree/file')
695
def test_cloning_metadir(self):
696
"""Ensure that cloning metadir is suitable"""
697
bzrdir = self.make_bzrdir('bzrdir')
698
bzrdir.cloning_metadir()
699
branch = self.make_branch('branch', format='knit')
700
format = branch.bzrdir.cloning_metadir()
701
self.assertIsInstance(format.workingtree_format,
702
workingtree.WorkingTreeFormat3)
704
def test_sprout_recursive_treeless(self):
705
tree = self.make_branch_and_tree('tree1',
706
format='dirstate-with-subtree')
707
sub_tree = self.make_branch_and_tree('tree1/subtree',
708
format='dirstate-with-subtree')
709
tree.add_reference(sub_tree)
710
self.build_tree(['tree1/subtree/file'])
712
tree.commit('Initial commit')
713
tree.bzrdir.destroy_workingtree()
714
repo = self.make_repository('repo', shared=True,
715
format='dirstate-with-subtree')
716
repo.set_make_working_trees(False)
717
tree.bzrdir.sprout('repo/tree2')
718
self.failUnlessExists('repo/tree2/subtree')
719
self.failIfExists('repo/tree2/subtree/file')
721
def make_foo_bar_baz(self):
722
foo = bzrdir.BzrDir.create_branch_convenience('foo').bzrdir
723
bar = self.make_branch('foo/bar').bzrdir
724
baz = self.make_branch('baz').bzrdir
727
def test_find_bzrdirs(self):
728
foo, bar, baz = self.make_foo_bar_baz()
729
transport = get_transport(self.get_url())
730
self.assertEqualBzrdirs([baz, foo, bar],
731
bzrdir.BzrDir.find_bzrdirs(transport))
733
def test_find_bzrdirs_list_current(self):
734
def list_current(transport):
735
return [s for s in transport.list_dir('') if s != 'baz']
737
foo, bar, baz = self.make_foo_bar_baz()
738
transport = get_transport(self.get_url())
739
self.assertEqualBzrdirs([foo, bar],
740
bzrdir.BzrDir.find_bzrdirs(transport,
741
list_current=list_current))
744
def test_find_bzrdirs_evaluate(self):
745
def evaluate(bzrdir):
747
repo = bzrdir.open_repository()
748
except NoRepositoryPresent:
749
return True, bzrdir.root_transport.base
751
return False, bzrdir.root_transport.base
753
foo, bar, baz = self.make_foo_bar_baz()
754
transport = get_transport(self.get_url())
755
self.assertEqual([baz.root_transport.base, foo.root_transport.base],
756
list(bzrdir.BzrDir.find_bzrdirs(transport,
759
def assertEqualBzrdirs(self, first, second):
761
second = list(second)
762
self.assertEqual(len(first), len(second))
763
for x, y in zip(first, second):
764
self.assertEqual(x.root_transport.base, y.root_transport.base)
766
def test_find_branches(self):
767
root = self.make_repository('', shared=True)
768
foo, bar, baz = self.make_foo_bar_baz()
769
qux = self.make_bzrdir('foo/qux')
770
transport = get_transport(self.get_url())
771
branches = bzrdir.BzrDir.find_branches(transport)
772
self.assertEqual(baz.root_transport.base, branches[0].base)
773
self.assertEqual(foo.root_transport.base, branches[1].base)
774
self.assertEqual(bar.root_transport.base, branches[2].base)
776
# ensure this works without a top-level repo
777
branches = bzrdir.BzrDir.find_branches(transport.clone('foo'))
778
self.assertEqual(foo.root_transport.base, branches[0].base)
779
self.assertEqual(bar.root_transport.base, branches[1].base)
782
class TestMeta1DirFormat(TestCaseWithTransport):
783
"""Tests specific to the meta1 dir format."""
785
def test_right_base_dirs(self):
786
dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
788
branch_base = t.clone('branch').base
789
self.assertEqual(branch_base, dir.get_branch_transport(None).base)
790
self.assertEqual(branch_base,
791
dir.get_branch_transport(bzrlib.branch.BzrBranchFormat5()).base)
792
repository_base = t.clone('repository').base
793
self.assertEqual(repository_base, dir.get_repository_transport(None).base)
794
self.assertEqual(repository_base,
795
dir.get_repository_transport(weaverepo.RepositoryFormat7()).base)
796
checkout_base = t.clone('checkout').base
797
self.assertEqual(checkout_base, dir.get_workingtree_transport(None).base)
798
self.assertEqual(checkout_base,
799
dir.get_workingtree_transport(workingtree.WorkingTreeFormat3()).base)
801
def test_meta1dir_uses_lockdir(self):
802
"""Meta1 format uses a LockDir to guard the whole directory, not a file."""
803
dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
805
self.assertIsDirectory('branch-lock', t)
807
def test_comparison(self):
808
"""Equality and inequality behave properly.
810
Metadirs should compare equal iff they have the same repo, branch and
813
mydir = bzrdir.format_registry.make_bzrdir('knit')
814
self.assertEqual(mydir, mydir)
815
self.assertFalse(mydir != mydir)
816
otherdir = bzrdir.format_registry.make_bzrdir('knit')
817
self.assertEqual(otherdir, mydir)
818
self.assertFalse(otherdir != mydir)
819
otherdir2 = bzrdir.format_registry.make_bzrdir('dirstate-with-subtree')
820
self.assertNotEqual(otherdir2, mydir)
821
self.assertFalse(otherdir2 == mydir)
823
def test_needs_conversion_different_working_tree(self):
824
# meta1dirs need an conversion if any element is not the default.
825
old_format = bzrdir.BzrDirFormat.get_default_format()
827
new_default = bzrdir.format_registry.make_bzrdir('dirstate')
828
bzrdir.BzrDirFormat._set_default_format(new_default)
830
tree = self.make_branch_and_tree('tree', format='knit')
831
self.assertTrue(tree.bzrdir.needs_format_conversion())
833
bzrdir.BzrDirFormat._set_default_format(old_format)
836
class TestFormat5(TestCaseWithTransport):
837
"""Tests specific to the version 5 bzrdir format."""
839
def test_same_lockfiles_between_tree_repo_branch(self):
840
# this checks that only a single lockfiles instance is created
841
# for format 5 objects
842
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
843
def check_dir_components_use_same_lock(dir):
844
ctrl_1 = dir.open_repository().control_files
845
ctrl_2 = dir.open_branch().control_files
846
ctrl_3 = dir.open_workingtree()._control_files
847
self.assertTrue(ctrl_1 is ctrl_2)
848
self.assertTrue(ctrl_2 is ctrl_3)
849
check_dir_components_use_same_lock(dir)
850
# and if we open it normally.
851
dir = bzrdir.BzrDir.open(self.get_url())
852
check_dir_components_use_same_lock(dir)
854
def test_can_convert(self):
855
# format 5 dirs are convertable
856
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
857
self.assertTrue(dir.can_convert_format())
859
def test_needs_conversion(self):
860
# format 5 dirs need a conversion if they are not the default.
861
# and they start of not the default.
862
old_format = bzrdir.BzrDirFormat.get_default_format()
863
bzrdir.BzrDirFormat._set_default_format(bzrdir.BzrDirFormat5())
865
dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
866
self.assertFalse(dir.needs_format_conversion())
868
bzrdir.BzrDirFormat._set_default_format(old_format)
869
self.assertTrue(dir.needs_format_conversion())
872
class TestFormat6(TestCaseWithTransport):
873
"""Tests specific to the version 6 bzrdir format."""
875
def test_same_lockfiles_between_tree_repo_branch(self):
876
# this checks that only a single lockfiles instance is created
877
# for format 6 objects
878
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
879
def check_dir_components_use_same_lock(dir):
880
ctrl_1 = dir.open_repository().control_files
881
ctrl_2 = dir.open_branch().control_files
882
ctrl_3 = dir.open_workingtree()._control_files
883
self.assertTrue(ctrl_1 is ctrl_2)
884
self.assertTrue(ctrl_2 is ctrl_3)
885
check_dir_components_use_same_lock(dir)
886
# and if we open it normally.
887
dir = bzrdir.BzrDir.open(self.get_url())
888
check_dir_components_use_same_lock(dir)
890
def test_can_convert(self):
891
# format 6 dirs are convertable
892
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
893
self.assertTrue(dir.can_convert_format())
895
def test_needs_conversion(self):
896
# format 6 dirs need an conversion if they are not the default.
897
old_format = bzrdir.BzrDirFormat.get_default_format()
898
bzrdir.BzrDirFormat._set_default_format(bzrdir.BzrDirMetaFormat1())
900
dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
901
self.assertTrue(dir.needs_format_conversion())
903
bzrdir.BzrDirFormat._set_default_format(old_format)
906
class NotBzrDir(bzrlib.bzrdir.BzrDir):
907
"""A non .bzr based control directory."""
909
def __init__(self, transport, format):
910
self._format = format
911
self.root_transport = transport
912
self.transport = transport.clone('.not')
915
class NotBzrDirFormat(bzrlib.bzrdir.BzrDirFormat):
916
"""A test class representing any non-.bzr based disk format."""
918
def initialize_on_transport(self, transport):
919
"""Initialize a new .not dir in the base directory of a Transport."""
920
transport.mkdir('.not')
921
return self.open(transport)
923
def open(self, transport):
924
"""Open this directory."""
925
return NotBzrDir(transport, self)
928
def _known_formats(self):
929
return set([NotBzrDirFormat()])
932
def probe_transport(self, transport):
933
"""Our format is present if the transport ends in '.not/'."""
934
if transport.has('.not'):
935
return NotBzrDirFormat()
938
class TestNotBzrDir(TestCaseWithTransport):
939
"""Tests for using the bzrdir api with a non .bzr based disk format.
941
If/when one of these is in the core, we can let the implementation tests
945
def test_create_and_find_format(self):
946
# create a .notbzr dir
947
format = NotBzrDirFormat()
948
dir = format.initialize(self.get_url())
949
self.assertIsInstance(dir, NotBzrDir)
951
bzrlib.bzrdir.BzrDirFormat.register_control_format(format)
953
found = bzrlib.bzrdir.BzrDirFormat.find_format(
954
get_transport(self.get_url()))
955
self.assertIsInstance(found, NotBzrDirFormat)
957
bzrlib.bzrdir.BzrDirFormat.unregister_control_format(format)
959
def test_included_in_known_formats(self):
960
bzrlib.bzrdir.BzrDirFormat.register_control_format(NotBzrDirFormat)
962
formats = bzrlib.bzrdir.BzrDirFormat.known_formats()
963
for format in formats:
964
if isinstance(format, NotBzrDirFormat):
966
self.fail("No NotBzrDirFormat in %s" % formats)
968
bzrlib.bzrdir.BzrDirFormat.unregister_control_format(NotBzrDirFormat)
971
class NonLocalTests(TestCaseWithTransport):
972
"""Tests for bzrdir static behaviour on non local paths."""
975
super(NonLocalTests, self).setUp()
976
self.vfs_transport_factory = MemoryServer
978
def test_create_branch_convenience(self):
979
# outside a repo the default convenience output is a repo+branch_tree
980
format = bzrdir.format_registry.make_bzrdir('knit')
981
branch = bzrdir.BzrDir.create_branch_convenience(
982
self.get_url('foo'), format=format)
983
self.assertRaises(errors.NoWorkingTree,
984
branch.bzrdir.open_workingtree)
985
branch.bzrdir.open_repository()
987
def test_create_branch_convenience_force_tree_not_local_fails(self):
988
# outside a repo the default convenience output is a repo+branch_tree
989
format = bzrdir.format_registry.make_bzrdir('knit')
990
self.assertRaises(errors.NotLocalUrl,
991
bzrdir.BzrDir.create_branch_convenience,
995
t = get_transport(self.get_url('.'))
996
self.assertFalse(t.has('foo'))
998
def test_clone(self):
999
# clone into a nonlocal path works
1000
format = bzrdir.format_registry.make_bzrdir('knit')
1001
branch = bzrdir.BzrDir.create_branch_convenience('local',
1003
branch.bzrdir.open_workingtree()
1004
result = branch.bzrdir.clone(self.get_url('remote'))
1005
self.assertRaises(errors.NoWorkingTree,
1006
result.open_workingtree)
1007
result.open_branch()
1008
result.open_repository()
1010
def test_checkout_metadir(self):
1011
# checkout_metadir has reasonable working tree format even when no
1012
# working tree is present
1013
self.make_branch('branch-knit2', format='dirstate-with-subtree')
1014
my_bzrdir = bzrdir.BzrDir.open(self.get_url('branch-knit2'))
1015
checkout_format = my_bzrdir.checkout_metadir()
1016
self.assertIsInstance(checkout_format.workingtree_format,
1017
workingtree.WorkingTreeFormat3)
1020
class TestHTTPRedirectionLoop(object):
1021
"""Test redirection loop between two http servers.
1023
This MUST be used by daughter classes that also inherit from
1024
TestCaseWithTwoWebservers.
1026
We can't inherit directly from TestCaseWithTwoWebservers or the
1027
test framework will try to create an instance which cannot
1028
run, its implementation being incomplete.
1031
# Should be defined by daughter classes to ensure redirection
1032
# still use the same transport implementation (not currently
1033
# enforced as it's a bit tricky to get right (see the FIXME
1034
# in BzrDir.open_from_transport for the unique use case so
1038
def create_transport_readonly_server(self):
1039
return HTTPServerRedirecting()
1041
def create_transport_secondary_server(self):
1042
return HTTPServerRedirecting()
1045
# Both servers redirect to each server creating a loop
1046
super(TestHTTPRedirectionLoop, self).setUp()
1047
# The redirections will point to the new server
1048
self.new_server = self.get_readonly_server()
1049
# The requests to the old server will be redirected
1050
self.old_server = self.get_secondary_server()
1051
# Configure the redirections
1052
self.old_server.redirect_to(self.new_server.host, self.new_server.port)
1053
self.new_server.redirect_to(self.old_server.host, self.old_server.port)
1055
def _qualified_url(self, host, port):
1056
return 'http+%s://%s:%s' % (self._qualifier, host, port)
1058
def test_loop(self):
1059
# Starting from either server should loop
1060
old_url = self._qualified_url(self.old_server.host,
1061
self.old_server.port)
1062
oldt = self._transport(old_url)
1063
self.assertRaises(errors.NotBranchError,
1064
bzrdir.BzrDir.open_from_transport, oldt)
1065
new_url = self._qualified_url(self.new_server.host,
1066
self.new_server.port)
1067
newt = self._transport(new_url)
1068
self.assertRaises(errors.NotBranchError,
1069
bzrdir.BzrDir.open_from_transport, newt)
1072
class TestHTTPRedirections_urllib(TestHTTPRedirectionLoop,
1073
TestCaseWithTwoWebservers):
1074
"""Tests redirections for urllib implementation"""
1076
_qualifier = 'urllib'
1077
_transport = HttpTransport_urllib
1081
class TestHTTPRedirections_pycurl(TestWithTransport_pycurl,
1082
TestHTTPRedirectionLoop,
1083
TestCaseWithTwoWebservers):
1084
"""Tests redirections for pycurl implementation"""
1086
_qualifier = 'pycurl'
1089
class TestDotBzrHidden(TestCaseWithTransport):
1092
if sys.platform == 'win32':
1093
ls = [os.environ['COMSPEC'], '/C', 'dir', '/B']
1096
f = subprocess.Popen(self.ls, stdout=subprocess.PIPE,
1097
stderr=subprocess.PIPE)
1098
out, err = f.communicate()
1099
self.assertEqual(0, f.returncode, 'Calling %s failed: %s'
1101
return out.splitlines()
1103
def test_dot_bzr_hidden(self):
1104
if sys.platform == 'win32' and not win32utils.has_win32file:
1105
raise TestSkipped('unable to make file hidden without pywin32 library')
1106
b = bzrdir.BzrDir.create('.')
1107
self.build_tree(['a'])
1108
self.assertEquals(['a'], self.get_ls())
1110
def test_dot_bzr_hidden_with_url(self):
1111
if sys.platform == 'win32' and not win32utils.has_win32file:
1112
raise TestSkipped('unable to make file hidden without pywin32 library')
1113
b = bzrdir.BzrDir.create(urlutils.local_path_to_url('.'))
1114
self.build_tree(['a'])
1115
self.assertEquals(['a'], self.get_ls())