/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/per_branch/test_branch.py

Merge bzr.dev, update to use new hooks.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2005-2011 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
24
24
    errors,
25
25
    gpg,
26
26
    merge,
 
27
    osutils,
27
28
    urlutils,
28
 
    transactions,
29
29
    transport,
30
30
    remote,
31
31
    repository,
32
32
    revision,
 
33
    symbol_versioning,
33
34
    tests,
34
35
    )
35
 
from bzrlib.symbol_versioning import deprecated_in
36
36
from bzrlib.tests import (
37
 
    http_server,
38
37
    per_branch,
39
38
    )
40
39
from bzrlib.tests.http_server import HttpServer
77
76
 
78
77
        br = self.get_branch()
79
78
        br.fetch(wt.branch)
80
 
        br.set_revision_history(['rev1', 'rev2', 'rev3'])
81
 
        rh = br.revision_history()
82
 
        self.assertEqual(['rev1', 'rev2', 'rev3'], rh)
83
 
        for revision_id in rh:
 
79
        br.generate_revision_history('rev3')
 
80
        for revision_id in ['rev3', 'rev2', 'rev1']:
84
81
            self.assertIsInstance(revision_id, str)
85
82
        last = br.last_revision()
86
83
        self.assertEqual('rev3', last)
116
113
        tree_a.add('vla', 'file2')
117
114
        tree_a.commit('rev2', rev_id='rev2')
118
115
 
119
 
        delta = tree_a.branch.get_revision_delta(1)
 
116
        delta = self.applyDeprecated(symbol_versioning.deprecated_in(
 
117
            (2, 5, 0)), tree_a.branch.get_revision_delta, 1)
120
118
        self.assertIsInstance(delta, _mod_delta.TreeDelta)
121
119
        self.assertEqual([('foo', 'file1', 'file')], delta.added)
122
 
        delta = tree_a.branch.get_revision_delta(2)
 
120
        delta = self.applyDeprecated(symbol_versioning.deprecated_in(
 
121
            (2, 5, 0)), tree_a.branch.get_revision_delta, 2)
123
122
        self.assertIsInstance(delta, _mod_delta.TreeDelta)
124
123
        self.assertEqual([('vla', 'file2', 'file')], delta.added)
125
124
 
187
186
        self.assertEqual(branch_b.get_parent(), branch_c.get_parent())
188
187
 
189
188
        # We can also set a specific parent, and it should be honored
190
 
        random_parent = 'http://bazaar-vcs.org/path/to/branch'
 
189
        random_parent = 'http://example.com/path/to/branch'
191
190
        branch_b.set_parent(random_parent)
192
191
        repo_d = self.make_repository('d')
193
192
        branch_b.repository.copy_content_into(repo_d)
217
216
    def test_record_initial_ghost(self):
218
217
        """Branches should support having ghosts."""
219
218
        wt = self.make_branch_and_tree('.')
 
219
        if not wt.branch.repository._format.supports_ghosts:
 
220
            raise tests.TestNotApplicable("repository format does not "
 
221
                "support ghosts")
220
222
        wt.set_parent_ids(['non:existent@rev--ision--0--2'],
221
223
            allow_leftmost_as_ghost=True)
