~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_bzrdir.py

NEWS section template into a separate file

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
2
 
 
2
#
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
12
12
#
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""Tests for the BzrDir facility and any format specific tests.
18
18
 
19
 
For interface contract tests, see tests/bzr_dir_implementations.
 
19
For interface contract tests, see tests/per_bzr_dir.
20
20
"""
21
21
 
22
22
import os
23
 
import os.path
24
 
from StringIO import StringIO
25
23
import subprocess
26
24
import sys
27
25
 
30
28
    errors,
31
29
    help_topics,
32
30
    repository,
33
 
    symbol_versioning,
 
31
    osutils,
 
32
    remote,
34
33
    urlutils,
35
34
    win32utils,
36
35
    workingtree,
42
41
                           )
43
42
from bzrlib.tests import (
44
43
    TestCase,
 
44
    TestCaseWithMemoryTransport,
45
45
    TestCaseWithTransport,
46
46
    TestSkipped,
47
 
    test_sftp_transport
48
47
    )
49
 
from bzrlib.tests.http_server import HttpServer
50
 
from bzrlib.tests.http_utils import (
51
 
    TestCaseWithTwoWebservers,
52
 
    HTTPServerRedirecting,
 
48
from bzrlib.tests import(
 
49
    http_server,
 
50
    http_utils,
53
51
    )
54
52
from bzrlib.tests.test_http import TestWithTransport_pycurl
55
53
from bzrlib.transport import get_transport
56
54
from bzrlib.transport.http._urllib import HttpTransport_urllib
57
55
from bzrlib.transport.memory import MemoryServer
58
 
from bzrlib.repofmt import knitrepo, weaverepo
 
56
from bzrlib.transport.nosmart import NoSmartTransportDecorator
 
57
from bzrlib.transport.readonly import ReadonlyTransportDecorator
 
58
from bzrlib.repofmt import knitrepo, weaverepo, pack_repo
59
59
 
60
60
 
61
61
class TestDefaultFormat(TestCase):
81
81
        my_format_registry.register('weave', bzrdir.BzrDirFormat6,
82
82
            'Pre-0.8 format.  Slower and does not support checkouts or shared'
83
83
            ' repositories', deprecated=True)
84
 
        my_format_registry.register_lazy('lazy', 'bzrlib.bzrdir', 
 
84
        my_format_registry.register_lazy('lazy', 'bzrlib.bzrdir',
85
85
            'BzrDirFormat6', 'Format registered lazily', deprecated=True)
86
86
        my_format_registry.register_metadir('knit',
87
87
            'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
114
114
        my_bzrdir = my_format_registry.make_bzrdir('weave')
115
115
        self.assertIsInstance(my_bzrdir, bzrdir.BzrDirFormat6)
116
116
        my_bzrdir = my_format_registry.make_bzrdir('default')
117
 
        self.assertIsInstance(my_bzrdir.repository_format, 
 
117
        self.assertIsInstance(my_bzrdir.repository_format,
118
118
            knitrepo.RepositoryFormatKnit1)
119
119
        my_bzrdir = my_format_registry.make_bzrdir('knit')
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('branch6')
123
123
        self.assertIsInstance(my_bzrdir.get_branch_format(),
127
127
        my_format_registry = self.make_format_registry()
128
128
        self.assertEqual('Format registered lazily',
129
129
                         my_format_registry.get_help('lazy'))
130
 
        self.assertEqual('Format using knits', 
 
130
        self.assertEqual('Format using knits',
131
131
                         my_format_registry.get_help('knit'))
132
 
        self.assertEqual('Format using knits', 
 
132
        self.assertEqual('Format using knits',
133
133
                         my_format_registry.get_help('default'))
134
134
        self.assertEqual('Pre-0.8 format.  Slower and does not support'
135
 
                         ' checkouts or shared repositories', 
 
135
                         ' checkouts or shared repositories',
136
136
                         my_format_registry.get_help('weave'))
137
 
        
 
137
 
138
138
    def test_help_topic(self):
139
139
        topics = help_topics.HelpTopicRegistry()
140
 
        topics.register('formats', self.make_format_registry().help_topic, 
141
 
                        'Directory formats')
142
 
        topic = topics.get_detail('formats')
143
 
        new, rest = topic.split('Experimental formats')
 
140
        registry = self.make_format_registry()
 
141
        topics.register('current-formats', registry.help_topic,
 
142
                        'Current formats')
 
143
        topics.register('other-formats', registry.help_topic,
 
144
                        'Other formats')
 
145
        new = topics.get_detail('current-formats')
 
146
        rest = topics.get_detail('other-formats')
144
147
        experimental, deprecated = rest.split('Deprecated formats')
145
 
        self.assertContainsRe(new, 'These formats can be used')
146
 
        self.assertContainsRe(new, 
 
148
        self.assertContainsRe(new, 'bzr help formats')
 
149
        self.assertContainsRe(new,
147
150
                ':knit:\n    \(native\) \(default\) Format using knits\n')
148
 
        self.assertContainsRe(experimental, 
 
151
        self.assertContainsRe(experimental,
149
152
                ':branch6:\n    \(native\) Experimental successor to knit')
150
 
        self.assertContainsRe(deprecated, 
 
153
        self.assertContainsRe(deprecated,
151
154
                ':lazy:\n    \(native\) Format registered lazily\n')
152
155
        self.assertNotContainsRe(new, 'hidden')
153
156
 
174
177
            'Pre-0.8 format.  Slower and does not support checkouts or shared'
175
178
            ' repositories', deprecated=True, alias=True)
176
179
        self.assertEqual(frozenset(['weavealias']), a_registry.aliases())
177
 
    
 
180
 
178
181
 
179
182
class SampleBranch(bzrlib.branch.Branch):
180
183
    """A dummy branch for guess what, dummy use."""
183
186
        self.bzrdir = dir
184
187
 
185
188
 
 
189
class SampleRepository(bzrlib.repository.Repository):
 
190
    """A dummy repo."""
 
191
 
 
192
    def __init__(self, dir):
 
193
        self.bzrdir = dir
 
194
 
 
195
 
186
196
class SampleBzrDir(bzrdir.BzrDir):
187
197
    """A sample BzrDir implementation to allow testing static methods."""
188
198
 
192
202
 
193
203
    def open_repository(self):
194
204
        """See BzrDir.open_repository."""
195
 
        return "A repository"
 
205
        return SampleRepository(self)
196
206
 
197
207
    def create_branch(self):
198
208
        """See BzrDir.create_branch."""
206
216
class SampleBzrDirFormat(bzrdir.BzrDirFormat):
207
217
    """A sample format
