~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Martin Pool
  • Date: 2009-01-13 03:11:04 UTC
  • mto: This revision was merged to the branch mainline in revision 3937.
  • Revision ID: mbp@sourcefrog.net-20090113031104-03my054s02i9l2pe
Bump version to 1.12 and add news template

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2008 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
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
 
18
18
"""Black-box tests for bzr branch."""
19
19
 
20
20
import os
21
21
 
22
 
from bzrlib import (
23
 
    branch,
24
 
    bzrdir,
25
 
    errors,
26
 
    repository,
27
 
    revision as _mod_revision,
28
 
    )
 
22
from bzrlib import (branch, bzrdir, errors, repository)
29
23
from bzrlib.repofmt.knitrepo import RepositoryFormatKnit1
30
24
from bzrlib.tests.blackbox import ExternalBase
31
 
from bzrlib.tests import (
32
 
    KnownFailure,
33
 
    HardlinkFeature,
34
 
    test_server,
35
 
    )
 
25
from bzrlib.tests import HardlinkFeature
36
26
from bzrlib.tests.test_sftp_transport import TestCaseWithSFTPServer
37
27
from bzrlib.urlutils import local_path_to_url, strip_trailing_slash
38
28
from bzrlib.workingtree import WorkingTree
59
49
        self.assertFalse(b._transport.has('branch-name'))
60
50
        b.bzrdir.open_workingtree().commit(message='foo', allow_pointless=True)
61
51
 
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
 
 
128
52
    def test_branch_only_copies_history(self):
129
53
        # Knit branches should only push the history for the current revision.
130
54
        format = bzrdir.BzrDirMetaFormat1()
169
93
        self.build_tree(['source/file1'])
170
94
        source.add('file1')
171
95
        source.commit('added file')
172
 
        out, err = self.run_bzr(['branch', 'source', 'target', '--hardlink'])
 
96
        self.run_bzr(['branch', 'source', 'target', '--hardlink'])
173
97
        source_stat = os.stat('source/file1')
174
98
        target_stat = os.stat('target/file1')
175
99
        self.assertEqual(source_stat, target_stat)
183
107
        self.assertEqual(strip_trailing_slash(b.repository.base),
184
108
            strip_trailing_slash(local_path_to_url(expected_repo_path)))
185
109
 
186
 
    def test_branch_no_tree(self):
187
 
        self.example_branch('source')
188
 
        self.run_bzr('branch --no-tree source target')
189
 
        self.failIfExists('target/hello')
190
 
        self.failIfExists('target/goodbye')
191
 
 
192
 
    def test_branch_into_existing_dir(self):
193
 
        self.example_branch('a')
194
 
        # existing dir with similar files but no .bzr dir
195
 
        self.build_tree_contents([('b/',)])
196
 
        self.build_tree_contents([('b/hello', 'bar')])  # different content
197
 
        self.build_tree_contents([('b/goodbye', 'baz')])# same content
198
 
        # fails without --use-existing-dir
199
 
        out,err = self.run_bzr('branch a b', retcode=3)
200
 
        self.assertEqual('', out)
201
 
        self.assertEqual('bzr: ERROR: Target directory "b" already exists.\n',
202
 
            err)
203
 
        # force operation
204
 
        self.run_bzr('branch a b --use-existing-dir')
205
 
        # check conflicts
206
 
        self.failUnlessExists('b/hello.moved')
207
 
        self.failIfExists('b/godbye.moved')
208
 
        # we can't branch into branch
209
 
        out,err = self.run_bzr('branch a b --use-existing-dir', retcode=3)
210
 
        self.assertEqual('', out)
211
 
        self.assertEqual('bzr: ERROR: Already a branch: "b".\n', err)
212
 
 
213
 
    def test_branch_bind(self):
214
 
        self.example_branch('a')
215
 
        out, err = self.run_bzr('branch a b --bind')
216
 
        self.assertEndsWith(err, "New branch bound to a\n")
217
 
        b = branch.Branch.open('b')
218
 
        self.assertEndsWith(b.get_bound_location(), '/a/')
219
 
 
220
 
    def test_branch_with_post_branch_init_hook(self):
221
 
        calls = []
