~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Vincent Ladeuil
  • Date: 2009-04-08 13:13:30 UTC
  • mfrom: (4202.4.3 348459-wrong-annotation)
  • mto: This revision was merged to the branch mainline in revision 4273.
  • Revision ID: v.ladeuil+lp@free.fr-20090408131330-mx1hq45oarrxia2z
Allows external annotation tie-breakers

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2011 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2008, 2009 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
19
19
 
20
20
import os
21
21
 
22
 
from bzrlib import (
23
 
    branch,
24
 
    bzrdir,
25
 
    errors,
26
 
    revision as _mod_revision,
27
 
    )
 
22
from bzrlib import (branch, bzrdir, errors, repository)
28
23
from bzrlib.repofmt.knitrepo import RepositoryFormatKnit1
29
 
from bzrlib.tests import TestCaseWithTransport
30
 
from bzrlib.tests import (
31
 
    fixtures,
32
 
    HardlinkFeature,
33
 
    script,
34
 
    test_server,
35
 
    )
36
 
from bzrlib.tests.blackbox import test_switch
 
24
from bzrlib.tests.blackbox import ExternalBase
 
25
from bzrlib.tests import HardlinkFeature
37
26
from bzrlib.tests.test_sftp_transport import TestCaseWithSFTPServer
38
 
from bzrlib.tests.script import run_script
39
27
from bzrlib.urlutils import local_path_to_url, strip_trailing_slash
40
28
from bzrlib.workingtree import WorkingTree
41
29
 
42
30
 
43
 
class TestBranch(TestCaseWithTransport):
 
31
class TestBranch(ExternalBase):
44
32
 
45
33
    def example_branch(self, path='.'):
46
34
        tree = self.make_branch_and_tree(path)
61
49
        self.assertFalse(b._transport.has('branch-name'))
62
50
        b.bzrdir.open_workingtree().commit(message='foo', allow_pointless=True)
63
51
 
64
 
    def test_branch_broken_pack(self):
65
 
        """branching with a corrupted pack file."""
66
 
        self.example_branch('a')
67
 
        #now add some random corruption
68
 
        fname = 'a/.bzr/repository/packs/' + os.listdir('a/.bzr/repository/packs')[0]
69
 
        with open(fname, 'rb+') as f:
70
 
            f.seek(750)
71
 
            f.write("\xff")
72
 
        self.run_bzr_error(['Corruption while decompressing repository file'], 
73
 
                            'branch a b', retcode=3)
74
 
 
75
 
    def test_branch_switch_no_branch(self):
76
 
        # No branch in the current directory:
77
 
        #  => new branch will be created, but switch fails
78
 
        self.example_branch('a')
79
 
        self.make_repository('current')
80
 
        self.run_bzr_error(['No WorkingTree exists for'],
81
 
            'branch --switch ../a ../b', working_dir='current')
82
 
        a = branch.Branch.open('a')
83
 
        b = branch.Branch.open('b')
84
 
        self.assertEqual(a.last_revision(), b.last_revision())
85
 
 
86
 
    def test_branch_switch_no_wt(self):
87
 
        # No working tree in the current directory:
88
 
        #  => new branch will be created, but switch fails and the current
89
 
        #     branch is unmodified
90
 
        self.example_branch('a')
91
 
        self.make_branch('current')
92
 
        self.run_bzr_error(['No WorkingTree exists for'],
93
 
            'branch --switch ../a ../b', working_dir='current')
94
 
        a = branch.Branch.open('a')
95
 
        b = branch.Branch.open('b')
96
 
        self.assertEqual(a.last_revision(), b.last_revision())
97
 
        work = branch.Branch.open('current')
98
 
        self.assertEqual(work.last_revision(), _mod_revision.NULL_REVISION)
99
 
 
100
 
    def test_branch_switch_no_checkout(self):
101
 
        # Standalone branch in the current directory:
102
 
        #  => new branch will be created, but switch fails and the current
103
 
        #     branch is unmodified
104
 
        self.example_branch('a')
105
 
        self.make_branch_and_tree('current')
106
 
        self.run_bzr_error(['Cannot switch a branch, only a checkout'],
107
 
            'branch --switch ../a ../b', working_dir='current')
108
 
        a = branch.Branch.open('a')