208
218
 
209
 
    this format is initializable, unsupported to aid in testing the 
 
219
    this format is initializable, unsupported to aid in testing the
210
220
    open and open_downlevel routines.
211
221
    """
212
222
 
233
243
    def test_find_format(self):
234
244
        # is the right format object found for a branch?
235
245
        # create a branch with a few known format objects.
236
 
        # this is not quite the same as 
 
246
        # this is not quite the same as
237
247
        t = get_transport(self.get_url())
238
248
        self.build_tree(["foo/", "bar/"], transport=t)
239
249
        def check_format(format, url):
243
253
            self.failUnless(isinstance(found_format, format.__class__))
244
254
        check_format(bzrdir.BzrDirFormat5(), "foo")
245
255
        check_format(bzrdir.BzrDirFormat6(), "bar")
246
 
        
 
256
 
247
257
    def test_find_format_nothing_there(self):
248
258
        self.assertRaises(NotBranchError,
249
259
                          bzrdir.BzrDirFormat.find_format,
293
303
                          branch.bzrdir.open_repository)
294
304
 
295
305
    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 
 
306
        # creating a branch and repo in a shared repo can be forced to
297
307
        # make a new repo
298
308
        format = bzrdir.format_registry.make_bzrdir('knit')
299
309
        self.make_repository('.', shared=True, format=format)
304
314
 
305
315
    def test_create_standalone_working_tree(self):
306
316
        format = SampleBzrDirFormat()
307
 
        # note this is deliberately readonly, as this failure should 
 
317
        # note this is deliberately readonly, as this failure should
308
318
        # occur before any writes.
309
319
        self.assertRaises(errors.NotLocalUrl,
310
320
                          bzrdir.BzrDir.create_standalone_workingtree,
311
321
                          self.get_readonly_url(), format=format)
312
 
        tree = bzrdir.BzrDir.create_standalone_workingtree('.', 
 
322
        tree = bzrdir.BzrDir.create_standalone_workingtree('.',
313
323
                                                           format=format)
314
324
        self.assertEqual('A tree', tree)
315
325
 
317
327
        # create standalone working tree always makes a repo.
318
328
        format = bzrdir.format_registry.make_bzrdir('knit')
319
329
        self.make_repository('.', shared=True, format=format)
320
 
        # note this is deliberately readonly, as this failure should 
 
330
        # note this is deliberately readonly, as this failure should
321
331
        # occur before any writes.
322
332
        self.assertRaises(errors.NotLocalUrl,
323
333
                          bzrdir.BzrDir.create_standalone_workingtree,
324
334
                          self.get_readonly_url('child'), format=format)
325
 
        tree = bzrdir.BzrDir.create_standalone_workingtree('child', 
 
335
        tree = bzrdir.BzrDir.create_standalone_workingtree('child',
326
336
            format=format)
327
337
        tree.bzrdir.open_repository()
328
338
 
347
357
        self.vfs_transport_factory = MemoryServer
348
358
        # outside a repo the default convenience output is a repo+branch_tree
349
359
        format = bzrdir.format_registry.make_bzrdir('knit')
350
 
        branch = bzrdir.BzrDir.create_branch_convenience(self.get_url(), 
 
360
        branch = bzrdir.BzrDir.create_branch_convenience(self.get_url(),
351
361
                                                         format=format)
352
362
        self.assertRaises(errors.NoWorkingTree,
353
363
                          branch.bzrdir.open_workingtree)
363
373
        branch.bzrdir.open_workingtree()
364
374
        self.assertRaises(errors.NoRepositoryPresent,
365
375
                          branch.bzrdir.open_repository)
366
 
            
 
376
 
367
377
    def test_create_branch_convenience_under_shared_repo_force_no_tree(self):
368
378
        # inside a repo the default convenience output is a branch+ follow the
369
379
        # repo tree policy but we can override that
375
385
                          branch.bzrdir.open_workingtree)
376
386
        self.assertRaises(errors.NoRepositoryPresent,
377
387
                          branch.bzrdir.open_repository)
378
 
            
 
388
 
379
389
    def test_create_branch_convenience_under_shared_repo_no_tree_policy(self):
380
390
        # inside a repo the default convenience output is a branch+ follow the
381
391
        # repo tree policy
382
392
        format = bzrdir.format_registry.make_bzrdir('knit')
383
393
        repo = self.make_repository('.', shared=True, format=format)
384
394
        repo.set_make_working_trees(False)
385
 
        branch = bzrdir.BzrDir.create_branch_convenience('child', 
 
395
        branch = bzrdir.BzrDir.create_branch_convenience('child',
386
396
                                                         format=format)
387
397
        self.assertRaises(errors.NoWorkingTree,
388
398
                          branch.bzrdir.open_workingtree)
418
428
        """The default acquisition policy should create a standalone branch."""
419
429
        my_bzrdir = self.make_bzrdir('.')
420
430
        repo_policy = my_bzrdir.determine_repository_policy()
421
 
        repo = repo_policy.acquire_repository()
 
431
        repo, is_new = repo_policy.acquire_repository()
422
432
        self.assertEqual(repo.bzrdir.root_transport.base,
423
433
                         my_bzrdir.root_transport.base)
424
434
        self.assertFalse(repo.is_shared())
425
435
 
 
436
    def test_determine_stacking_policy(self):
 
437
        parent_bzrdir = self.make_bzrdir('.')
 
438
        child_bzrdir = self.make_bzrdir('child')
 
439
        parent_bzrdir.get_config().set_default_stack_on('http://example.org')
 
440
        repo_policy = child_bzrdir.determine_repository_policy()
 
441
        self.assertEqual('http://example.org', repo_policy._stack_on)
 
442
 
 
443
    def test_determine_stacking_policy_relative(self):
 
444
        parent_bzrdir = self.make_bzrdir('.')
 
445
        child_bzrdir = self.make_bzrdir('child')
 
446
        parent_bzrdir.get_config().set_default_stack_on('child2')
 
447
        repo_policy = child_bzrdir.determine_repository_policy()
 
448
        self.assertEqual('child2', repo_policy._stack_on)
 
449
        self.assertEqual(parent_bzrdir.root_transport.base,
 
450
                         repo_policy._stack_on_pwd)
 
451
 
 
452
    def prepare_default_stacking(self, child_format='1.6'):
 
453
        parent_bzrdir = self.make_bzrdir('.')
 
454
        child_branch = self.make_branch('child', format=child_format)
 
455
        parent_bzrdir.get_config().set_default_stack_on(child_branch.base)
 
456
        new_child_transport = parent_bzrdir.transport.clone('child2')
 
457
        return child_branch, new_child_transport
 
458
 
 
459
    def test_clone_on_transport_obeys_stacking_policy(self):
 
460
        child_branch, new_child_transport = self.prepare_default_stacking()
 
461
        new_child = child_branch.bzrdir.clone_on_transport(new_child_transport)
 
462
        self.assertEqual(child_branch.base,
 
463
                         new_child.open_branch().get_stacked_on_url())
 
464
 
 
465
    def test_default_stacking_with_stackable_branch_unstackable_repo(self):
 
466
        # Make stackable source branch with an unstackable repo format.
 
467
        source_bzrdir = self.make_bzrdir('source')
 
468
        pack_repo.RepositoryFormatKnitPack1().initialize(source_bzrdir)
 
469
        source_branch = bzrlib.branch.BzrBranchFormat7().initialize(source_bzrdir)
 
470
        # Make a directory with a default stacking policy
 
471
        parent_bzrdir = self.make_bzrdir('parent')
 
472
        stacked_on = self.make_branch('parent/stacked-on', format='pack-0.92')
 
473
        parent_bzrdir.get_config().set_default_stack_on(stacked_on.base)
 
474
        # Clone source into directory
 
475
        target = source_bzrdir.clone(self.get_url('parent/target'))
 
476
 
 
477
    def test_sprout_obeys_stacking_policy(self):
 
478
        child_branch, new_child_transport = self.prepare_default_stacking()
 
479
        new_child = child_branch.bzrdir.sprout(new_child_transport.base)
 
480
        self.assertEqual(child_branch.base,
 
481
                         new_child.open_branch().get_stacked_on_url())
 
482
 
 
483
    def test_clone_ignores_policy_for_unsupported_formats(self):
 
484
        child_branch, new_child_transport = self.prepare_default_stacking(
 
485
            child_format='pack-0.92')
 
486
        new_child = child_branch.bzrdir.clone_on_transport(new_child_transport)
 
487
        self.assertRaises(errors.UnstackableBranchFormat,
 
488
                          new_child.open_branch().get_stacked_on_url)
 
489
 
 
490
    def test_sprout_ignores_policy_for_unsupported_formats(self):
 
491
        child_branch, new_child_transport = self.prepare_default_stacking(
 
492
            child_format='pack-0.92')
 
493
        new_child = child_branch.bzrdir.sprout(new_child_transport.base)
 
494
        self.assertRaises(errors.UnstackableBranchFormat,
 
495
                          new_child.open_branch().get_stacked_on_url)
 
496
 
 
497
    def test_sprout_upgrades_format_if_stacked_specified(self):
 
498
        child_branch, new_child_transport = self.prepare_default_stacking(
 
499
            child_format='pack-0.92')
 
500
        new_child = child_branch.bzrdir.sprout(new_child_transport.base,
 
501
                                               stacked=True)
 
502
        self.assertEqual(child_branch.bzrdir.root_transport.base,
 
503
                         new_child.open_branch().get_stacked_on_url())
 
504
        repo = new_child.open_repository()
 
505
        self.assertTrue(repo._format.supports_external_lookups)
 
506
        self.assertFalse(repo.supports_rich_root())
 
507
 
 
508
    def test_clone_on_transport_upgrades_format_if_stacked_on_specified(self):
 
509
        child_branch, new_child_transport = self.prepare_default_stacking(
 
510
            child_format='pack-0.92')
 
511
        new_child = child_branch.bzrdir.clone_on_transport(new_child_transport,
 
512
            stacked_on=child_branch.bzrdir.root_transport.base)
 
513
        self.assertEqual(child_branch.bzrdir.root_transport.base,
 
514
                         new_child.open_branch().get_stacked_on_url())
 
515
        repo = new_child.open_repository()
 
516
        self.assertTrue(repo._format.supports_external_lookups)
 
517
        self.assertFalse(repo.supports_rich_root())
 
518
 
 
519
    def test_sprout_upgrades_to_rich_root_format_if_needed(self):
 
520
        child_branch, new_child_transport = self.prepare_default_stacking(
 
521
            child_format='rich-root-pack')
 
522
        new_child = child_branch.bzrdir.sprout(new_child_transport.base,
 
523
                                               stacked=True)
 
524
        repo = new_child.open_repository()
 
525
        self.assertTrue(repo._format.supports_external_lookups)
 
526
        self.assertTrue(repo.supports_rich_root())
 
527
 
 
528
    def test_add_fallback_repo_handles_absolute_urls(self):
 
529
        stack_on = self.make_branch('stack_on', format='1.6')
 
530
        repo = self.make_repository('repo', format='1.6')
 
531
        policy = bzrdir.UseExistingRepository(repo, stack_on.base)
 
532
        policy._add_fallback(repo)
 
533
 
 
534
    def test_add_fallback_repo_handles_relative_urls(self):
 
535
        stack_on = self.make_branch('stack_on', format='1.6')
 
536
        repo = self.make_repository('repo', format='1.6')
 
537
        policy = bzrdir.UseExistingRepository(repo, '.', stack_on.base)
 
538
        policy._add_fallback(repo)
 
539
 
 
540
    def test_configure_relative_branch_stacking_url(self):
 
541
        stack_on = self.make_branch('stack_on', format='1.6')
 
542
        stacked = self.make_branch('stack_on/stacked', format='1.6')
 
543
        policy = bzrdir.UseExistingRepository(stacked.repository,
 
544
            '.', stack_on.base)
 
545
        policy.configure_branch(stacked)
 
546
        self.assertEqual('..', stacked.get_stacked_on_url())
 
547
 
 
548
    def test_relative_branch_stacking_to_absolute(self):
 
549
        stack_on = self.make_branch('stack_on', format='1.6')
 
550
        stacked = self.make_branch('stack_on/stacked', format='1.6')
 
551
        policy = bzrdir.UseExistingRepository(stacked.repository,
 
552
            '.', self.get_readonly_url('stack_on'))
 
553
        policy.configure_branch(stacked)
 
554
        self.assertEqual(self.get_readonly_url('stack_on'),
 
555
                         stacked.get_stacked_on_url())
 
556
 
426
557
 
427
558
class ChrootedTests(TestCaseWithTransport):
428
559
    """A support class that provides readonly urls outside the local namespace.