222
 
        branch.Branch.hooks.install_named_hook('post_branch_init',
223
 
            calls.append, None)
224
 
        self.assertLength(0, calls)
225
 
        self.example_branch('a')
226
 
        self.assertLength(1, calls)
227
 
        self.run_bzr('branch a b')
228
 
        self.assertLength(2, calls)
229
 
 
230
 
    def test_checkout_with_post_branch_init_hook(self):
231
 
        calls = []
232
 
        branch.Branch.hooks.install_named_hook('post_branch_init',
233
 
            calls.append, None)
234
 
        self.assertLength(0, calls)
235
 
        self.example_branch('a')
236
 
        self.assertLength(1, calls)
237
 
        self.run_bzr('checkout a b')
238
 
        self.assertLength(2, calls)
239
 
 
240
 
    def test_lightweight_checkout_with_post_branch_init_hook(self):
241
 
        calls = []
242
 
        branch.Branch.hooks.install_named_hook('post_branch_init',
243
 
            calls.append, None)
244
 
        self.assertLength(0, calls)
245
 
        self.example_branch('a')
246
 
        self.assertLength(1, calls)
247
 
        self.run_bzr('checkout --lightweight a b')
248
 
        self.assertLength(2, calls)
249
 
 
250
110
 
251
111
class TestBranchStacked(ExternalBase):
252
112
    """Tests for branch --stacked"""
253
113
 
 
114
    def check_shallow_branch(self, branch_revid, stacked_on):
 
115
        """Assert that the branch 'newbranch' has been published correctly.
 
116
 
 
117
        :param stacked_on: url of a branch this one is stacked upon.
 
118
        :param branch_revid: a revision id that should be the only
 
119
            revision present in the stacked branch, and it should not be in
 
120
            the reference branch.
 
121
        """
 
122
        new_branch = branch.Branch.open('newbranch')
 
123
        # The branch refers to the mainline
 
124
        self.assertEqual(stacked_on, new_branch.get_stacked_on_url())
 
125
        # and the branch's work was pushed
 
126
        self.assertTrue(new_branch.repository.has_revision(branch_revid))
 
127
        # The newly committed revision shoud be present in the stacked branch,
 
128
        # but not in the stacked-on branch.  Because stacking is set up by the
 
129
        # branch object, if we open the stacked branch's repository directly,
 
130
        # bypassing the branch, we see only what's in the stacked repository.
 
131
        stacked_repo = bzrdir.BzrDir.open('newbranch').open_repository()
 
132
        stacked_repo_revisions = set(stacked_repo.all_revision_ids())
 
133
        if len(stacked_repo_revisions) != 1:
 
134
            self.fail("wrong revisions in stacked repository: %r"
 
135
                % (stacked_repo_revisions,))
 
136
 
254
137
    def assertRevisionInRepository(self, repo_path, revid):
255
138
        """Check that a revision is in a repository, disregarding stacking."""
256
139
        repo = bzrdir.BzrDir.open(repo_path).open_repository()
270
153
        """Branching a stacked branch is not stacked by default"""
271
154
        # We have a mainline
272
155
        trunk_tree = self.make_branch_and_tree('target',
273
 
            format='1.9')
 
156
            format='development')
274
157
        trunk_tree.commit('mainline')
275
158
        # and a branch from it which is stacked
276
159
        branch_tree = self.make_branch_and_tree('branch',
277
 
            format='1.9')
 
160
            format='development')
278
161
        branch_tree.branch.set_stacked_on_url(trunk_tree.branch.base)
279
162
        # with some work on it
280
 
        work_tree = trunk_tree.branch.bzrdir.sprout('local').open_workingtree()
281
 
        work_tree.commit('moar work plz')
282
 
        work_tree.branch.push(branch_tree.branch)
 
163
        branch_tree.commit('moar work plz')
283
164
        # branching our local branch gives us a new stacked branch pointing at
284
165
        # mainline.
285
166
        out, err = self.run_bzr(['branch', 'branch', 'newbranch'])
286
167
        self.assertEqual('', out)