109
 
        b = branch.Branch.open('b')
110
 
        self.assertEqual(a.last_revision(), b.last_revision())
111
 
        work = branch.Branch.open('current')
112
 
        self.assertEqual(work.last_revision(), _mod_revision.NULL_REVISION)
113
 
 
114
 
    def test_branch_switch_checkout(self):
115
 
        # Checkout in the current directory:
116
 
        #  => new branch will be created and checkout bound to the new branch
117
 
        self.example_branch('a')
118
 
        self.run_bzr('checkout a current')
119
 
        out, err = self.run_bzr('branch --switch ../a ../b', working_dir='current')
120
 
        a = branch.Branch.open('a')
121
 
        b = branch.Branch.open('b')
122
 
        self.assertEqual(a.last_revision(), b.last_revision())
123
 
        work = WorkingTree.open('current')
124
 
        self.assertEndsWith(work.branch.get_bound_location(), '/b/')
125
 
        self.assertContainsRe(err, "Switched to branch: .*/b/")
126
 
 
127
 
    def test_branch_switch_lightweight_checkout(self):
128
 
        # Lightweight checkout in the current directory:
129
 
        #  => new branch will be created and lightweight checkout pointed to
130
 
        #     the new branch
131
 
        self.example_branch('a')
132
 
        self.run_bzr('checkout --lightweight a current')
133
 
        out, err = self.run_bzr('branch --switch ../a ../b', working_dir='current')
134
 
        a = branch.Branch.open('a')
135
 
        b = branch.Branch.open('b')
136
 
        self.assertEqual(a.last_revision(), b.last_revision())
137
 
        work = WorkingTree.open('current')
138
 
        self.assertEndsWith(work.branch.base, '/b/')
139
 
        self.assertContainsRe(err, "Switched to branch: .*/b/")
140
 
 
141
52
    def test_branch_only_copies_history(self):
142
53
        # Knit branches should only push the history for the current revision.
143
54
        format = bzrdir.BzrDirMetaFormat1()
182
93
        self.build_tree(['source/file1'])
183
94
        source.add('file1')
184
95
        source.commit('added file')
185
 
        out, err = self.run_bzr(['branch', 'source', 'target', '--hardlink'])
 
96
        self.run_bzr(['branch', 'source', 'target', '--hardlink'])
186
97
        source_stat = os.stat('source/file1')
187
98
        target_stat = os.stat('target/file1')
188
99
        self.assertEqual(source_stat, target_stat)
189
100
 
190
 
    def test_branch_files_from(self):
191
 
        source = self.make_branch_and_tree('source')
192
 
        self.build_tree(['source/file1'])
193
 
        source.add('file1')
194
 
        source.commit('added file')
195
 
        out, err = self.run_bzr('branch source target --files-from source')
196
 
        self.assertPathExists('target/file1')
197
 
 
198
 
    def test_branch_files_from_hardlink(self):
199
 
        self.requireFeature(HardlinkFeature)
200
 
        source = self.make_branch_and_tree('source')
201
 
        self.build_tree(['source/file1'])
202
 
        source.add('file1')
203
 
        source.commit('added file')
204
 
        source.bzrdir.sprout('second')
205
 
        out, err = self.run_bzr('branch source target --files-from second'
206
 
                                ' --hardlink')
207
 
        source_stat = os.stat('source/file1')
208
 
        second_stat = os.stat('second/file1')
209
 
        target_stat = os.stat('target/file1')
210
 
        self.assertNotEqual(source_stat, target_stat)
211
 
        self.assertEqual(second_stat, target_stat)
212
 
 
213
101
    def test_branch_standalone(self):
214
102
        shared_repo = self.make_repository('repo', shared=True)
215
103
        self.example_branch('source')
222
110
    def test_branch_no_tree(self):
223
111
        self.example_branch('source')
224
112
        self.run_bzr('branch --no-tree source target')
225
 
        self.assertPathDoesNotExist('target/hello')
226
 
        self.assertPathDoesNotExist('target/goodbye')
227
 
 
228
 
    def test_branch_into_existing_dir(self):
229
 
        self.example_branch('a')
230
 
        # existing dir with similar files but no .bzr dir
231
 
        self.build_tree_contents([('b/',)])
232
 
        self.build_tree_contents([('b/hello', 'bar')])  # different content