435
566
    def setUp(self):
436
567
        super(ChrootedTests, self).setUp()
437
568
        if not self.vfs_transport_factory == MemoryServer:
438
 
            self.transport_readonly_server = HttpServer
 
569
            self.transport_readonly_server = http_server.HttpServer
439
570
 
440
571
    def local_branch_path(self, branch):
441
572
         return os.path.realpath(urlutils.local_path_from_url(branch.base))
466
597
        self.assertEqual(os.path.realpath('topdir'),
467
598
                         self.local_branch_path(branch))
468
599
        self.assertEqual(
469
 
            os.path.realpath(os.path.join('topdir', '.bzr', 'repository')),
 
600
            osutils.realpath(os.path.join('topdir', '.bzr', 'repository')),
470
601
            repo.bzrdir.transport.local_abspath('repository'))
471
602
        self.assertEqual(relpath, 'foo')
472
603
 
479
610
        self.assertEqual(os.path.realpath('branch'),
480
611
                         self.local_branch_path(branch))
481
612
        self.assertEqual(
482
 
            os.path.realpath(os.path.join('branch', '.bzr', 'repository')),
 
613
            osutils.realpath(os.path.join('branch', '.bzr', 'repository')),
483
614
            repo.bzrdir.transport.local_abspath('repository'))