287
 
        self.assertEqual('Branched 2 revision(s).\n',
 
168
        self.assertEqual('Branched 1 revision(s).\n',
288
169
            err)
289
170
        # it should have preserved the branch format, and so it should be
290
171
        # capable of supporting stacking, but not actually have a stacked_on
296
177
        """Asking to stack on a stacked branch does work"""
297
178
        # We have a mainline
298
179
        trunk_tree = self.make_branch_and_tree('target',
299
 
            format='1.9')
 
180
            format='development')
300
181
        trunk_revid = trunk_tree.commit('mainline')
301
182
        # and a branch from it which is stacked
302
183
        branch_tree = self.make_branch_and_tree('branch',
303
 
            format='1.9')
 
184
            format='development')
304
185
        branch_tree.branch.set_stacked_on_url(trunk_tree.branch.base)
305
186
        # with some work on it
306
 
        work_tree = trunk_tree.branch.bzrdir.sprout('local').open_workingtree()
307
 
        branch_revid = work_tree.commit('moar work plz')
308
 
        work_tree.branch.push(branch_tree.branch)
 
187
        branch_revid = branch_tree.commit('moar work plz')
309
188
        # you can chain branches on from there
310
189
        out, err = self.run_bzr(['branch', 'branch', '--stacked', 'branch2'])
311
190
        self.assertEqual('', out)
314
193
        self.assertEqual(branch_tree.branch.base,
315
194
            branch.Branch.open('branch2').get_stacked_on_url())
316
195
        branch2_tree = WorkingTree.open('branch2')
317
 
        branch2_revid = work_tree.commit('work on second stacked branch')
318
 
        work_tree.branch.push(branch2_tree.branch)
 
196
        branch2_revid = branch2_tree.commit('work on second stacked branch')
319
197
        self.assertRevisionInRepository('branch2', branch2_revid)
320
198
        self.assertRevisionsInBranchRepository(
321
199
            [trunk_revid, branch_revid, branch2_revid],
324
202
    def test_branch_stacked(self):
325
203
        # We have a mainline
326
204
        trunk_tree = self.make_branch_and_tree('mainline',
327
 
            format='1.9')
 
205
            format='development')
328
206
        original_revid = trunk_tree.commit('mainline')
329
207
        self.assertRevisionInRepository('mainline', original_revid)
330
208
        # and a branch from it which is stacked
334
212
        self.assertEqual('Created new stacked branch referring to %s.\n' %
335
213
            trunk_tree.branch.base, err)
336
214
        self.assertRevisionNotInRepository('newbranch', original_revid)
337
 
        new_branch = branch.Branch.open('newbranch')
338
 
        self.assertEqual(trunk_tree.branch.base, new_branch.get_stacked_on_url())
 
215
        new_tree = WorkingTree.open('newbranch')
 
216
        new_revid = new_tree.commit('new work')
 
217
        self.check_shallow_branch(new_revid, trunk_tree.branch.base)
339
218
 
340
219
    def test_branch_stacked_from_smart_server(self):
341
220
        # We can branch stacking on a smart server
342
 
        self.transport_server = test_server.SmartTCPServer_for_testing
343
 
        trunk = self.make_branch('mainline', format='1.9')
 
221
        from bzrlib.smart.server import SmartTCPServer_for_testing
 
222
        self.transport_server = SmartTCPServer_for_testing
 
223
        trunk = self.make_branch('mainline', format='development')
344
224
        out, err = self.run_bzr(
345
225
            ['branch', '--stacked', self.get_url('mainline'), 'shallow'])
346
226
 
351
231
            ['branch', '--stacked', 'trunk', 'shallow'])
352
232
        # We should notify the user that we upgraded their format
353
233
        self.assertEqualDiff(
354
 
            'Source repository format does not support stacking, using format:\n'
 
234
            'Source format does not support stacking, using format: \'1.6\'\n'
355
235
            '  Packs 5 (adds stacking support, requires bzr 1.6)\n'
356
 
            'Source branch format does not support stacking, using format:\n'
357
 
            '  Branch format 7\n'
358
 
            'Doing on-the-fly conversion from RepositoryFormatKnitPack1() to RepositoryFormatKnitPack5().\n'
359
 
            'This may take some time. Upgrade the repositories to the same format for better performance.\n'
 
236
            '\n'
360
237
            'Created new stacked branch referring to %s.\n' % (trunk.base,),
361
238
            err)