233
 
        self.build_tree_contents([('b/goodbye', 'baz')])# same content
234
 
        # fails without --use-existing-dir
235
 
        out,err = self.run_bzr('branch a b', retcode=3)
236
 
        self.assertEqual('', out)
237
 
        self.assertEqual('bzr: ERROR: Target directory "b" already exists.\n',
238
 
            err)
239
 
        # force operation
240
 
        self.run_bzr('branch a b --use-existing-dir')
241
 
        # check conflicts
242
 
        self.assertPathExists('b/hello.moved')
243
 
        self.assertPathDoesNotExist('b/godbye.moved')
244
 
        # we can't branch into branch
245
 
        out,err = self.run_bzr('branch a b --use-existing-dir', retcode=3)
246
 
        self.assertEqual('', out)
247
 
        self.assertEqual('bzr: ERROR: Already a branch: "b".\n', err)
248
 
 
249
 
    def test_branch_bind(self):
250
 
        self.example_branch('a')
251
 
        out, err = self.run_bzr('branch a b --bind')
252
 
        self.assertEndsWith(err, "New branch bound to a\n")
253
 
        b = branch.Branch.open('b')
254
 
        self.assertEndsWith(b.get_bound_location(), '/a/')
255
 
 
256
 
    def test_branch_with_post_branch_init_hook(self):
257
 
        calls = []
258
 
        branch.Branch.hooks.install_named_hook('post_branch_init',
259
 
            calls.append, None)
260
 
        self.assertLength(0, calls)
261
 
        self.example_branch('a')
262
 
        self.assertLength(1, calls)
263
 
        self.run_bzr('branch a b')
264
 
        self.assertLength(2, calls)
265
 
 
266
 
    def test_checkout_with_post_branch_init_hook(self):
267
 
        calls = []
268
 
        branch.Branch.hooks.install_named_hook('post_branch_init',
269
 
            calls.append, None)
270
 
        self.assertLength(0, calls)
271
 
        self.example_branch('a')
272
 
        self.assertLength(1, calls)
273
 
        self.run_bzr('checkout a b')
274
 
        self.assertLength(2, calls)
275
 
 
276
 
    def test_lightweight_checkout_with_post_branch_init_hook(self):
277
 
        calls = []
278
 
        branch.Branch.hooks.install_named_hook('post_branch_init',
279
 
            calls.append, None)
280
 
        self.assertLength(0, calls)
281
 
        self.example_branch('a')
282
 
        self.assertLength(1, calls)
283
 
        self.run_bzr('checkout --lightweight a b')
284
 
        self.assertLength(2, calls)
285
 
 
286
 
    def test_branch_fetches_all_tags(self):
287
 
        builder = self.make_branch_builder('source')
288
 
        source = fixtures.build_branch_with_non_ancestral_rev(builder)
289
 
        source.tags.set_tag('tag-a', 'rev-2')
290
 
        # Now source has a tag not in its ancestry.  Make a branch from it.
291
 
        self.run_bzr('branch source new-branch')
292
 
        new_branch = branch.Branch.open('new-branch')
293
 
        # The tag is present, and so is its revision.
294
 
        self.assertEqual('rev-2', new_branch.tags.lookup_tag('tag-a'))
295
 
        new_branch.repository.get_revision('rev-2')
296
 
 
297
 
 
298
 
class TestBranchStacked(TestCaseWithTransport):
 
113
        self.failIfExists('target/hello')
 
114
        self.failIfExists('target/goodbye')
 
115
 
 
116
 
 
117
class TestBranchStacked(ExternalBase):
299
118
    """Tests for branch --stacked"""
300
119
 
 
120
    def check_shallow_branch(self, branch_revid, stacked_on):
 
121
        """Assert that the branch 'newbranch' has been published correctly.
 
122
 
 
123
        :param stacked_on: url of a branch this one is stacked upon.
 
124
        :param branch_revid: a revision id that should be the only
 
125
            revision present in the stacked branch, and it should not be in
 
126
            the reference branch.
 
127
        """
 
128
        new_branch = branch.Branch.open('newbranch')
 
129
        # The branch refers to the mainline
 
130
        self.assertEqual(stacked_on, new_branch.get_stacked_on_url())
 