484
615
        self.assertEqual(relpath, 'foo')
485
616
 
491
622
        self.assertEqual(tree, None)
492
623
        self.assertEqual(branch, None)
493
624
        self.assertEqual(
494
 
            os.path.realpath(os.path.join('repo', '.bzr', 'repository')),
 
625
            osutils.realpath(os.path.join('repo', '.bzr', 'repository')),
495
626
            repo.bzrdir.transport.local_abspath('repository'))
496
627
        self.assertEqual(relpath, '')
497
628
 
506
637
        self.assertEqual(os.path.realpath('shared/branch'),
507
638
                         self.local_branch_path(branch))
508
639
        self.assertEqual(
509
 
            os.path.realpath(os.path.join('shared', '.bzr', 'repository')),
 
640
            osutils.realpath(os.path.join('shared', '.bzr', 'repository')),
510
641
            repo.bzrdir.transport.local_abspath('repository'))
511
642
        self.assertEqual(relpath, '')
512
643
 
521
652
        self.assertEqual(os.path.realpath('foo'),
522
653
                         self.local_branch_path(branch))
523
654
        self.assertEqual(
524
 
            os.path.realpath(os.path.join('foo', '.bzr', 'repository')),
 
655
            osutils.realpath(os.path.join('foo', '.bzr', 'repository')),
525
656
            repo.bzrdir.transport.local_abspath('repository'))
