~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2010-09-29 22:03:03 UTC
  • mfrom: (5416.2.6 jam-integration)
  • Revision ID: pqm@pqm.ubuntu.com-20100929220303-cr95h8iwtggco721
(mbp) Add 'break-lock --force'

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2008, 2009 Canonical Ltd
 
1
# Copyright (C) 2006-2010 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 (branch, bzrdir, errors, repository)
 
22
from bzrlib import (
 
23
    branch,
 
24
    bzrdir,
 
25
    errors,
 
26
    repository,
 
27
    revision as _mod_revision,
 
28
    )
23
29
from bzrlib.repofmt.knitrepo import RepositoryFormatKnit1
24
 
from bzrlib.tests.blackbox import ExternalBase
25
 
from bzrlib.tests import HardlinkFeature
 
30
from bzrlib.tests import TestCaseWithTransport
 
31
from bzrlib.tests import (
 
32
    KnownFailure,
 
33
    HardlinkFeature,
 
34
    test_server,
 
35
    )
26
36
from bzrlib.tests.test_sftp_transport import TestCaseWithSFTPServer
27
37
from bzrlib.urlutils import local_path_to_url, strip_trailing_slash
28
38
from bzrlib.workingtree import WorkingTree
29
39
 
30
40
 
31
 
class TestBranch(ExternalBase):
 
41
class TestBranch(TestCaseWithTransport):
32
42
 
33
43
    def example_branch(self, path='.'):
34
44
        tree = self.make_branch_and_tree(path)
49
59
        self.assertFalse(b._transport.has('branch-name'))
50
60
        b.bzrdir.open_workingtree().commit(message='foo', allow_pointless=True)
51
61
 
 
62
    def test_branch_switch_no_branch(self):
 
63
        # No branch in the current directory:
 
64
        #  => new branch will be created, but switch fails
 
65
        self.example_branch('a')
 
66
        self.make_repository('current')
 
67
        self.run_bzr_error(['No WorkingTree exists for'],
 
68
            'branch --switch ../a ../b', working_dir='current')
 
69
        a = branch.Branch.open('a')
 
70
        b = branch.Branch.open('b')
 
71
        self.assertEqual(a.last_revision(), b.last_revision())
 
72
 
 
73
    def test_branch_switch_no_wt(self):
 
74
        # No working tree in the current directory:
 
75
        #  => new branch will be created, but switch fails and the current
 
76
        #     branch is unmodified
 
77
        self.example_branch('a')
 
78
        self.make_branch('current')
 
79
        self.run_bzr_error(['No WorkingTree exists for'],
 
80
            'branch --switch ../a ../b', working_dir='current')
 
81
        a = branch.Branch.open('a')
 
82
        b = branch.Branch.open('b')
 
83
        self.assertEqual(a.last_revision(), b.last_revision())
 
84
        work = branch.Branch.open('current')
 
85
        self.assertEqual(work.last_revision(), _mod_revision.NULL_REVISION)
 
86
 
 
87
    def test_branch_switch_no_checkout(self):
 
88
        # Standalone branch in the current directory:
 
89
        #  => new branch will be created, but switch fails and the current
 
90
        #     branch is unmodified
 
91
        self.example_branch('a')
 
92
        self.make_branch_and_tree('current')
 
93
        self.run_bzr_error(['Cannot switch a branch, only a checkout'],
 
94
            'branch --switch ../a ../b', working_dir='current')
 
95
        a = branch.Branch.open('a')
 
96
        b = branch.Branch.open('b')
 
97
        self.assertEqual(a.last_revision(), b.last_revision())
 
98
        work = branch.Branch.open('current')
 
99
        self.assertEqual(work.last_revision(), _mod_revision.NULL_REVISION)
 
100
 
 
101
    def test_branch_switch_checkout(self):
 
102
        # Checkout in the current directory:
 
103
        #  => new branch will be created and checkout bound to the new branch
 
104
        self.example_branch('a')
 