131
        # and the branch's work was pushed
 
132
        self.assertTrue(new_branch.repository.has_revision(branch_revid))
 
133
        # The newly committed revision shoud be present in the stacked branch,
 
134
        # but not in the stacked-on branch.  Because stacking is set up by the
 
135
        # branch object, if we open the stacked branch's repository directly,
 
136
        # bypassing the branch, we see only what's in the stacked repository.
 
137
        stacked_repo = bzrdir.BzrDir.open('newbranch').open_repository()
 
138
        stacked_repo_revisions = set(stacked_repo.all_revision_ids())
 
139
        if len(stacked_repo_revisions) != 1:
 
140
            self.fail("wrong revisions in stacked repository: %r"
 
141
                % (stacked_repo_revisions,))
 
142
 
301
143
    def assertRevisionInRepository(self, repo_path, revid):
302
144
        """Check that a revision is in a repository, disregarding stacking."""
303
145
        repo = bzrdir.BzrDir.open(repo_path).open_repository()
324
166
            format='1.9')
325
167
        branch_tree.branch.set_stacked_on_url(trunk_tree.branch.base)
326
168
        # with some work on it
327
 
        work_tree = trunk_tree.branch.bzrdir.sprout('local').open_workingtree()
328
 
        work_tree.commit('moar work plz')
329
 
        work_tree.branch.push(branch_tree.branch)
 
169
        branch_tree.commit('moar work plz')
330
170
        # branching our local branch gives us a new stacked branch pointing at
331
171
        # mainline.
332
172
        out, err = self.run_bzr(['branch', 'branch', 'newbranch'])
333
173
        self.assertEqual('', out)
334
 
        self.assertEqual('Branched 2 revision(s).\n',
 
174
        self.assertEqual('Branched 1 revision(s).\n',
335
175
            err)
336
176
        # it should have preserved the branch format, and so it should be
337
177
        # capable of supporting stacking, but not actually have a stacked_on
350
190
            format='1.9')
351
191
        branch_tree.branch.set_stacked_on_url(trunk_tree.branch.base)
352
192
        # with some work on it
353
 
        work_tree = trunk_tree.branch.bzrdir.sprout('local').open_workingtree()
354
 
        branch_revid = work_tree.commit('moar work plz')
355
 
        work_tree.branch.push(branch_tree.branch)
 
193
        branch_revid = branch_tree.commit('moar work plz')
356
194
        # you can chain branches on from there
357
195
        out, err = self.run_bzr(['branch', 'branch', '--stacked', 'branch2'])
358
196
        self.assertEqual('', out)
361
199
        self.assertEqual(branch_tree.branch.base,
362
200
            branch.Branch.open('branch2').get_stacked_on_url())
363
201
        branch2_tree = WorkingTree.open('branch2')
364
 
        branch2_revid = work_tree.commit('work on second stacked branch')
365
 
        work_tree.branch.push(branch2_tree.branch)
 
202
        branch2_revid = branch2_tree.commit('work on second stacked branch')
366
203
        self.assertRevisionInRepository('branch2', branch2_revid)
367
204
        self.assertRevisionsInBranchRepository(
368
205
            [trunk_revid, branch_revid, branch2_revid],
381
218
        self.assertEqual('Created new stacked branch referring to %s.\n' %
382
219
            trunk_tree.branch.base, err)
383
220
        self.assertRevisionNotInRepository('newbranch', original_revid)
384
 
        new_branch = branch.Branch.open('newbranch')
385
 
        self.assertEqual(trunk_tree.branch.base, new_branch.get_stacked_on_url())
 
221
        new_tree = WorkingTree.open('newbranch')
 
222
        new_revid = new_tree.commit('new work')
 
223
        self.check_shallow_branch(new_revid, trunk_tree.branch.base)
386
224
 
387
225
    def test_branch_stacked_from_smart_server(self):
388
226
        # We can branch stacking on a smart server
389
 
        self.transport_server = test_server.SmartTCPServer_for_testing
 
227
        from bzrlib.smart.server import SmartTCPServer_for_testing
 
228
        self.transport_server = SmartTCPServer_for_testing
390
229
        trunk = self.make_branch('mainline', format='1.9')
391
230
        out, err = self.run_bzr(
392
231
            ['branch', '--stacked', self.get_url('mainline'), 'shallow'])
398
237
            ['branch', '--stacked', 'trunk', 'shallow'])