526
657
        self.assertEqual(relpath, 'bar')
527
658
 
534
665
        self.assertEqual(tree, None)
535
666
        self.assertEqual(branch, None)
536
667
        self.assertEqual(
537
 
            os.path.realpath(os.path.join('bar', '.bzr', 'repository')),
 
668
            osutils.realpath(os.path.join('bar', '.bzr', 'repository')),
538
669
            repo.bzrdir.transport.local_abspath('repository'))
539
670
        self.assertEqual(relpath, 'baz')
540
671
 
602
733
        opened_bzrdir = bzrdir.BzrDir.open_from_transport(transport)
603
734
        self.assertEqual(transport.base, opened_bzrdir.root_transport.base)
604
735
        self.assertIsInstance(opened_bzrdir, bzrdir.BzrDir)
605
 
        
 
736
 
606
737
    def test_open_from_transport_no_bzrdir(self):
607
738
        transport = get_transport(self.get_url())
608
739
        self.assertRaises(NotBranchError, bzrdir.BzrDir.open_from_transport,
617
748
                          transport)
618
749
 
619
750
    def test_sprout_recursive(self):
620
 
        tree = self.make_branch_and_tree('tree1', format='dirstate-with-subtree')
 
751
        tree = self.make_branch_and_tree('tree1',
 
752
                                         format='dirstate-with-subtree')
621
753
        sub_tree = self.make_branch_and_tree('tree1/subtree',
622
754
            format='dirstate-with-subtree')
 
755
        sub_tree.set_root_id('subtree-root')
623
756
        tree.add_reference(sub_tree)
624
757
        self.build_tree(['tree1/subtree/file'])
625
758
        sub_tree.add('file')
626
759
        tree.commit('Initial commit')
627
 
        tree.bzrdir.sprout('tree2')
 
760
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
 
761
        tree2.lock_read()
 
762
        self.addCleanup(tree2.unlock)
628
763
        self.failUnlessExists('tree2/subtree/file')
 
764
        self.assertEqual('tree-reference', tree2.kind('subtree-root'))
629
765
 
630
766
    def test_cloning_metadir(self):
631
767
        """Ensure that cloning metadir is suitable"""
757
893
 
758
894
    def test_needs_conversion_different_working_tree(self):
759
895
        # meta1dirs need an conversion if any element is not the default.
760
 
        old_format = bzrdir.BzrDirFormat.get_default_format()
761
 
        # test with 
762
 
        new_default = bzrdir.format_registry.make_bzrdir('dirstate')
763
 
        bzrdir.BzrDirFormat._set_default_format(new_default)
764
 
        try:
765
 
            tree = self.make_branch_and_tree('tree', format='knit')
766
 
            self.assertTrue(tree.bzrdir.needs_format_conversion())
767
 
        finally:
768
 
            bzrdir.BzrDirFormat._set_default_format(old_format)
 
896
        new_format = bzrdir.format_registry.make_bzrdir('dirstate')
 
897
        tree = self.make_branch_and_tree('tree', format='knit')
 
898
        self.assertTrue(tree.bzrdir.needs_format_conversion(
 
899
            new_format))
 
900
 
 
901
    def test_initialize_on_format_uses_smart_transport(self):
 
902
        self.setup_smart_server_with_call_log()
 
903
        new_format = bzrdir.format_registry.make_bzrdir('dirstate')
 
904
        transport = self.get_transport('target')
 
905
        transport.ensure_base()
 
906
        self.reset_smart_call_log()
 
907
        instance = new_format.initialize_on_transport(transport)
 
908
        self.assertIsInstance(instance, remote.RemoteBzrDir)
 
909
        rpc_count = len(self.hpss_calls)
 
910
        # This figure represent the amount of work to perform this use case. It
 
911
        # is entirely ok to reduce this number if a test fails due to rpc_count
 
912
        # being too low. If rpc_count increases, more network roundtrips have
 
913
        # become necessary for this use case. Please do not adjust this number
 
914
        # upwards without agreement from bzr's network support maintainers.
 
915
        self.assertEqual(2, rpc_count)
769
916
 
770
917
 
771
918
class TestFormat5(TestCaseWithTransport):
772
919
    """Tests specific to the version 5 bzrdir format."""
773
920
 
774
921
    def test_same_lockfiles_between_tree_repo_branch(self):
775
 
        # this checks that only a single lockfiles instance is created 
 
922
        # this checks that only a single lockfiles instance is created
776
923
        # for format 5 objects
777
924
        dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
778
925
        def check_dir_components_use_same_lock(dir):
785
932
        # and if we open it normally.