105
        self.run_bzr('checkout a current')
 
106
        out, err = self.run_bzr('branch --switch ../a ../b', working_dir='current')
 
107
        a = branch.Branch.open('a')
 
108
        b = branch.Branch.open('b')
 
109
        self.assertEqual(a.last_revision(), b.last_revision())
 
110
        work = WorkingTree.open('current')
 
111
        self.assertEndsWith(work.branch.get_bound_location(), '/b/')
 
112
        self.assertContainsRe(err, "Switched to branch: .*/b/")
 
113
 
 
114
    def test_branch_switch_lightweight_checkout(self):
 
115
        # Lightweight checkout in the current directory:
 
116
        #  => new branch will be created and lightweight checkout pointed to
 
117
        #     the new branch
 
118
        self.example_branch('a')
 
119
        self.run_bzr('checkout --lightweight a current')
 
120
        out, err = self.run_bzr('branch --switch ../a ../b', working_dir='current')
 
121
        a = branch.Branch.open('a')
 
122
        b = branch.Branch.open('b')
 
123
        self.assertEqual(a.last_revision(), b.last_revision())
 
124
        work = WorkingTree.open('current')
 
125
        self.assertEndsWith(work.branch.base, '/b/')
 
126
        self.assertContainsRe(err, "Switched to branch: .*/b/")
 
127
 
52
128
    def test_branch_only_copies_history(self):
53
129
        # Knit branches should only push the history for the current revision.
54
130
        format = bzrdir.BzrDirMetaFormat1()
93
169
        self.build_tree(['source/file1'])
94
170
        source.add('file1')
95
171
        source.commit('added file')
96
 
        self.run_bzr(['branch', 'source', 'target', '--hardlink'])
 
172
        out, err = self.run_bzr(['branch', 'source', 'target', '--hardlink'])
97
173
        source_stat = os.stat('source/file1')
98
174
        target_stat = os.stat('target/file1')
99
175
        self.assertEqual(source_stat, target_stat)
100
176
 
 
177
    def test_branch_files_from(self):
 
178
        source = self.make_branch_and_tree('source')
 
179
        self.build_tree(['source/file1'])
 
180
        source.add('file1')
 
181
        source.commit('added file')
 
182
        out, err = self.run_bzr('branch source target --files-from source')
 
183
        self.failUnlessExists('target/file1')
 
184
 
 
185
    def test_branch_files_from_hardlink(self):
 
186
        self.requireFeature(HardlinkFeature)
 
187
        source = self.make_branch_and_tree('source')
 
188
        self.build_tree(['source/file1'])
 
189
        source.add('file1')
 
190
        source.commit('added file')
 
191
        source.bzrdir.sprout('second')
 
192
        out, err = self.run_bzr('branch source target --files-from second'
 
193
                                ' --hardlink')
 
194
        source_stat = os.stat('source/file1')
 
195
        second_stat = os.stat('second/file1')
 
196
        target_stat = os.stat('target/file1')
 
197
        self.assertNotEqual(source_stat, target_stat)
 
198
        self.assertEqual(second_stat, target_stat)
 
199
 
101
200
    def test_branch_standalone(self):
102
201
        shared_repo = self.make_repository('repo', shared=True)
103
202
        self.example_branch('source')
113
212
        self.failIfExists('target/hello')
114
213
        self.failIfExists('target/goodbye')
115
214
 
116
 
 
117
 
class TestBranchStacked(ExternalBase):
 
215
    def test_branch_into_existing_dir(self):
 
216
        self.example_branch('a')
 
217
        # existing dir with similar files but no .bzr dir
 
218
        self.build_tree_contents([('b/',)])
 
219
        self.build_tree_contents([('b/hello', 'bar')])  # different content
 
220
        self.build_tree_contents([('b/goodbye', 'baz')])# same content
 
221
        # fails without --use-existing-dir
 
222
        out,err = self.run_bzr('branch a b', retcode=3)
 
