~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Jelmer Vernooij
  • Date: 2012-02-20 14:15:25 UTC
  • mto: (6471.1.4 iter-child-entries)
  • mto: This revision was merged to the branch mainline in revision 6472.
  • Revision ID: jelmer@samba.org-20120220141525-9azkfei62st8yc7w
Use inventories directly in fewer places.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007, 2008, 2009 Canonical Ltd
 
1
# Copyright (C) 2007-2012 Canonical Ltd
2
2
# -*- coding: utf-8 -*-
3
3
#
4
4
# This program is free software; you can redistribute it and/or modify
20
20
 
21
21
import os
22
22
 
 
23
from bzrlib.bzrdir import BzrDir
 
24
from bzrlib import (
 
25
        osutils,
 
26
        urlutils,
 
27
        branch,
 
28
        )
23
29
from bzrlib.workingtree import WorkingTree
24
 
from bzrlib.tests.blackbox import ExternalBase
 
30
from bzrlib.tests import (
 
31
        TestCaseWithTransport,
 
32
        script,
 
33
        )
 
34
from bzrlib.tests.features import UnicodeFilenameFeature
25
35
from bzrlib.directory_service import directories
26
36
 
27
 
 
28
 
class TestSwitch(ExternalBase):
 
37
from bzrlib.tests.matchers import ContainsNoVfsCalls
 
38
 
 
39
 
 
40
class TestSwitch(TestCaseWithTransport):
29
41
 
30
42
    def _create_sample_tree(self):
31
43
        tree = self.make_branch_and_tree('branch-1')
128
140
        """Using switch on a heavy checkout should find master sibling
129
141
 
130
142
        The behaviour of lighweight and heavy checkouts should be
131
 
        consistentwhen using the convenient "switch to sibling" feature
 
143
        consistent when using the convenient "switch to sibling" feature
132
144
        Both should switch to a sibling of the branch
133
145
        they are bound to, and not a sibling of themself"""
134
146
 
141
153
        branchb_id = tree2.commit('bar')
142
154
        checkout = tree1.branch.create_checkout('heavyco/a', lightweight=False)
143
155
        self.run_bzr(['switch', 'branchb'], working_dir='heavyco/a')
144
 
        self.assertEqual(branchb_id, checkout.last_revision())
145
 
        self.assertEqual(tree2.branch.base, checkout.branch.get_bound_location())
 
156
        # Refresh checkout as 'switch' modified it
 
157
        checkout = checkout.bzrdir.open_workingtree()
 
158
        self.assertEqual(branchb_id, checkout.last_revision())
 
159
        self.assertEqual(tree2.branch.base,
 
160
                         checkout.branch.get_bound_location())
 
161
 
 
162
    def test_switch_finds_relative_unicode_branch(self):
 
163
        """Switch will find 'foo' relative to the branch the checkout is of."""
 
164
        self.requireFeature(UnicodeFilenameFeature)
 
165
        self.build_tree(['repo/'])
 
166
        tree1 = self.make_branch_and_tree('repo/brancha')
 
167
        tree1.commit('foo')
 
168
        tree2 = self.make_branch_and_tree(u'repo/branch\xe9')
 
169
        tree2.pull(tree1.branch)
 
170
        branchb_id = tree2.commit('bar')
 
171
        checkout =  tree1.branch.create_checkout('checkout', lightweight=True)
 
172
        self.run_bzr(['switch', u'branch\xe9'], working_dir='checkout')
 
173
        self.assertEqual(branchb_id, checkout.last_revision())
 
174
        checkout = checkout.bzrdir.open_workingtree()
 
175
        self.assertEqual(tree2.branch.base, checkout.branch.base)
146
176
 
147
177
    def test_switch_revision(self):
148
178
        tree = self._create_sample_tree()
149
179
        checkout = tree.branch.create_checkout('checkout', lightweight=True)
150
180
        self.run_bzr(['switch', 'branch-1', '-r1'], working_dir='checkout')
151
 
        self.failUnlessExists('checkout/file-1')
152
 
        self.failIfExists('checkout/file-2')
 
181
        self.assertPathExists('checkout/file-1')
 
182
        self.assertPathDoesNotExist('checkout/file-2')
 
183
 
 
184
    def test_switch_into_colocated(self):
 
185
        # Create a new colocated branch from an existing non-colocated branch.
 
186
        tree = self.make_branch_and_tree('.', format='development-colo')
 
187
        self.build_tree(['file-1', 'file-2'])
 