786
933
        dir = bzrdir.BzrDir.open(self.get_url())
787
934
        check_dir_components_use_same_lock(dir)
788
 
    
 
935
 
789
936
    def test_can_convert(self):
790
937
        # format 5 dirs are convertable
791
938
        dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
792
939
        self.assertTrue(dir.can_convert_format())
793
 
    
 
940
 
794
941
    def test_needs_conversion(self):
795
 
        # format 5 dirs need a conversion if they are not the default.
796
 
        # and they start of not the default.
797
 
        old_format = bzrdir.BzrDirFormat.get_default_format()
798
 
        bzrdir.BzrDirFormat._set_default_format(bzrdir.BzrDirFormat5())
799
 
        try:
800
 
            dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
801
 
            self.assertFalse(dir.needs_format_conversion())
802
 
        finally:
803
 
            bzrdir.BzrDirFormat._set_default_format(old_format)
804
 
        self.assertTrue(dir.needs_format_conversion())
 
942
        # format 5 dirs need a conversion if they are not the default,
 
943
        # and they aren't
 
944
        dir = bzrdir.BzrDirFormat5().initialize(self.get_url())
 
945
        # don't need to convert it to itself
 
946
        self.assertFalse(dir.needs_format_conversion(bzrdir.BzrDirFormat5()))
 
947
        # do need to convert it to the current default
 
948
        self.assertTrue(dir.needs_format_conversion(
 
949
            bzrdir.BzrDirFormat.get_default_format()))
805
950
 
806
951
 
807
952
class TestFormat6(TestCaseWithTransport):
808
953
    """Tests specific to the version 6 bzrdir format."""
809
954
 
810
955
    def test_same_lockfiles_between_tree_repo_branch(self):
811
 
        # this checks that only a single lockfiles instance is created 
 
956
        # this checks that only a single lockfiles instance is created
812
957
        # for format 6 objects
813
958
        dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
814
959
        def check_dir_components_use_same_lock(dir):
821
966
        # and if we open it normally.
822
967
        dir = bzrdir.BzrDir.open(self.get_url())
823
968
        check_dir_components_use_same_lock(dir)
824
 
    
 
969
 
825
970
    def test_can_convert(self):
826
971
        # format 6 dirs are convertable
827
972
        dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
828
973
        self.assertTrue(dir.can_convert_format())
829
 
    
 
974
 
830
975
    def test_needs_conversion(self):
831
976
        # format 6 dirs need an conversion if they are not the default.
832
 
        old_format = bzrdir.BzrDirFormat.get_default_format()
833
 
        bzrdir.BzrDirFormat._set_default_format(bzrdir.BzrDirMetaFormat1())
834
 
        try:
835
 
            dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
836
 
            self.assertTrue(dir.needs_format_conversion())
837
 
        finally:
838
 
            bzrdir.BzrDirFormat._set_default_format(old_format)
 
977
        dir = bzrdir.BzrDirFormat6().initialize(self.get_url())
 
978
        self.assertTrue(dir.needs_format_conversion(
 
979
            bzrdir.BzrDirFormat.get_default_format()))
839
980
 
840
981
 
841
982
class NotBzrDir(bzrlib.bzrdir.BzrDir):
872
1013
 
873
1014
class TestNotBzrDir(TestCaseWithTransport):
874
1015
    """Tests for using the bzrdir api with a non .bzr based disk format.
875
 
    
 
1016
 
876
1017
    If/when one of these is in the core, we can let the implementation tests
877
1018
    verify this works.
878
1019
    """
879
1020
 
880
1021
    def test_create_and_find_format(self):
881
 
        # create a .notbzr dir 
 
1022
        # create a .notbzr dir
882
1023
        format = NotBzrDirFormat()
883
1024
        dir = format.initialize(self.get_url())
884
1025
        self.assertIsInstance(dir, NotBzrDir)
909
1050
    def setUp(self):
910
1051
        super(NonLocalTests, self).setUp()
911
1052
        self.vfs_transport_factory = MemoryServer
912
 
    
 
1053
 
913
1054
    def test_create_branch_convenience(self):
914
1055
        # outside a repo the default convenience output is a repo+branch_tree
915
1056
        format = bzrdir.format_registry.make_bzrdir('knit')
952
1093
                              workingtree.WorkingTreeFormat3)
953
1094
 
954
1095
 
955
 
class TestHTTPRedirectionLoop(object):
956
 
    """Test redirection loop between two http servers.
 
1096
class TestHTTPRedirections(object):
 
1097
    """Test redirection between two http servers.
957
1098
 
958
1099
    This MUST be used by daughter classes that also inherit from
959
1100
    TestCaseWithTwoWebservers.
960
1101
 
961
1102
    We can't inherit directly from TestCaseWithTwoWebservers or the
962
1103
    test framework will try to create an instance which cannot
963
 
    run, its implementation being incomplete. 
 
1104
    run, its implementation being incomplete.