223
        self.assertEqual('', out)
 
224
        self.assertEqual('bzr: ERROR: Target directory "b" already exists.\n',
 
225
            err)
 
226
        # force operation
 
227
        self.run_bzr('branch a b --use-existing-dir')
 
228
        # check conflicts
 
229
        self.failUnlessExists('b/hello.moved')
 
230
        self.failIfExists('b/godbye.moved')
 
231
        # we can't branch into branch
 
232
        out,err = self.run_bzr('branch a b --use-existing-dir', retcode=3)
 
233
        self.assertEqual('', out)
 
234
        self.assertEqual('bzr: ERROR: Already a branch: "b".\n', err)
 
235
 
 
236
    def test_branch_bind(self):
 
237
        self.example_branch('a')
 
238
        out, err = self.run_bzr('branch a b --bind')
 
239
        self.assertEndsWith(err, "New branch bound to a\n")
 
240
        b = branch.Branch.open('b')
 
241
        self.assertEndsWith(b.get_bound_location(), '/a/')
 
242
 
 
243
    def test_branch_with_post_branch_init_hook(self):
 
244
        calls = []
 
245
        branch.Branch.hooks.install_named_hook('post_branch_init',
 
246
            calls.append, None)
 
247
        self.assertLength(0, calls)
 
248
        self.example_branch('a')
 
249
        self.assertLength(1, calls)
 
250
        self.run_bzr('branch a b')
 
251
        self.assertLength(2, calls)
 
252
 
 
253
    def test_checkout_with_post_branch_init_hook(self):
 
254
        calls = []
 
255
        branch.Branch.hooks.install_named_hook('post_branch_init',
 
256
            calls.append, None)
 
257
        self.assertLength(0, calls)
 
258
        self.example_branch('a')
 
259
        self.assertLength(1, calls)
 
260
        self.run_bzr('checkout a b')
 
261
        self.assertLength(2, calls)
 
262
 
 
263
    def test_lightweight_checkout_with_post_branch_init_hook(self):
 
264
        calls = []
 
265
        branch.Branch.hooks.install_named_hook('post_branch_init',
 
266
            calls.append, None)
 
267
        self.assertLength(0, calls)
 
268
        self.example_branch('a')
 
269
        self.assertLength(1, calls)
 
270
        self.run_bzr('checkout --lightweight a b')
 
271
        self.assertLength(2, calls)
 
272
 
 
273
 
 
274
class TestBranchStacked(TestCaseWithTransport):
118
275
    """Tests for branch --stacked"""
119
276
 
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
 
 
143
277
    def assertRevisionInRepository(self, repo_path, revid):
144
278
        """Check that a revision is in a repository, disregarding stacking."""
145
279
        repo = bzrdir.BzrDir.open(repo_path).open_repository()
166
300
            format='1.9')
167
301
        branch_tree.branch.set_stacked_on_url(trunk_tree.branch.base)
168
302
        # with some work on it
169
 
        branch_tree.commit('moar work plz')
 
303
        work_tree = trunk_tree.branch.bzrdir.sprout('local').open_workingtree()
 
304
        work_tree.commit('moar work plz')
 
305
        work_tree.branch.push(branch_tree.branch)
170
306
        # branching our local branch gives us a new stacked branch pointing at
171
307
        # mainline.
172
308
        out, err = self.run_bzr(['branch', 'branch', 'newbranch'])
173
309
        self.assertEqual('', out)
174
 
        self.assertEqual('Branched 1 revision(s).\n',
 
310
        self.assertEqual('Branched 2 revision(s).\n',
175
311
            err)
176
312
        # it should have preserved the branch format, and so it should be
177
313
        # capable of supporting stacking, but not actually have a stacked_on
190
326
            format='1.9')
191
327
        branch_tree.branch.set_stacked_on_url(trunk_tree.branch.base)
192
328
        # with some work on it
193
 
        branch_revid = branch_tree.commit('moar work plz')
 