399
238
        # We should notify the user that we upgraded their format
400
239
        self.assertEqualDiff(
401
 
            'Source repository format does not support stacking, using format:\n'
 
240
            'Source format does not support stacking, using format: \'1.6\'\n'
402
241
            '  Packs 5 (adds stacking support, requires bzr 1.6)\n'
403
 
            'Source branch format does not support stacking, using format:\n'
404
 
            '  Branch format 7\n'
405
 
            'Doing on-the-fly conversion from RepositoryFormatKnitPack1() to RepositoryFormatKnitPack5().\n'
406
 
            'This may take some time. Upgrade the repositories to the same format for better performance.\n'
 
242
            '\n'
407
243
            'Created new stacked branch referring to %s.\n' % (trunk.base,),
408
244
            err)
409
245
 
413
249
            ['branch', '--stacked', 'trunk', 'shallow'])
414
250
        # We should notify the user that we upgraded their format
415
251
        self.assertEqualDiff(
416
 
            'Source repository format does not support stacking, using format:\n'
 
252
            'Source format does not support stacking, using format:'
 
253
            ' \'1.6.1-rich-root\'\n'
417
254
            '  Packs 5 rich-root (adds stacking support, requires bzr 1.6.1)\n'
418
 
            'Source branch format does not support stacking, using format:\n'
419
 
            '  Branch format 7\n'
420
 
            'Doing on-the-fly conversion from RepositoryFormatKnitPack4() to RepositoryFormatKnitPack5RichRoot().\n'
421
 
            'This may take some time. Upgrade the repositories to the same format for better performance.\n'
 
255
            '\n'
422
256
            'Created new stacked branch referring to %s.\n' % (trunk.base,),
423
257
            err)
424
258
 
425
259
 
426
 
class TestSmartServerBranching(TestCaseWithTransport):
 
260
class TestSmartServerBranching(ExternalBase):
427
261
 
428
262
    def test_branch_from_trivial_branch_to_same_server_branch_acceptance(self):
429
263
        self.setup_smart_server_with_call_log()
438
272
        # being too low. If rpc_count increases, more network roundtrips have
439
273
        # become necessary for this use case. Please do not adjust this number
440
274
        # upwards without agreement from bzr's network support maintainers.
441
 
        self.assertLength(36, self.hpss_calls)
 
275
        self.assertLength(53, self.hpss_calls)
442
276
 
443
277
    def test_branch_from_trivial_branch_streaming_acceptance(self):
444
278
        self.setup_smart_server_with_call_log()
453
287
        # being too low. If rpc_count increases, more network roundtrips have
454
288
        # become necessary for this use case. Please do not adjust this number
455
289
        # upwards without agreement from bzr's network support maintainers.
456
 
        self.assertLength(9, self.hpss_calls)
 
290
        self.assertLength(10, self.hpss_calls)
457
291
 
458
292
    def test_branch_from_trivial_stacked_branch_streaming_acceptance(self):
459
293
        self.setup_smart_server_with_call_log()
462
296
            t.commit(message='commit %d' % count)
463
297
        tree2 = t.branch.bzrdir.sprout('feature', stacked=True
464
298
            ).open_workingtree()
465
 
        local_tree = t.branch.bzrdir.sprout('local-working').open_workingtree()
466
 
        local_tree.commit('feature change')
467
 
        local_tree.branch.push(tree2.branch)
 
299
        tree2.commit('feature change')
468
300
        self.reset_smart_call_log()
469
301
        out, err = self.run_bzr(['branch', self.get_url('feature'),
470
302
            'local-target'])
473
305
        # being too low. If rpc_count increases, more network roundtrips have
474
306
        # become necessary for this use case. Please do not adjust this number
475
307
        # upwards without agreement from bzr's network support maintainers.
476
 
        self.assertLength(14, self.hpss_calls)
477
 
 
478
 
    def test_branch_from_branch_with_tags(self):
479
 
        self.setup_smart_server_with_call_log()
480
 
        builder = self.make_branch_builder('source')
481
 
        source = fixtures.build_branch_with_non_ancestral_rev(builder)
482
 
        source.tags.set_tag('tag-a', 'rev-2')