964
1105
    """
965
1106
 
966
 
    # Should be defined by daughter classes to ensure redirection
967
 
    # still use the same transport implementation (not currently
968
 
    # enforced as it's a bit tricky to get right (see the FIXME
969
 
    # in BzrDir.open_from_transport for the unique use case so
970
 
    # far)
971
 
    _qualifier = None
972
 
 
973
1107
    def create_transport_readonly_server(self):
974
 
        return HTTPServerRedirecting()
 
1108
        return http_utils.HTTPServerRedirecting()
975
1109
 
976
1110
    def create_transport_secondary_server(self):
977
 
        return HTTPServerRedirecting()
 
1111
        return http_utils.HTTPServerRedirecting()
978
1112
 
979
1113
    def setUp(self):
980
 
        # Both servers redirect to each server creating a loop
981
 
        super(TestHTTPRedirectionLoop, self).setUp()
 
1114
        super(TestHTTPRedirections, self).setUp()
982
1115
        # The redirections will point to the new server
983
1116
        self.new_server = self.get_readonly_server()
984
1117
        # The requests to the old server will be redirected
985
1118
        self.old_server = self.get_secondary_server()
986
1119
        # Configure the redirections
987
1120
        self.old_server.redirect_to(self.new_server.host, self.new_server.port)
 
1121
 
 
1122
    def test_loop(self):
 
1123
        # Both servers redirect to each other creating a loop
988
1124
        self.new_server.redirect_to(self.old_server.host, self.old_server.port)
989
 
 
990
 
    def _qualified_url(self, host, port):
991
 
        return 'http+%s://%s:%s' % (self._qualifier, host, port)
992
 
 
993
 
    def test_loop(self):
994
1125
        # Starting from either server should loop
995
 
        old_url = self._qualified_url(self.old_server.host, 
 
1126
        old_url = self._qualified_url(self.old_server.host,
996
1127
                                      self.old_server.port)
997
1128
        oldt = self._transport(old_url)
998
1129
        self.assertRaises(errors.NotBranchError,
999
1130
                          bzrdir.BzrDir.open_from_transport, oldt)
1000
 
        new_url = self._qualified_url(self.new_server.host, 
 
1131
        new_url = self._qualified_url(self.new_server.host,
1001
1132
                                      self.new_server.port)
1002
1133
        newt = self._transport(new_url)
1003
1134
        self.assertRaises(errors.NotBranchError,
1004
1135
                          bzrdir.BzrDir.open_from_transport, newt)
1005
1136
 
1006
 
 
1007
 
class TestHTTPRedirections_urllib(TestHTTPRedirectionLoop,
1008
 
                                  TestCaseWithTwoWebservers):
 
1137
    def test_qualifier_preserved(self):
 
1138
        wt = self.make_branch_and_tree('branch')
 
1139
        old_url = self._qualified_url(self.old_server.host,
 
1140
                                      self.old_server.port)
 
1141
        start = self._transport(old_url).clone('branch')
 
1142
        bdir = bzrdir.BzrDir.open_from_transport(start)
 
1143
        # Redirection should preserve the qualifier, hence the transport class
 
1144
        # itself.
 
1145
        self.assertIsInstance(bdir.root_transport, type(start))
 
1146
 
 
1147
 
 
1148
class TestHTTPRedirections_urllib(TestHTTPRedirections,
 
1149
                                  http_utils.TestCaseWithTwoWebservers):
1009
1150
    """Tests redirections for urllib implementation"""
1010
1151
 
1011
 
    _qualifier = 'urllib'
1012
1152
    _transport = HttpTransport_urllib
1013
1153
 
 
1154
    def _qualified_url(self, host, port):
 
1155
        return 'http+urllib://%s:%s' % (host, port)
 
1156
 
1014
1157
 
1015
1158
 
1016
1159
class TestHTTPRedirections_pycurl(TestWithTransport_pycurl,
1017
 
                                  TestHTTPRedirectionLoop,
1018
 
                                  TestCaseWithTwoWebservers):
 
1160
                                  TestHTTPRedirections,
 
1161
                                  http_utils.TestCaseWithTwoWebservers):
1019
1162
    """Tests redirections for pycurl implementation"""
1020
1163
 
1021
 
    _qualifier = 'pycurl'
 
1164
    def _qualified_url(self, host, port):
 
1165
        return 'http+pycurl://%s:%s' % (host, port)
 
1166
 
 
1167
 
 
1168
class TestHTTPRedirections_nosmart(TestHTTPRedirections,
 
1169
                                  http_utils.TestCaseWithTwoWebservers):
 
1170
    """Tests redirections for the nosmart decorator"""
 
1171
 
 
1172
    _transport = NoSmartTransportDecorator
 
1173
 
 
1174
    def _qualified_url(self, host, port):
 
1175
        return 'nosmart+http://%s:%s' % (host, port)
 
1176
 
 
1177
 
 
1178
class TestHTTPRedirections_readonly(TestHTTPRedirections,
 
1179
                                    http_utils.TestCaseWithTwoWebservers):
 
1180
    """Tests redirections for readonly decoratror"""
 
1181
 
 
1182
    _transport = ReadonlyTransportDecorator
 
1183
 
 
1184
    def _qualified_url(self, host, port):
 
1185
        return 'readonly+http://%s:%s' % (host, port)
1022
1186
 
1023
1187
 
1024
1188
class TestDotBzrHidden(TestCaseWithTransport):
1048
1212
        b = bzrdir.BzrDir.create(urlutils.local_path_to_url('.'))
1049
1213
        self.build_tree(['a'])
1050
1214
        self.assertEquals(['a'], self.get_ls())
 
1215
 
 
1216
 
 
1217
class _TestBzrDirFormat(bzrdir.BzrDirMetaFormat1):
 
1218
    """Test BzrDirFormat implementation for TestBzrDirSprout."""
 
1219
 
 
1220
    def _open(self, transport):
 
1221
        return _TestBzrDir(transport, self)
 
1222
 
 
1223
 
 
1224
class _TestBzrDir(bzrdir.BzrDirMeta1):
 
1225
    """Test BzrDir implementation for TestBzrDirSprout.
 