188
        tree.add('file-1')
 
189
        revid1 = tree.commit('rev1')
 
190
        tree.add('file-2')
 
191
        revid2 = tree.commit('rev2')
 
192
        self.run_bzr(['switch', '-b', 'anotherbranch'])
 
193
        self.assertEquals(
 
194
            set(['', 'anotherbranch']),
 
195
            set(tree.branch.bzrdir.get_branches().keys()))
 
196
 
 
197
    def test_switch_into_unrelated_colocated(self):
 
198
        # Create a new colocated branch from an existing non-colocated branch.
 
199
        tree = self.make_branch_and_tree('.', format='development-colo')
 
200
        self.build_tree(['file-1', 'file-2'])
 
201
        tree.add('file-1')
 
202
        revid1 = tree.commit('rev1')
 
203
        tree.add('file-2')
 
204
        revid2 = tree.commit('rev2')
 
205
        tree.bzrdir.create_branch(name='foo')
 
206
        self.run_bzr_error(['Cannot switch a branch, only a checkout.'],
 
207
            'switch foo')
 
208
        self.run_bzr(['switch', '--force', 'foo'])
 
209
 
 
210
    def test_switch_existing_colocated(self):
 
211
        # Create a branch branch-1 that initially is a checkout of 'foo'
 
212
        # Use switch to change it to 'anotherbranch'
 
213
        repo = self.make_repository('branch-1', format='development-colo')
 
214
        target_branch = repo.bzrdir.create_branch(name='foo')
 
215
        repo.bzrdir.set_branch_reference(target_branch)
 
216
        tree = repo.bzrdir.create_workingtree()
 
217
        self.build_tree(['branch-1/file-1', 'branch-1/file-2'])
 
218
        tree.add('file-1')
 
219
        revid1 = tree.commit('rev1')
 
220
        tree.add('file-2')
 
221
        revid2 = tree.commit('rev2')
 
222
        otherbranch = tree.bzrdir.create_branch(name='anotherbranch')
 
223
        otherbranch.generate_revision_history(revid1)
 
224
        self.run_bzr(['switch', 'anotherbranch'], working_dir='branch-1')
 
225
        tree = WorkingTree.open("branch-1")
 
226
        self.assertEquals(tree.last_revision(), revid1)
 
227
        self.assertEquals(tree.branch.control_url, otherbranch.control_url)
 
228
 
 
229
    def test_switch_new_colocated(self):
 
230
        # Create a branch branch-1 that initially is a checkout of 'foo'
 
231
        # Use switch to create 'anotherbranch' which derives from that
 
232
        repo = self.make_repository('branch-1', format='development-colo')
 
233
        target_branch = repo.bzrdir.create_branch(name='foo')
 
234
        repo.bzrdir.set_branch_reference(target_branch)
 
235
        tree = repo.bzrdir.create_workingtree()
 
236
        self.build_tree(['branch-1/file-1', 'branch-1/file-2'])
 
237
        tree.add('file-1')
 
238
        revid1 = tree.commit('rev1')
 
239
        self.run_bzr(['switch', '-b', 'anotherbranch'], working_dir='branch-1')
 
240
        bzrdir = BzrDir.open("branch-1")
 
241
        self.assertEquals(
 
242
            set([b.name for b in bzrdir.list_branches()]),
 
243
            set(["foo", "anotherbranch"]))
 
244
        self.assertEquals(bzrdir.open_branch().name, "anotherbranch")
 
245
        self.assertEquals(bzrdir.open_branch().last_revision(), revid1)
 
246
 
 
247
    def test_switch_new_colocated_unicode(self):
 
248
        # Create a branch branch-1 that initially is a checkout of 'foo'
 
249
        # Use switch to create 'branch\xe9' which derives from that
 
250
        self.requireFeature(UnicodeFilenameFeature)
 
251
        repo = self.make_repository('branch-1', format='development-colo')
 
252
        target_branch = repo.bzrdir.create_branch(name='foo')
 
253
        repo.bzrdir.set_branch_reference(target_branch)
 
254
        tree = repo.bzrdir.create_workingtree()
 
255
        self.build_tree(['branch-1/file-1', 'branch-1/file-2'])
 
256
        tree.add('file-1')
 
257
        revid1 = tree.commit('rev1')
 
258
        self.run_bzr(['switch', '-b', u'branch\xe9'], working_dir='branch-1')
 
259
        bzrdir = BzrDir.open("branch-1")
 