362
239
 
366
243
            ['branch', '--stacked', 'trunk', 'shallow'])
367
244
        # We should notify the user that we upgraded their format
368
245
        self.assertEqualDiff(
369
 
            'Source repository format does not support stacking, using format:\n'
 
246
            'Source format does not support stacking, using format:'
 
247
            ' \'1.6.1-rich-root\'\n'
370
248
            '  Packs 5 rich-root (adds stacking support, requires bzr 1.6.1)\n'
371
 
            'Source branch format does not support stacking, using format:\n'
372
 
            '  Branch format 7\n'
373
 
            'Doing on-the-fly conversion from RepositoryFormatKnitPack4() to RepositoryFormatKnitPack5RichRoot().\n'
374
 
            'This may take some time. Upgrade the repositories to the same format for better performance.\n'
 
249
            '\n'
375
250
            'Created new stacked branch referring to %s.\n' % (trunk.base,),
376
251
            err)
377
252
 
378
253
 
379
 
class TestSmartServerBranching(ExternalBase):
380
 
 
381
 
    def test_branch_from_trivial_branch_to_same_server_branch_acceptance(self):
382
 
        self.setup_smart_server_with_call_log()
383
 
        t = self.make_branch_and_tree('from')
384
 
        for count in range(9):
385
 
            t.commit(message='commit %d' % count)
386
 
        self.reset_smart_call_log()
387
 
        out, err = self.run_bzr(['branch', self.get_url('from'),
388
 
            self.get_url('target')])
389
 
        # This figure represent the amount of work to perform this use case. It
390
 
        # is entirely ok to reduce this number if a test fails due to rpc_count
391
 
        # being too low. If rpc_count increases, more network roundtrips have
392
 
        # become necessary for this use case. Please do not adjust this number
393
 
        # upwards without agreement from bzr's network support maintainers.
394
 
        self.assertLength(38, self.hpss_calls)
395
 
 
396
 
    def test_branch_from_trivial_branch_streaming_acceptance(self):
397
 
        self.setup_smart_server_with_call_log()
398
 
        t = self.make_branch_and_tree('from')
399
 
        for count in range(9):
400
 
            t.commit(message='commit %d' % count)
401
 
        self.reset_smart_call_log()
402
 
        out, err = self.run_bzr(['branch', self.get_url('from'),
403
 
            'local-target'])
404
 
        # This figure represent the amount of work to perform this use case. It
405
 
        # is entirely ok to reduce this number if a test fails due to rpc_count
406
 
        # being too low. If rpc_count increases, more network roundtrips have
407
 
        # become necessary for this use case. Please do not adjust this number
408
 
        # upwards without agreement from bzr's network support maintainers.
409
 
        self.assertLength(10, self.hpss_calls)
410
 
 
411
 
    def test_branch_from_trivial_stacked_branch_streaming_acceptance(self):
412
 
        self.setup_smart_server_with_call_log()
413
 
        t = self.make_branch_and_tree('trunk')
414
 
        for count in range(8):
415
 
            t.commit(message='commit %d' % count)
416
 
        tree2 = t.branch.bzrdir.sprout('feature', stacked=True
417
 
            ).open_workingtree()
418
 
        local_tree = t.branch.bzrdir.sprout('local-working').open_workingtree()
419
 
        local_tree.commit('feature change')
420
 
        local_tree.branch.push(tree2.branch)
421
 
        self.reset_smart_call_log()
422
 
        out, err = self.run_bzr(['branch', self.get_url('feature'),
423
 
            'local-target'])
424
 
        # This figure represent the amount of work to perform this use case. It
425
 
        # is entirely ok to reduce this number if a test fails due to rpc_count
426
 
        # being too low. If rpc_count increases, more network roundtrips have
427
 
        # become necessary for this use case. Please do not adjust this number
428
 
        # upwards without agreement from bzr's network support maintainers.
429
 
        self.assertLength(15, self.hpss_calls)
430
 
 
431
254
 
432
255
class TestRemoteBranch(TestCaseWithSFTPServer):
433
256