1226
 
 
1227
    When created a _TestBzrDir already has repository and a branch.  The branch
 
1228
    is a test double as well.
 
1229
    """
 
1230
 
 
1231
    def __init__(self, *args, **kwargs):
 
1232
        super(_TestBzrDir, self).__init__(*args, **kwargs)
 
1233
        self.test_branch = _TestBranch()
 
1234
        self.test_branch.repository = self.create_repository()
 
1235
 
 
1236
    def open_branch(self, unsupported=False):
 
1237
        return self.test_branch
 
1238
 
 
1239
    def cloning_metadir(self, require_stacking=False):
 
1240
        return _TestBzrDirFormat()
 
1241
 
 
1242
 
 
1243
class _TestBranchFormat(bzrlib.branch.BranchFormat):
 
1244
    """Test Branch format for TestBzrDirSprout."""
 
1245
 
 
1246
 
 
1247
class _TestBranch(bzrlib.branch.Branch):
 
1248
    """Test Branch implementation for TestBzrDirSprout."""
 
1249
 
 
1250
    def __init__(self, *args, **kwargs):
 
1251
        self._format = _TestBranchFormat()
 
1252
        super(_TestBranch, self).__init__(*args, **kwargs)
 
1253
        self.calls = []
 
1254
        self._parent = None
 
1255
 
 
1256
    def sprout(self, *args, **kwargs):
 
1257
        self.calls.append('sprout')
 
1258
        return _TestBranch()
 
1259
 
 
1260
    def copy_content_into(self, destination, revision_id=None):
 
1261
        self.calls.append('copy_content_into')
 
1262
 
 
1263
    def get_parent(self):
 
1264
        return self._parent
 
1265
 
 
1266
    def set_parent(self, parent):
 
1267
        self._parent = parent
 
1268
 
 
1269
 
 
1270
class TestBzrDirSprout(TestCaseWithMemoryTransport):
 
1271
 
 
1272
    def test_sprout_uses_branch_sprout(self):
 
1273
        """BzrDir.sprout calls Branch.sprout.
 
1274
 
 
1275
        Usually, BzrDir.sprout should delegate to the branch's sprout method
 
1276
        for part of the work.  This allows the source branch to control the
 
1277
        choice of format for the new branch.
 
1278
 
 
1279
        There are exceptions, but this tests avoids them:
 
1280
          - if there's no branch in the source bzrdir,
 
1281
          - or if the stacking has been requested and the format needs to be
 
1282
            overridden to satisfy that.
 
1283
        """
 
1284
        # Make an instrumented bzrdir.
 
1285
        t = self.get_transport('source')
 
1286
        t.ensure_base()
 
1287
        source_bzrdir = _TestBzrDirFormat().initialize_on_transport(t)
 
1288
        # The instrumented bzrdir has a test_branch attribute that logs calls
 
1289
        # made to the branch contained in that bzrdir.  Initially the test
 
1290
        # branch exists but no calls have been made to it.
 
1291
        self.assertEqual([], source_bzrdir.test_branch.calls)
 
1292
 
 
1293
        # Sprout the bzrdir
 
1294
        target_url = self.get_url('target')
 
1295
        result = source_bzrdir.sprout(target_url, recurse='no')
 
1296
 
 
1297
        # The bzrdir called the branch's sprout method.
 
1298
        self.assertSubset(['sprout'], source_bzrdir.test_branch.calls)
 
1299
 
 
1300
    def test_sprout_parent(self):
 
1301
        grandparent_tree = self.make_branch('grandparent')
 
1302
        parent = grandparent_tree.bzrdir.sprout('parent').open_branch()
 
1303
        branch_tree = parent.bzrdir.sprout('branch').open_branch()
 
1304
        self.assertContainsRe(branch_tree.get_parent(), '/parent/$')
 
1305
 
 
1306
 
 
1307
class TestBzrDirHooks(TestCaseWithMemoryTransport):
 
1308
 
 
1309
    def test_pre_open_called(self):
 
1310
        calls = []
 
1311
        bzrdir.BzrDir.hooks.install_named_hook('pre_open', calls.append, None)
 
1312
        transport = self.get_transport('foo')
 
1313
        url = transport.base
 
1314
        self.assertRaises(errors.NotBranchError, bzrdir.BzrDir.open, url)
 
1315
        self.assertEqual([transport.base], [t.base for t in calls])
 
1316
 
 
1317
    def test_pre_open_actual_exceptions_raised(self):
 
1318
        count = [0]
 
1319
        def fail_once(transport):
 
1320
            count[0] += 1
 
1321
            if count[0] == 1:
 
1322
                raise errors.BzrError("fail")
 
1323
        bzrdir.BzrDir.hooks.install_named_hook('pre_open', fail_once, None)
 
1324
        transport = self.get_transport('foo')
 
1325
        url = transport.base
 
1326
        err = self.assertRaises(errors.BzrError, bzrdir.BzrDir.open, url)
 
1327
        self.assertEqual('fail', err._preformatted_string)