483
 
        source.tags.set_tag('tag-missing', 'missing-rev')
484
 
        # Now source has a tag not in its ancestry.  Make a branch from it.
485
 
        self.reset_smart_call_log()
486
 
        out, err = self.run_bzr(['branch', self.get_url('source'), 'target'])
487
 
        # This figure represent the amount of work to perform this use case. It
488
 
        # is entirely ok to reduce this number if a test fails due to rpc_count
489
 
        # being too low. If rpc_count increases, more network roundtrips have
490
 
        # become necessary for this use case. Please do not adjust this number
491
 
        # upwards without agreement from bzr's network support maintainers.
492
 
        self.assertLength(9, self.hpss_calls)
493
 
 
494
 
    def test_branch_to_stacked_from_trivial_branch_streaming_acceptance(self):
495
 
        self.setup_smart_server_with_call_log()
496
 
        t = self.make_branch_and_tree('from')
497
 
        for count in range(9):
498
 
            t.commit(message='commit %d' % count)
499
 
        self.reset_smart_call_log()
500
 
        out, err = self.run_bzr(['branch', '--stacked', self.get_url('from'),
501
 
            'local-target'])
502
 
        # XXX: the number of hpss calls for this case isn't deterministic yet,
503
 
        # so we can't easily assert about the number of calls.
504
 
        #self.assertLength(XXX, self.hpss_calls)
505
 
        # We can assert that none of the calls were readv requests for rix
506
 
        # files, though (demonstrating that at least get_parent_map calls are
507
 
        # not using VFS RPCs).
508
 
        readvs_of_rix_files = [
509
 
            c for c in self.hpss_calls
510
 
            if c.call.method == 'readv' and c.call.args[-1].endswith('.rix')]
511
 
        self.assertLength(0, readvs_of_rix_files)
 
308
        self.assertLength(15, self.hpss_calls)
512
309
 
513
310
 
514
311
class TestRemoteBranch(TestCaseWithSFTPServer):
534
331
        # Ensure that no working tree what created remotely
535
332
        self.assertFalse(t.has('remote/file'))
536
333
 
537
 
 
538
 
class TestDeprecatedAliases(TestCaseWithTransport):
539
 
 
540
 
    def test_deprecated_aliases(self):
541
 
        """bzr branch can be called clone or get, but those names are deprecated.
542
 
 
543
 
        See bug 506265.
544
 
        """
545
 
        for command in ['clone', 'get']:
546
 
            run_script(self, """
547
 
            $ bzr %(command)s A B
548
 
            2>The command 'bzr %(command)s' has been deprecated in bzr 2.4. Please use 'bzr branch' instead.
549
 
            2>bzr: ERROR: Not a branch...
550
 
            """ % locals())
551
 
 
552
 
 
553
 
class TestBranchParentLocation(test_switch.TestSwitchParentLocationBase):
554
 
 
555
 
    def _checkout_and_branch(self, option=''):
556
 
        self.script_runner.run_script(self, '''
557
 
                $ bzr checkout %(option)s repo/trunk checkout
558
 
                $ cd checkout
559
 
                $ bzr branch --switch ../repo/trunk ../repo/branched
560
 
                2>Branched 0 revision(s).
561
 
                2>Tree is up to date at revision 0.
562
 
                2>Switched to branch:...branched...
563
 
                $ cd ..
564
 
                ''' % locals())
565
 
        bound_branch = branch.Branch.open_containing('checkout')[0]
566
 
        master_branch = branch.Branch.open_containing('repo/branched')[0]
567
 
        return (bound_branch, master_branch)
568
 
 
569
 
    def test_branch_switch_parent_lightweight(self):
570
 
        """Lightweight checkout using bzr branch --switch."""
571
 
        bb, mb = self._checkout_and_branch(option='--lightweight')
572
 
        self.assertParent('repo/trunk', bb)
573
 
        self.assertParent('repo/trunk', mb)
574
 
 
575
 
    def test_branch_switch_parent_heavyweight(self):
576
 
        """Heavyweight checkout using bzr branch --switch."""
577
 
        bb, mb = self._checkout_and_branch()
578
 
        self.assertParent('repo/trunk', bb)
579
 
        self.assertParent('repo/trunk', mb)