222
224
        self.assertEqual(['non:existent@rev--ision--0--2'],
230
232
    def test_record_two_ghosts(self):
231
233
        """Recording with all ghosts works."""
232
234
        wt = self.make_branch_and_tree('.')
 
235
        if not wt.branch.repository._format.supports_ghosts:
 
236
            raise tests.TestNotApplicable("repository format does not "
 
237
                "support ghosts")
233
238
        wt.set_parent_ids([
234
239
                'foo@azkhazan-123123-abcabc',
235
240
                'wibble@fofof--20050401--1928390812',
247
252
                          self.get_branch().repository.get_revision,
248
253
                          None)
249
254
 
250
 
# TODO 20051003 RBC:
251
 
# compare the gpg-to-sign info for a commit with a ghost and
252
 
#     an identical tree without a ghost
253
 
# fetch missing should rewrite the TOC of weaves to list newly available parents.
254
 
 
255
 
    def test_sign_existing_revision(self):
256
 
        wt = self.make_branch_and_tree('.')
257
 
        branch = wt.branch
258
 
        wt.commit("base", allow_pointless=True, rev_id='A')
259
 
        from bzrlib.testament import Testament
260
 
        strategy = gpg.LoopbackGPGStrategy(None)
261
 
        branch.repository.lock_write()
262
 
        branch.repository.start_write_group()
263
 
        branch.repository.sign_revision('A', strategy)
264
 
        branch.repository.commit_write_group()
265
 
        branch.repository.unlock()
266
 
        self.assertEqual('-----BEGIN PSEUDO-SIGNED CONTENT-----\n' +
267
 
                         Testament.from_revision(branch.repository,
268
 
                         'A').as_short_text() +
269
 
                         '-----END PSEUDO-SIGNED CONTENT-----\n',
270
 
                         branch.repository.get_signature_text('A'))
271
 
 
272
 
    def test_store_signature(self):
273
 
        wt = self.make_branch_and_tree('.')
274
 
        branch = wt.branch
275
 
        branch.lock_write()
276
 
        try:
277
 
            branch.repository.start_write_group()
278
 
            try:
279
 
                branch.repository.store_revision_signature(
280
 
                    gpg.LoopbackGPGStrategy(None), 'FOO', 'A')
281
 
            except:
282
 
                branch.repository.abort_write_group()
283
 
                raise
284
 
            else:
285
 
                branch.repository.commit_write_group()
286
 
        finally:
287
 
            branch.unlock()
288
 
        # A signature without a revision should not be accessible.
289
 
        self.assertRaises(errors.NoSuchRevision,
290
 
                          branch.repository.has_signature_for_revision_id,
291
 
                          'A')
292
 
        wt.commit("base", allow_pointless=True, rev_id='A')
293
 
        self.assertEqual('-----BEGIN PSEUDO-SIGNED CONTENT-----\n'
294
 
                         'FOO-----END PSEUDO-SIGNED CONTENT-----\n',
295
 
                         branch.repository.get_signature_text('A'))
296
 
 
297
 
    def test_branch_keeps_signatures(self):
298
 
        wt = self.make_branch_and_tree('source')
299
 
        wt.commit('A', allow_pointless=True, rev_id='A')
300
 
        repo = wt.branch.repository
301
 
        repo.lock_write()
302
 
        repo.start_write_group()
303
 
        repo.sign_revision('A', gpg.LoopbackGPGStrategy(None))
304
 
        repo.commit_write_group()
305
 
        repo.unlock()
306
 
        #FIXME: clone should work to urls,
307
 
        # wt.clone should work to disks.
308
 
        self.build_tree(['target/'])
309
 
        d2 = repo.bzrdir.clone(urlutils.local_path_to_url('target'))
310
 
        self.assertEqual(repo.get_signature_text('A'),
311
 
                         d2.open_repository().get_signature_text('A'))
312
 
 
313
 
    def test_missing_revisions(self):
314
 
        t1 = self.make_branch_and_tree('b1')
315
 
        rev1 = t1.commit('one')
316
 
        t2 = t1.bzrdir.sprout('b2').open_workingtree()
317
 
        rev2 = t1.commit('two')
318
 
        rev3 = t1.commit('three')
319
 
 
320
 
        self.assertEqual([rev2, rev3],
321
 
            self.applyDeprecated(deprecated_in((1, 6, 0)),
322
 
            t2.branch.missing_revisions, t1.branch))
323
 
 
324
 
        self.assertEqual([],
325
 
            self.applyDeprecated(deprecated_in((1, 6, 0)),
326
 
            t2.branch.missing_revisions, t1.branch, stop_revision=1))
327
 
        self.assertEqual([rev2],
328
 
            self.applyDeprecated(deprecated_in((1, 6, 0)),
329
 
            t2.branch.missing_revisions, t1.branch, stop_revision=2))
330
 
        self.assertEqual([rev2, rev3],
331
 
            self.applyDeprecated(deprecated_in((1, 6, 0)),
332
 
            t2.branch.missing_revisions, t1.branch, stop_revision=3))
333
 
 
334
 
        self.assertRaises(errors.NoSuchRevision,
335
 
            self.applyDeprecated, deprecated_in((1, 6, 0)),
336
 
            t2.branch.missing_revisions, t1.branch, stop_revision=4)
337
 
 
338
 
        rev4 = t2.commit('four')
339
 
        self.assertRaises(errors.DivergedBranches,
340
 
            self.applyDeprecated, deprecated_in((1, 6, 0)),
341
 
            t2.branch.missing_revisions, t1.branch)
342
 
 
343
 
    def test_nicks(self):
344
 
        """Test explicit and implicit branch nicknames.
 
255
    def test_nicks_bzr(self):
 
256
        """Test the behaviour of branch nicks specific to bzr branches.
345
257
 
346
258
        Nicknames are implicitly the name of the branch's directory, unless an
347
259
        explicit nickname is set.  That is, an explicit nickname always
348
260
        overrides the implicit one.
 
261
 
349
262
        """
350
 
        t = transport.get_transport(self.get_url())
 
263
        t = self.get_transport()
351
264
        branch = self.make_branch('bzr.dev')
 
265
        if not isinstance(branch, _mod_branch.BzrBranch):
 
266
            raise tests.TestNotApplicable("not a bzr branch format")
352
267
        # The nick will be 'bzr.dev', because there is no explicit nick set.
353
268
        self.assertEqual(branch.nick, 'bzr.dev')
354
269
        # Move the branch to a different directory, 'bzr.ab'.  Now that branch
360
275
        # config file in the branch.
361
276
        branch.nick = "Aaron's branch"
362
277
        if not isinstance(branch, remote.RemoteBranch):
363
 
            self.failUnless(branch._transport.has("branch.conf"))
 
278
            self.assertTrue(branch._transport.has("branch.conf"))
364
279
        # Because the nick has been set explicitly, the nick is now always
365
280
        # "Aaron's branch", regardless of directory name.
366
281
        self.assertEqual(branch.nick, "Aaron's branch")
370
285
        branch.nick = u"\u1234"
371
286
        self.assertEqual(branch.nick, u"\u1234")
372
287
 
 
288
    def test_nicks(self):
 
289
        """Test explicit and implicit branch nicknames.
 
290
 
 
291
        A nickname is always available, whether set explicitly or not.
 
292
        """
 
293
        t = self.get_transport()
 
294
        branch = self.make_branch('bzr.dev')
 
295
        # An implicit nick name is set; what it is exactly depends on the
 
296
        # format.
 
297
        self.assertIsInstance(branch.nick, basestring)
 
298
        # Set the branch nick explicitly.
 
299
        branch.nick = "Aaron's branch"
 
300
        # Because the nick has been set explicitly, the nick is now always
 
301
        # "Aaron's branch".
 
302
        self.assertEqual(branch.nick, "Aaron's branch")
 
303
        branch.nick = u"\u1234"
 
304
        self.assertEqual(branch.nick, u"\u1234")
 
305
 
373
306
    def test_commit_nicks(self):
374
307
        """Nicknames are committed to the revision"""
375
308
        wt = self.make_branch_and_tree('bzr.dev')
397
330
        self.branch_format.initialize(repo.bzrdir, name='branch2')
398
331
        self.assertEquals(2, len(repo.bzrdir.list_branches()))
399
332
 
 
333
    def test_create_append_revisions_only(self):
 
334
        try:
 
335
            repo = self.make_repository('.', shared=True)
 
336
        except errors.IncompatibleFormat:
 
337
            return
 
338
        for val in (True, False):
 
339
            try:
 
340
                branch = self.branch_format.initialize(repo.bzrdir,
 
341
                    append_revisions_only=True)
 
342
            except (errors.UninitializableFormat, errors.UpgradeRequired):
 
343
                # branch references are not default init'able and
 
344
                # not all branches support append_revisions_only
 
345
                return
 
346
            self.assertEquals(True, branch.get_append_revisions_only())
 
347
            repo.bzrdir.destroy_branch()
 
348
 
 
349
    def test_get_set_append_revisions_only(self):
 
350
        branch = self.make_branch('.')
 
351
        if branch._format.supports_set_append_revisions_only():
 
352
            branch.set_append_revisions_only(True)
 
353
            self.assertTrue(branch.get_append_revisions_only())
 
354
            branch.set_append_revisions_only(False)
 
355
            self.assertFalse(branch.get_append_revisions_only())
 
356
        else:
 
357
            self.assertRaises(errors.UpgradeRequired,
 
358
                branch.set_append_revisions_only, True)
 
359
            self.assertFalse(branch.get_append_revisions_only())
 
360
 
400
361
    def test_create_open_branch_uses_repository(self):
401
362
        try:
402
363
            repo = self.make_repository('.', shared=True)
403
364
        except errors.IncompatibleFormat:
404
 
            return
 
365
            raise tests.TestNotApplicable("requires shared repository support")
405
366
        child_transport = repo.bzrdir.root_transport.clone('child')
406
367
        child_transport.mkdir('.')
407
 
        child_dir = self.bzrdir_format.initialize_on_transport(child_transport)
 
368
        try:
 
369
            child_dir = self.bzrdir_format.initialize_on_transport(child_transport)
 
370
        except errors.UninitializableFormat:
 
371
            raise tests.TestNotApplicable("control dir format not initializable")
408
372
        try:
409
373
            child_branch = self.branch_format.initialize(child_dir)
410
374
        except errors.UninitializableFormat:
419
383
    def test_format_description(self):
420
384
        tree = self.make_branch_and_tree('tree')
421
385
        text = tree.branch._format.get_format_description()
422
 
        self.failUnless(len(text))
 
386
        self.assertTrue(len(text))
423
387
 
424
388
    def test_get_commit_builder(self):
425
389
        branch = self.make_branch(".")
433
397
        """Create a fake revision history easily."""
434
398
        tree = self.make_branch_and_tree('.')
435
399
        rev1 = tree.commit('foo')
436
 
        orig_history = tree.branch.revision_history()
 
400
        tree.lock_write()
 
401
        self.addCleanup(tree.unlock)
 
402
        graph = tree.branch.repository.get_graph()
 
403
        orig_history = list(
 
404
            graph.iter_lefthand_ancestry(
 
405
                tree.branch.last_revision(), [revision.NULL_REVISION]))
437
406
        rev2 = tree.commit('bar', allow_pointless=True)
438
407
        tree.branch.generate_revision_history(rev1)
439
 
        self.assertEqual(orig_history, tree.branch.revision_history())
 
408
        self.assertEqual(orig_history, list(
 
409
            graph.iter_lefthand_ancestry(
 
410
                tree.branch.last_revision(), [revision.NULL_REVISION])))
440
411
 
441
412
    def test_generate_revision_history_NULL_REVISION(self):
442
413
        tree = self.make_branch_and_tree('.')
443
414
        rev1 = tree.commit('foo')
 
415
        tree.lock_write()
 
416
        self.addCleanup(tree.unlock)
444
417
        tree.branch.generate_revision_history(revision.NULL_REVISION)
445
 
        self.assertEqual([], tree.branch.revision_history())
 
418
        self.assertEqual(revision.NULL_REVISION, tree.branch.last_revision())
446
419
 
447
420
    def test_create_checkout(self):
448
421
        tree_a = self.make_branch_and_tree('a')
469
442
        tree_a = self.make_branch_and_tree('a')
470
443
        rev_id = tree_a.commit('put some content in the branch')
471
444
        # open the branch via a readonly transport
472
 
        source_branch = _mod_branch.Branch.open(self.get_readonly_url('a'))
 
445
        url = self.get_readonly_url(urlutils.basename(tree_a.branch.base))
 
446
        t = transport.get_transport_from_url(url)
 
447
        if not tree_a.branch.bzrdir._format.supports_transport(t):
 
448
            raise tests.TestNotApplicable("format does not support transport")
 
449
        source_branch = _mod_branch.Branch.open(url)
473
450
        # sanity check that the test will be valid
474
451
        self.assertRaises((errors.LockError, errors.TransportNotPossible),
475
452
            source_branch.lock_write)
481
458
        tree_a = self.make_branch_and_tree('a')
482
459
        rev_id = tree_a.commit('put some content in the branch')
483
460
        # open the branch via a readonly transport
484
 
        source_branch = _mod_branch.Branch.open(self.get_readonly_url('a'))
 
461
        url = self.get_readonly_url(
 
462
            osutils.basename(tree_a.branch.base.rstrip('/')))
 
463
        t = transport.get_transport_from_url(url)
 
464
        if not tree_a.branch.bzrdir._format.supports_transport(t):
 
465
            raise tests.TestNotApplicable("format does not support transport")
 
466
        source_branch = _mod_branch.Branch.open(url)
485
467
        # sanity check that the test will be valid
486
468
        self.assertRaises((errors.LockError, errors.TransportNotPossible),
487
469
            source_branch.lock_write)
492
474
        tree = self.make_branch_and_tree('a')
493
475
        tree.commit('a commit', rev_id='rev1')
494
476
        br = tree.branch
495
 
        br.set_revision_history(["rev1"])
496
 
        self.assertEquals(br.revision_history(), ["rev1"])
497
 
        br.set_revision_history([])
498
 
        self.assertEquals(br.revision_history(), [])
 
477
        self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
 
478
            br.set_revision_history, ["rev1"])
 
479
        self.assertEquals(br.last_revision(), "rev1")
 
480
        self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
 
481
            br.set_revision_history, [])
 
482
        self.assertEquals(br.last_revision(), 'null:')
 
483
 
 
484
    def test_heads_to_fetch(self):
 
485
        # heads_to_fetch is a method that returns a collection of revids that
 
486
        # need to be fetched to copy this branch into another repo.  At a
 
487
        # minimum this will include the tip.
 
488
        # (In native formats, this is the tip + tags, but other formats may
 
489
        # have other revs needed)
 
490
        tree = self.make_branch_and_tree('a')
 
491
        tree.commit('first commit', rev_id='rev1')
 
492
        tree.commit('second commit', rev_id='rev2')
 
493
        must_fetch, should_fetch = tree.branch.heads_to_fetch()
 
494
        self.assertTrue('rev2' in must_fetch)
 
495
 
 
496
    def test_heads_to_fetch_not_null_revision(self):
 
497
        # NULL_REVISION does not appear in the result of heads_to_fetch, even
 
498
        # for an empty branch.
 
499
        tree = self.make_branch_and_tree('a')
 
500
        must_fetch, should_fetch = tree.branch.heads_to_fetch()
 
501
        self.assertFalse(revision.NULL_REVISION in must_fetch)
 
502
        self.assertFalse(revision.NULL_REVISION in should_fetch)
499
503
 
500
504
 
501
505
class TestBranchFormat(per_branch.TestCaseWithBranch):
519
523
            looked_up_format = registry.get(network_name)
520
524
            self.assertEqual(format.__class__, looked_up_format.__class__)
521
525
 
 
526
    def get_get_config_calls(self):
 
527
        # Smoke test that all branch succeed getting a config
 
528
        br = self.make_branch('.')
 
529
        br.get_config()
 
530
        br.get_config_stack()
 
531
 
522
532
 
523
533
class ChrootedTests(per_branch.TestCaseWithBranch):
524
534
    """A support class that provides readonly urls outside the local namespace.
541
551
                          _mod_branch.Branch.open_containing,
542
552
                          self.get_readonly_url('g/p/q'))
543
553
        branch = self.make_branch('.')
 
554
        if not branch.bzrdir._format.supports_transport(
 
555
            transport.get_transport_from_url(self.get_readonly_url('.'))):
 
556
            raise tests.TestNotApplicable("format does not support transport")
544
557
        branch, relpath = _mod_branch.Branch.open_containing(
545
558
            self.get_readonly_url(''))
546
559
        self.assertEqual('', relpath)
632
645
class TestChildSubmitFormats(per_branch.TestCaseWithBranch):
633
646
 
634
647
    def test_get_child_submit_format_default(self):
635
 
        self.assertEqual(None, self.get_branch().get_child_submit_format())
 
648
        submit_format = self.get_branch().get_child_submit_format()
 
649
        self.assertTrue(submit_format is None or
 
650
                        isinstance(submit_format, str))
636
651
 
637
652
    def test_get_child_submit_format(self):
638
653
        branch = self.get_branch()
682
697
            # they may not be initializable.
683
698
            return
684
699
        # supported formats must be able to init and open
685
 
        t = transport.get_transport(self.get_url())
686
 
        readonly_t = transport.get_transport(self.get_readonly_url())
 
700
        t = self.get_transport()
 
701
        readonly_t = transport.get_transport_from_url(self.get_readonly_url())
687
702
        made_branch = self.make_branch('.')
688
 
        self.failUnless(isinstance(made_branch, _mod_branch.Branch))
 
703
        self.assertIsInstance(made_branch, _mod_branch.Branch)
689
704
 
690
705
        # find it via bzrdir opening:
691
706
        opened_control = bzrdir.BzrDir.open(readonly_t.base)
692
707
        direct_opened_branch = opened_control.open_branch()
693
708
        self.assertEqual(direct_opened_branch.__class__, made_branch.__class__)
694
709
        self.assertEqual(opened_control, direct_opened_branch.bzrdir)
695
 
        self.failUnless(isinstance(direct_opened_branch._format,
696
 
                        self.branch_format.__class__))
 
710
        self.assertIsInstance(direct_opened_branch._format,
 
711
            self.branch_format.__class__)
697
712
 
698
713
        # find it via Branch.open
699
714
        opened_branch = _mod_branch.Branch.open(readonly_t.base)
700
 
        self.failUnless(isinstance(opened_branch, made_branch.__class__))
 
715
        self.assertIsInstance(opened_branch, made_branch.__class__)
701
716
        self.assertEqual(made_branch._format.__class__,
702
717
                         opened_branch._format.__class__)
703
718
        # if it has a unique id string, can we probe for it ?
746
761
        except errors.UpgradeRequired:
747
762
            raise tests.TestNotApplicable('Format does not support binding')
748
763
 
 
764
    def test_unbind_clears_cached_master_branch(self):
 
765
        """b.unbind clears any cached value of b.get_master_branch."""
 
766
        master = self.make_branch('master')
 
767
        branch = self.make_branch('branch')
 
768
        try:
 
769
            branch.bind(master)
 
770
        except errors.UpgradeRequired:
 
771
            raise tests.TestNotApplicable('Format does not support binding')
 
772
        self.addCleanup(branch.lock_write().unlock)
 
773
        self.assertNotEqual(None, branch.get_master_branch())
 
774
        branch.unbind()
 
775
        self.assertEqual(None, branch.get_master_branch())
 
776
 
 
777
    def test_unlocked_does_not_cache_master_branch(self):
 
778
        """Unlocked branches do not cache the result of get_master_branch."""
 
779
        master = self.make_branch('master')
 
780
        branch1 = self.make_branch('branch')
 
781
        try:
 
782
            branch1.bind(master)
 
783
        except errors.UpgradeRequired:
 
784
            raise tests.TestNotApplicable('Format does not support binding')
 
785
        # Open branch1 again
 
786
        branch2 = branch1.bzrdir.open_branch()
 
787
        self.assertNotEqual(None, branch1.get_master_branch())
 
788
        # Unbind the branch via branch2.  branch1 isn't locked so will
 
789
        # immediately return the new value for get_master_branch.
 
790
        branch2.unbind()
 
791
        self.assertEqual(None, branch1.get_master_branch())
 
792
 
 
793
    def test_bind_clears_cached_master_branch(self):
 
794
        """b.bind clears any cached value of b.get_master_branch."""
 
795
        master1 = self.make_branch('master1')
 
796
        master2 = self.make_branch('master2')
 
797
        branch = self.make_branch('branch')
 
798
        try:
 
799
            branch.bind(master1)
 
800
        except errors.UpgradeRequired:
 
801
            raise tests.TestNotApplicable('Format does not support binding')
 
802
        self.addCleanup(branch.lock_write().unlock)
 
803
        self.assertNotEqual(None, branch.get_master_branch())
 
804
        branch.bind(master2)
 
805
        self.assertEqual('.', urlutils.relative_url(self.get_url('master2'),
 
806
                branch.get_master_branch().base))
 
807
 
 
808
    def test_set_bound_location_clears_cached_master_branch(self):
 
809
        """b.set_bound_location clears any cached value of b.get_master_branch.
 
810
        """
 
811
        master1 = self.make_branch('master1')
 
812
        master2 = self.make_branch('master2')
 
813
        branch = self.make_branch('branch')
 
814
        try:
 
815
            branch.bind(master1)
 
816
        except errors.UpgradeRequired:
 
817
            raise tests.TestNotApplicable('Format does not support binding')
 
818
        self.addCleanup(branch.lock_write().unlock)
 
819
        self.assertNotEqual(None, branch.get_master_branch())
 
820
        branch.set_bound_location(self.get_url('master2'))
 
821
        self.assertEqual('.', urlutils.relative_url(self.get_url('master2'),
 
822
                branch.get_master_branch().base))
 
823
 
749
824
 
750
825
class TestStrict(per_branch.TestCaseWithBranch):
751
826
 
785
860
    def test_fallbacks_not_opened(self):
786
861
        stacked = self.make_branch_with_fallback()
787
862
        self.get_transport('').rename('fallback', 'moved')
788
 
        reopened = stacked.bzrdir.open_branch(ignore_fallbacks=True)
 
863
        reopened_dir = bzrdir.BzrDir.open(stacked.base)
 
864
        reopened = reopened_dir.open_branch(ignore_fallbacks=True)
789
865
        self.assertEqual([], reopened.repository._fallback_repositories)
790
866
 
791
867
    def test_fallbacks_are_opened(self):
792
868
        stacked = self.make_branch_with_fallback()
793
 
        reopened = stacked.bzrdir.open_branch(ignore_fallbacks=False)
 
869
        reopened_dir = bzrdir.BzrDir.open(stacked.base)
 
870
        reopened = reopened_dir.open_branch(ignore_fallbacks=False)
794
871
        self.assertLength(1, reopened.repository._fallback_repositories)
795
872
 
796
873
 
804
881
            tree.add_reference(subtree)
805
882
        except errors.UnsupportedOperation:
806
883
            raise tests.TestNotApplicable('Tree cannot hold references.')
807
 
        reference_parent = tree.branch.reference_parent('subtree-id',
808
 
                                                        'subtree')
 
884
        reference_parent = tree.branch.reference_parent(
 
885
            'subtree-id',
 
886
            urlutils.relative_url(tree.branch.user_url, subtree.branch.user_url))
809
887
        self.assertEqual(subtree.branch.base, reference_parent.base)
810
888
 
811
889
    def test_reference_parent_accepts_possible_transports(self):
817
895
        except errors.UnsupportedOperation:
818
896
            raise tests.TestNotApplicable('Tree cannot hold references.')
819
897
        reference_parent = tree.branch.reference_parent('subtree-id',
820
 
            'subtree', possible_transports=[subtree.bzrdir.root_transport])
 
898
            urlutils.relative_url(
 
899
                tree.branch.user_url, subtree.branch.user_url),
 
900
            possible_transports=[subtree.bzrdir.root_transport])
821
901
 
822
902
    def test_get_reference_info(self):
823
903
        branch = self.make_branch('branch')
990
1070
 
991
1071
class TestBranchControlComponent(per_branch.TestCaseWithBranch):
992
1072
    """Branch implementations adequately implement ControlComponent."""
993
 
    
 
1073
 
994
1074
    def test_urls(self):
995
1075
        br = self.make_branch('branch')
996
1076
        self.assertIsInstance(br.user_url, str)