260
        self.assertEquals(
 
261
            set([b.name for b in bzrdir.list_branches()]),
 
262
            set(["foo", u"branch\xe9"]))
 
263
        self.assertEquals(bzrdir.open_branch().name, u"branch\xe9")
 
264
        self.assertEquals(bzrdir.open_branch().last_revision(), revid1)
153
265
 
154
266
    def test_switch_only_revision(self):
155
267
        tree = self._create_sample_tree()
156
268
        checkout = tree.branch.create_checkout('checkout', lightweight=True)
157
 
        self.failUnlessExists('checkout/file-1')
158
 
        self.failUnlessExists('checkout/file-2')
 
269
        self.assertPathExists('checkout/file-1')
 
270
        self.assertPathExists('checkout/file-2')
159
271
        self.run_bzr(['switch', '-r1'], working_dir='checkout')
160
 
        self.failUnlessExists('checkout/file-1')
161
 
        self.failIfExists('checkout/file-2')
 
272
        self.assertPathExists('checkout/file-1')
 
273
        self.assertPathDoesNotExist('checkout/file-2')
162
274
        # Check that we don't accept a range
163
275
        self.run_bzr_error(
164
276
            ['bzr switch --revision takes exactly one revision identifier'],
167
279
    def prepare_lightweight_switch(self):
168
280
        branch = self.make_branch('branch')
169
281
        branch.create_checkout('tree', lightweight=True)
170
 
        os.rename('branch', 'branch1')
 
282
        osutils.rename('branch', 'branch1')
171
283
 
172
284
    def test_switch_lightweight_after_branch_moved(self):
173
285
        self.prepare_lightweight_switch()
225
337
        self.run_bzr('switch -b foo:branch2', working_dir='tree')
226
338
        tree = WorkingTree.open('tree')
227
339
        self.assertEndsWith(tree.branch.base, 'foo-branch2/')
 
340
 
 
341
    def test_switch_with_post_switch_hook(self):
 
342
        from bzrlib import branch as _mod_branch
 
343
        calls = []
 
344
        _mod_branch.Branch.hooks.install_named_hook('post_switch',
 
345
            calls.append, None)
 
346
        self.make_branch_and_tree('branch')
 
347
        self.run_bzr('branch branch branch2')
 
348
        self.run_bzr('checkout branch checkout')
 
349
        os.chdir('checkout')
 
350
        self.assertLength(0, calls)
 
351
        out, err = self.run_bzr('switch ../branch2')
 
352
        self.assertLength(1, calls)
 
353
 
 
354
    def test_switch_lightweight_co_with_post_switch_hook(self):
 
355
        from bzrlib import branch as _mod_branch
 
356
        calls = []
 
357
        _mod_branch.Branch.hooks.install_named_hook('post_switch',
 
358
            calls.append, None)
 
359
        self.make_branch_and_tree('branch')
 
360
        self.run_bzr('branch branch branch2')
 
361
        self.run_bzr('checkout --lightweight branch checkout')
 
362
        os.chdir('checkout')
 
363
        self.assertLength(0, calls)
 
364
        out, err = self.run_bzr('switch ../branch2')
 
365
        self.assertLength(1, calls)
 
366
 
 
367
    def test_switch_lightweight_directory(self):
 
368
        """Test --directory option"""
 
369
 
 
370
        # create a source branch
 
371
        a_tree = self.make_branch_and_tree('a')
 
372
        self.build_tree_contents([('a/a', 'initial\n')])
 
373
        a_tree.add('a')
 
374
        a_tree.commit(message='initial')
 
375
 
 
376
        # clone and add a differing revision
 
377
        b_tree = a_tree.bzrdir.sprout('b').open_workingtree()
 
378
        self.build_tree_contents([('b/a', 'initial\nmore\n')])
 
379
        b_tree.commit(message='more')
 
380
 
 
381
        self.run_bzr('checkout --lightweight a checkout')
 
382
        self.run_bzr('switch --directory checkout b')
 
383
        self.assertFileEqual('initial\nmore\n', 'checkout/a')
 
384
 
 
385
 
 
386
class TestSwitchParentLocationBase(TestCaseWithTransport):
 
387
 
 
388
    def setUp(self):
 
389
        """Set up a repository and branch ready for testing."""
 
390
        super(TestSwitchParentLocationBase, self).setUp()
 
391
        self.script_runner = script.ScriptRunner()
 
392
        self.script_runner.run_script(self, '''
 
393
                $ bzr init-repo --no-trees repo
 
394
                Shared repository...
 
395
                Location:
 
396
                  shared repository: repo
 
397
                $ bzr init repo/trunk
 
398
                Created a repository branch...
 
399
                Using shared repository: ...
 
400
                ''')
 
401
 
 
402
    def assertParent(self, expected_parent, branch):
 
403
        """Verify that the parent is not None and is set correctly."""
 
404
        actual_parent = branch.get_parent()
 
405
        self.assertIsSameRealPath(urlutils.local_path_to_url(expected_parent),
 
406
                                  branch.get_parent())
 
407
 
 
408
 
 
409
class TestSwitchParentLocation(TestSwitchParentLocationBase):
 
410
 
 
411
    def _checkout_and_switch(self, option=''):
 
412
        self.script_runner.run_script(self, '''
 
413
                $ bzr checkout %(option)s repo/trunk checkout
 
414
                $ cd checkout
 
415
                $ bzr switch --create-branch switched
 
416
                2>Tree is up to date at revision 0.
 
417
                2>Switched to branch:...switched...
 
418
                $ cd ..
 
419
                ''' % locals())
 
420
        bound_branch = branch.Branch.open_containing('checkout')[0]
 
421
        master_branch = branch.Branch.open_containing('repo/switched')[0]
 
422
        return (bound_branch, master_branch)
 
423
 
 
424
    def test_switch_parent_lightweight(self):
 
425
        """Lightweight checkout using bzr switch."""
 
426
        bb, mb = self._checkout_and_switch(option='--lightweight')
 
427
        self.assertParent('repo/trunk', bb)
 
428
        self.assertParent('repo/trunk', mb)
 
429
 
 
430
    def test_switch_parent_heavyweight(self):
 
431
        """Heavyweight checkout using bzr switch."""
 
432
        bb, mb = self._checkout_and_switch()
 
433
        self.assertParent('repo/trunk', bb)
 
434
        self.assertParent('repo/trunk', mb)
 
435
 
 
436
 
 
437
class TestSwitchDoesntOpenMasterBranch(TestCaseWithTransport):
 
438
    # See https://bugs.launchpad.net/bzr/+bug/812285
 
439
    # "bzr switch --create-branch" can point the new branch's parent to the
 
440
    # master branch, but it doesn't have to open it to do so.
 
441
 
 
442
    def test_switch_create_doesnt_open_master_branch(self):
 
443
        master = self.make_branch_and_tree('master')
 
444
        master.commit('one')
 
445
        # Note: not a lightweight checkout
 
446
        checkout = master.branch.create_checkout('checkout')
 
447
        opened = []
 
448
        def open_hook(branch):
 
449
            # Just append the final directory of the branch
 
450
            name = branch.base.rstrip('/').rsplit('/', 1)[1]
 
451
            opened.append(name)
 
452
        branch.Branch.hooks.install_named_hook('open', open_hook,
 
453
                                               'open_hook_logger')
 
454
        self.run_bzr('switch --create-branch -d checkout feature')
 
455
        # We only open the master branch 1 time.
 
456
        # This test should be cleaner to write, but see bug:
 
457
        #  https://bugs.launchpad.net/bzr/+bug/812295
 
458
        self.assertEqual(1, opened.count('master'))
 
459
 
 
460
 
 
461
class TestSmartServerSwitch(TestCaseWithTransport):
 
462
 
 
463
    def test_switch_lightweight(self):
 
464
        self.setup_smart_server_with_call_log()
 
465
        t = self.make_branch_and_tree('from')
 
466
        for count in range(9):
 
467
            t.commit(message='commit %d' % count)
 
468
        out, err = self.run_bzr(['checkout', '--lightweight', self.get_url('from'),
 
469
            'target'])
 
470
        self.reset_smart_call_log()
 
471
        self.run_bzr(['switch', self.get_url('from')], working_dir='target')
 
472
        # This figure represent the amount of work to perform this use case. It
 
473
        # is entirely ok to reduce this number if a test fails due to rpc_count
 
474
        # being too low. If rpc_count increases, more network roundtrips have
 
475
        # become necessary for this use case. Please do not adjust this number
 
476
        # upwards without agreement from bzr's network support maintainers.
 
477
        self.assertLength(24, self.hpss_calls)
 
478
        self.assertLength(5, self.hpss_connections)
 
479
        self.assertThat(self.hpss_calls, ContainsNoVfsCalls)