329
        work_tree = trunk_tree.branch.bzrdir.sprout('local').open_workingtree()
 
330
        branch_revid = work_tree.commit('moar work plz')
 
331
        work_tree.branch.push(branch_tree.branch)
194
332
        # you can chain branches on from there
195
333
        out, err = self.run_bzr(['branch', 'branch', '--stacked', 'branch2'])
196
334
        self.assertEqual('', out)
199
337
        self.assertEqual(branch_tree.branch.base,
200
338
            branch.Branch.open('branch2').get_stacked_on_url())
201
339
        branch2_tree = WorkingTree.open('branch2')
202
 
        branch2_revid = branch2_tree.commit('work on second stacked branch')
 
340
        branch2_revid = work_tree.commit('work on second stacked branch')
 
341
        work_tree.branch.push(branch2_tree.branch)
203
342
        self.assertRevisionInRepository('branch2', branch2_revid)
204
343
        self.assertRevisionsInBranchRepository(
205
344
            [trunk_revid, branch_revid, branch2_revid],
218
357
        self.assertEqual('Created new stacked branch referring to %s.\n' %
219
358
            trunk_tree.branch.base, err)
220
359
        self.assertRevisionNotInRepository('newbranch', original_revid)
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)
 
360
        new_branch = branch.Branch.open('newbranch')
 
361
        self.assertEqual(trunk_tree.branch.base, new_branch.get_stacked_on_url())
224
362
 
225
363
    def test_branch_stacked_from_smart_server(self):
226
364
        # We can branch stacking on a smart server
227
 
        from bzrlib.smart.server import SmartTCPServer_for_testing
228
 
        self.transport_server = SmartTCPServer_for_testing
 
365
        self.transport_server = test_server.SmartTCPServer_for_testing
229
366
        trunk = self.make_branch('mainline', format='1.9')
230
367
        out, err = self.run_bzr(
231
368
            ['branch', '--stacked', self.get_url('mainline'), 'shallow'])
241
378
            '  Packs 5 (adds stacking support, requires bzr 1.6)\n'
242
379
            'Source branch format does not support stacking, using format:\n'
243
380
            '  Branch format 7\n'
 
381
            'Doing on-the-fly conversion from RepositoryFormatKnitPack1() to RepositoryFormatKnitPack5().\n'
 
382
            'This may take some time. Upgrade the repositories to the same format for better performance.\n'
244
383
            'Created new stacked branch referring to %s.\n' % (trunk.base,),
245
384
            err)
246
385
 
254
393
            '  Packs 5 rich-root (adds stacking support, requires bzr 1.6.1)\n'
255
394
            'Source branch format does not support stacking, using format:\n'
256
395
            '  Branch format 7\n'
 
396
            'Doing on-the-fly conversion from RepositoryFormatKnitPack4() to RepositoryFormatKnitPack5RichRoot().\n'
 
397
            'This may take some time. Upgrade the repositories to the same format for better performance.\n'
257
398
            'Created new stacked branch referring to %s.\n' % (trunk.base,),
258
399
            err)
259
400
 
260
401
 
261
 
class TestSmartServerBranching(ExternalBase):
 
402
class TestSmartServerBranching(TestCaseWithTransport):
262
403
 
263
404
    def test_branch_from_trivial_branch_to_same_server_branch_acceptance(self):
264
405
        self.setup_smart_server_with_call_log()
297
438
            t.commit(message='commit %d' % count)
298
439
        tree2 = t.branch.bzrdir.sprout('feature', stacked=True
299
440
            ).open_workingtree()
300
 
        tree2.commit('feature change')
 
441
        local_tree = t.branch.bzrdir.sprout('local-working').open_workingtree()
 
442
        local_tree.commit('feature change')
 
443
        local_tree.branch.push(tree2.branch)
301
444
        self.reset_smart_call_log()
302
445
        out, err = self.run_bzr(['branch', self.get_url('feature'),
303
446
            'local-target'])