/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/blackbox/test_branch.py

  • Committer: John Arbash Meinel
  • Date: 2010-01-12 22:51:31 UTC
  • mto: This revision was merged to the branch mainline in revision 4955.
  • Revision ID: john@arbash-meinel.com-20100112225131-he8h411p6aeeb947
Delay grabbing an output stream until we actually go to show a diff.

This makes the test suite happy, but it also seems to be reasonable.
If we aren't going to write anything, we don't need to hold an
output stream open.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005, 2006, 2008, 2009 Canonical Ltd
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
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
 
16
 
 
17
 
 
18
"""Black-box tests for bzr branch."""
 
19
 
 
20
import os
 
21
 
 
22
from bzrlib import (
 
23
    branch,
 
24
    bzrdir,
 
25
    errors,
 
26
    repository,
 
27
    revision as _mod_revision,
 
28
    )
 
29
from bzrlib.repofmt.knitrepo import RepositoryFormatKnit1
 
30
from bzrlib.tests.blackbox import ExternalBase
 
31
from bzrlib.tests import (
 
32
    KnownFailure,
 
33
    HardlinkFeature,
 
34
    )
 
35
from bzrlib.tests.test_sftp_transport import TestCaseWithSFTPServer
 
36
from bzrlib.urlutils import local_path_to_url, strip_trailing_slash
 
37
from bzrlib.workingtree import WorkingTree
 
38
 
 
39
 
 
40
class TestBranch(ExternalBase):
 
41
 
 
42
    def example_branch(self, path='.'):
 
43
        tree = self.make_branch_and_tree(path)
 
44
        self.build_tree_contents([(path + '/hello', 'foo')])
 
45
        tree.add('hello')
 
46
        tree.commit(message='setup')
 
47
        self.build_tree_contents([(path + '/goodbye', 'baz')])
 
48
        tree.add('goodbye')
 
49
        tree.commit(message='setup')
 
50
 
 
51
    def test_branch(self):
 
52
        """Branch from one branch to another."""
 
53
        self.example_branch('a')
 
54
        self.run_bzr('branch a b')
 
55
        b = branch.Branch.open('b')
 
56
        self.run_bzr('branch a c -r 1')
 
57
        # previously was erroneously created by branching
 
58
        self.assertFalse(b._transport.has('branch-name'))
 
59
        b.bzrdir.open_workingtree().commit(message='foo', allow_pointless=True)
 
60
 
 
61
    def test_branch_switch_no_branch(self):
 
62
        # No branch in the current directory:
 
63
        #  => new branch will be created, but switch fails
 
64
        self.example_branch('a')
 
65
        self.make_repository('current')
 
66
        self.run_bzr_error(['No WorkingTree exists for'],
 
67
            'branch --switch ../a ../b', working_dir='current')
 
68
        a = branch.Branch.open('a')
 
69
        b = branch.Branch.open('b')
 
70
        self.assertEqual(a.last_revision(), b.last_revision())
 
71
 
 
72
    def test_branch_switch_no_wt(self):
 
73
        # No working tree in the current directory:
 
74
        #  => new branch will be created, but switch fails and the current
 
75
        #     branch is unmodified
 
76
        self.example_branch('a')
 
77
        self.make_branch('current')
 
78
        self.run_bzr_error(['No WorkingTree exists for'],
 
79
            'branch --switch ../a ../b', working_dir='current')
 
80
        a = branch.Branch.open('a')
 
81
        b = branch.Branch.open('b')
 
82
        self.assertEqual(a.last_revision(), b.last_revision())
 
83
        work = branch.Branch.open('current')
 
84
        self.assertEqual(work.last_revision(), _mod_revision.NULL_REVISION)
 
85
 
 
86
    def test_branch_switch_no_checkout(self):
 
87
        # Standalone branch 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_and_tree('current')
 
92
        self.run_bzr_error(['Cannot switch a branch, only a checkout'],
 
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_checkout(self):
 
101
        # Checkout in the current directory:
 
102
        #  => new branch will be created and checkout bound to the new branch
 
103
        self.example_branch('a')
 
104
        self.run_bzr('checkout a current')
 
105
        out, err = self.run_bzr('branch --switch ../a ../b', working_dir='current')
 
106
        a = branch.Branch.open('a')
 
107
        b = branch.Branch.open('b')
 
108
        self.assertEqual(a.last_revision(), b.last_revision())
 
109
        work = WorkingTree.open('current')
 
110
        self.assertEndsWith(work.branch.get_bound_location(), '/b/')
 
111
        self.assertContainsRe(err, "Switched to branch: .*/b/")
 
112
 
 
113
    def test_branch_switch_lightweight_checkout(self):
 
114
        # Lightweight checkout in the current directory:
 
115
        #  => new branch will be created and lightweight checkout pointed to
 
116
        #     the new branch
 
117
        self.example_branch('a')
 
118
        self.run_bzr('checkout --lightweight 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.base, '/b/')
 
125
        self.assertContainsRe(err, "Switched to branch: .*/b/")
 
126
 
 
127
    def test_branch_only_copies_history(self):
 
128
        # Knit branches should only push the history for the current revision.
 
129
        format = bzrdir.BzrDirMetaFormat1()
 
130
        format.repository_format = RepositoryFormatKnit1()
 
131
        shared_repo = self.make_repository('repo', format=format, shared=True)
 
132
        shared_repo.set_make_working_trees(True)
 
133
 
 
134
        def make_shared_tree(path):
 
135
            shared_repo.bzrdir.root_transport.mkdir(path)
 
136
            shared_repo.bzrdir.create_branch_convenience('repo/' + path)
 
137
            return WorkingTree.open('repo/' + path)
 
138
        tree_a = make_shared_tree('a')
 
139
        self.build_tree(['repo/a/file'])
 
140
        tree_a.add('file')
 
141
        tree_a.commit('commit a-1', rev_id='a-1')
 
142
        f = open('repo/a/file', 'ab')
 
143
        f.write('more stuff\n')
 
144
        f.close()
 
145
        tree_a.commit('commit a-2', rev_id='a-2')
 
146
 
 
147
        tree_b = make_shared_tree('b')
 
148
        self.build_tree(['repo/b/file'])
 
149
        tree_b.add('file')
 
150
        tree_b.commit('commit b-1', rev_id='b-1')
 
151
 
 
152
        self.assertTrue(shared_repo.has_revision('a-1'))
 
153
        self.assertTrue(shared_repo.has_revision('a-2'))
 
154
        self.assertTrue(shared_repo.has_revision('b-1'))
 
155
 
 
156
        # Now that we have a repository with shared files, make sure
 
157
        # that things aren't copied out by a 'branch'
 
158
        self.run_bzr('branch repo/b branch-b')
 
159
        pushed_tree = WorkingTree.open('branch-b')
 
160
        pushed_repo = pushed_tree.branch.repository
 
161
        self.assertFalse(pushed_repo.has_revision('a-1'))
 
162
        self.assertFalse(pushed_repo.has_revision('a-2'))
 
163
        self.assertTrue(pushed_repo.has_revision('b-1'))
 
164
 
 
165
    def test_branch_hardlink(self):
 
166
        self.requireFeature(HardlinkFeature)
 
167
        source = self.make_branch_and_tree('source')
 
168
        self.build_tree(['source/file1'])
 
169
        source.add('file1')
 
170
        source.commit('added file')
 
171
        out, err = self.run_bzr(['branch', 'source', 'target', '--hardlink'])
 
172
        source_stat = os.stat('source/file1')
 
173
        target_stat = os.stat('target/file1')
 
174
        self.assertEqual(source_stat, target_stat)
 
175
 
 
176
    def test_branch_standalone(self):
 
177
        shared_repo = self.make_repository('repo', shared=True)
 
178
        self.example_branch('source')
 
179
        self.run_bzr('branch --standalone source repo/target')
 
180
        b = branch.Branch.open('repo/target')
 
181
        expected_repo_path = os.path.abspath('repo/target/.bzr/repository')
 
182
        self.assertEqual(strip_trailing_slash(b.repository.base),
 
183
            strip_trailing_slash(local_path_to_url(expected_repo_path)))
 
184
 
 
185
    def test_branch_no_tree(self):
 
186
        self.example_branch('source')
 
187
        self.run_bzr('branch --no-tree source target')
 
188
        self.failIfExists('target/hello')
 
189
        self.failIfExists('target/goodbye')
 
190
 
 
191
    def test_branch_into_existing_dir(self):
 
192
        self.example_branch('a')
 
193
        # existing dir with similar files but no .bzr dir
 
194
        self.build_tree_contents([('b/',)])
 
195
        self.build_tree_contents([('b/hello', 'bar')])  # different content
 
196
        self.build_tree_contents([('b/goodbye', 'baz')])# same content
 
197
        # fails without --use-existing-dir
 
198
        out,err = self.run_bzr('branch a b', retcode=3)
 
199
        self.assertEqual('', out)
 
200
        self.assertEqual('bzr: ERROR: Target directory "b" already exists.\n',
 
201
            err)
 
202
        # force operation
 
203
        self.run_bzr('branch a b --use-existing-dir')
 
204
        # check conflicts
 
205
        self.failUnlessExists('b/hello.moved')
 
206
        self.failIfExists('b/godbye.moved')
 
207
        # we can't branch into branch
 
208
        out,err = self.run_bzr('branch a b --use-existing-dir', retcode=3)
 
209
        self.assertEqual('', out)
 
210
        self.assertEqual('bzr: ERROR: Already a branch: "b".\n', err)
 
211
 
 
212
    def test_branch_bind(self):
 
213
        self.example_branch('a')
 
214
        out, err = self.run_bzr('branch a b --bind')
 
215
        self.assertEndsWith(err, "New branch bound to a\n")
 
216
        b = branch.Branch.open('b')
 
217
        self.assertEndsWith(b.get_bound_location(), '/a/')
 
218
 
 
219
 
 
220
class TestBranchStacked(ExternalBase):
 
221
    """Tests for branch --stacked"""
 
222
 
 
223
    def assertRevisionInRepository(self, repo_path, revid):
 
224
        """Check that a revision is in a repository, disregarding stacking."""
 
225
        repo = bzrdir.BzrDir.open(repo_path).open_repository()
 
226
        self.assertTrue(repo.has_revision(revid))
 
227
 
 
228
    def assertRevisionNotInRepository(self, repo_path, revid):
 
229
        """Check that a revision is not in a repository, disregarding stacking."""
 
230
        repo = bzrdir.BzrDir.open(repo_path).open_repository()
 
231
        self.assertFalse(repo.has_revision(revid))
 
232
 
 
233
    def assertRevisionsInBranchRepository(self, revid_list, branch_path):
 
234
        repo = branch.Branch.open(branch_path).repository
 
235
        self.assertEqual(set(revid_list),
 
236
            repo.has_revisions(revid_list))
 
237
 
 
238
    def test_branch_stacked_branch_not_stacked(self):
 
239
        """Branching a stacked branch is not stacked by default"""
 
240
        # We have a mainline
 
241
        trunk_tree = self.make_branch_and_tree('target',
 
242
            format='1.9')
 
243
        trunk_tree.commit('mainline')
 
244
        # and a branch from it which is stacked
 
245
        branch_tree = self.make_branch_and_tree('branch',
 
246
            format='1.9')
 
247
        branch_tree.branch.set_stacked_on_url(trunk_tree.branch.base)
 
248
        # with some work on it
 
249
        work_tree = trunk_tree.branch.bzrdir.sprout('local').open_workingtree()
 
250
        work_tree.commit('moar work plz')
 
251
        work_tree.branch.push(branch_tree.branch)
 
252
        # branching our local branch gives us a new stacked branch pointing at
 
253
        # mainline.
 
254
        out, err = self.run_bzr(['branch', 'branch', 'newbranch'])
 
255
        self.assertEqual('', out)
 
256
        self.assertEqual('Branched 2 revision(s).\n',
 
257
            err)
 
258
        # it should have preserved the branch format, and so it should be
 
259
        # capable of supporting stacking, but not actually have a stacked_on
 
260
        # branch configured
 
261
        self.assertRaises(errors.NotStacked,
 
262
            bzrdir.BzrDir.open('newbranch').open_branch().get_stacked_on_url)
 
263
 
 
264
    def test_branch_stacked_branch_stacked(self):
 
265
        """Asking to stack on a stacked branch does work"""
 
266
        # We have a mainline
 
267
        trunk_tree = self.make_branch_and_tree('target',
 
268
            format='1.9')
 
269
        trunk_revid = trunk_tree.commit('mainline')
 
270
        # and a branch from it which is stacked
 
271
        branch_tree = self.make_branch_and_tree('branch',
 
272
            format='1.9')
 
273
        branch_tree.branch.set_stacked_on_url(trunk_tree.branch.base)
 
274
        # with some work on it
 
275
        work_tree = trunk_tree.branch.bzrdir.sprout('local').open_workingtree()
 
276
        branch_revid = work_tree.commit('moar work plz')
 
277
        work_tree.branch.push(branch_tree.branch)
 
278
        # you can chain branches on from there
 
279
        out, err = self.run_bzr(['branch', 'branch', '--stacked', 'branch2'])
 
280
        self.assertEqual('', out)
 
281
        self.assertEqual('Created new stacked branch referring to %s.\n' %
 
282
            branch_tree.branch.base, err)
 
283
        self.assertEqual(branch_tree.branch.base,
 
284
            branch.Branch.open('branch2').get_stacked_on_url())
 
285
        branch2_tree = WorkingTree.open('branch2')
 
286
        branch2_revid = work_tree.commit('work on second stacked branch')
 
287
        work_tree.branch.push(branch2_tree.branch)
 
288
        self.assertRevisionInRepository('branch2', branch2_revid)
 
289
        self.assertRevisionsInBranchRepository(
 
290
            [trunk_revid, branch_revid, branch2_revid],
 
291
            'branch2')
 
292
 
 
293
    def test_branch_stacked(self):
 
294
        # We have a mainline
 
295
        trunk_tree = self.make_branch_and_tree('mainline',
 
296
            format='1.9')
 
297
        original_revid = trunk_tree.commit('mainline')
 
298
        self.assertRevisionInRepository('mainline', original_revid)
 
299
        # and a branch from it which is stacked
 
300
        out, err = self.run_bzr(['branch', '--stacked', 'mainline',
 
301
            'newbranch'])
 
302
        self.assertEqual('', out)
 
303
        self.assertEqual('Created new stacked branch referring to %s.\n' %
 
304
            trunk_tree.branch.base, err)
 
305
        self.assertRevisionNotInRepository('newbranch', original_revid)
 
306
        new_branch = branch.Branch.open('newbranch')
 
307
        self.assertEqual(trunk_tree.branch.base, new_branch.get_stacked_on_url())
 
308
 
 
309
    def test_branch_stacked_from_smart_server(self):
 
310
        # We can branch stacking on a smart server
 
311
        from bzrlib.smart.server import SmartTCPServer_for_testing
 
312
        self.transport_server = SmartTCPServer_for_testing
 
313
        trunk = self.make_branch('mainline', format='1.9')
 
314
        out, err = self.run_bzr(
 
315
            ['branch', '--stacked', self.get_url('mainline'), 'shallow'])
 
316
 
 
317
    def test_branch_stacked_from_non_stacked_format(self):
 
318
        """The origin format doesn't support stacking"""
 
319
        trunk = self.make_branch('trunk', format='pack-0.92')
 
320
        out, err = self.run_bzr(
 
321
            ['branch', '--stacked', 'trunk', 'shallow'])
 
322
        # We should notify the user that we upgraded their format
 
323
        self.assertEqualDiff(
 
324
            'Source repository format does not support stacking, using format:\n'
 
325
            '  Packs 5 (adds stacking support, requires bzr 1.6)\n'
 
326
            'Source branch format does not support stacking, using format:\n'
 
327
            '  Branch format 7\n'
 
328
            'Created new stacked branch referring to %s.\n' % (trunk.base,),
 
329
            err)
 
330
 
 
331
    def test_branch_stacked_from_rich_root_non_stackable(self):
 
332
        trunk = self.make_branch('trunk', format='rich-root-pack')
 
333
        out, err = self.run_bzr(
 
334
            ['branch', '--stacked', 'trunk', 'shallow'])
 
335
        # We should notify the user that we upgraded their format
 
336
        self.assertEqualDiff(
 
337
            'Source repository format does not support stacking, using format:\n'
 
338
            '  Packs 5 rich-root (adds stacking support, requires bzr 1.6.1)\n'
 
339
            'Source branch format does not support stacking, using format:\n'
 
340
            '  Branch format 7\n'
 
341
            'Created new stacked branch referring to %s.\n' % (trunk.base,),
 
342
            err)
 
343
 
 
344
 
 
345
class TestSmartServerBranching(ExternalBase):
 
346
 
 
347
    def test_branch_from_trivial_branch_to_same_server_branch_acceptance(self):
 
348
        self.setup_smart_server_with_call_log()
 
349
        t = self.make_branch_and_tree('from')
 
350
        for count in range(9):
 
351
            t.commit(message='commit %d' % count)
 
352
        self.reset_smart_call_log()
 
353
        out, err = self.run_bzr(['branch', self.get_url('from'),
 
354
            self.get_url('target')])
 
355
        # This figure represent the amount of work to perform this use case. It
 
356
        # is entirely ok to reduce this number if a test fails due to rpc_count
 
357
        # being too low. If rpc_count increases, more network roundtrips have
 
358
        # become necessary for this use case. Please do not adjust this number
 
359
        # upwards without agreement from bzr's network support maintainers.
 
360
        self.assertLength(38, self.hpss_calls)
 
361
 
 
362
    def test_branch_from_trivial_branch_streaming_acceptance(self):
 
363
        self.setup_smart_server_with_call_log()
 
364
        t = self.make_branch_and_tree('from')
 
365
        for count in range(9):
 
366
            t.commit(message='commit %d' % count)
 
367
        self.reset_smart_call_log()
 
368
        out, err = self.run_bzr(['branch', self.get_url('from'),
 
369
            'local-target'])
 
370
        # This figure represent the amount of work to perform this use case. It
 
371
        # is entirely ok to reduce this number if a test fails due to rpc_count
 
372
        # being too low. If rpc_count increases, more network roundtrips have
 
373
        # become necessary for this use case. Please do not adjust this number
 
374
        # upwards without agreement from bzr's network support maintainers.
 
375
        self.assertLength(10, self.hpss_calls)
 
376
 
 
377
    def test_branch_from_trivial_stacked_branch_streaming_acceptance(self):
 
378
        self.setup_smart_server_with_call_log()
 
379
        t = self.make_branch_and_tree('trunk')
 
380
        for count in range(8):
 
381
            t.commit(message='commit %d' % count)
 
382
        tree2 = t.branch.bzrdir.sprout('feature', stacked=True
 
383
            ).open_workingtree()
 
384
        local_tree = t.branch.bzrdir.sprout('local-working').open_workingtree()
 
385
        local_tree.commit('feature change')
 
386
        local_tree.branch.push(tree2.branch)
 
387
        self.reset_smart_call_log()
 
388
        out, err = self.run_bzr(['branch', self.get_url('feature'),
 
389
            'local-target'])
 
390
        # This figure represent the amount of work to perform this use case. It
 
391
        # is entirely ok to reduce this number if a test fails due to rpc_count
 
392
        # being too low. If rpc_count increases, more network roundtrips have
 
393
        # become necessary for this use case. Please do not adjust this number
 
394
        # upwards without agreement from bzr's network support maintainers.
 
395
        self.assertLength(15, self.hpss_calls)
 
396
 
 
397
 
 
398
class TestRemoteBranch(TestCaseWithSFTPServer):
 
399
 
 
400
    def setUp(self):
 
401
        super(TestRemoteBranch, self).setUp()
 
402
        tree = self.make_branch_and_tree('branch')
 
403
        self.build_tree_contents([('branch/file', 'file content\n')])
 
404
        tree.add('file')
 
405
        tree.commit('file created')
 
406
 
 
407
    def test_branch_local_remote(self):
 
408
        self.run_bzr(['branch', 'branch', self.get_url('remote')])
 
409
        t = self.get_transport()
 
410
        # Ensure that no working tree what created remotely
 
411
        self.assertFalse(t.has('remote/file'))
 
412
 
 
413
    def test_branch_remote_remote(self):
 
414
        # Light cheat: we access the branch remotely
 
415
        self.run_bzr(['branch', self.get_url('branch'),
 
416
                      self.get_url('remote')])
 
417
        t = self.get_transport()
 
418
        # Ensure that no working tree what created remotely
 
419
        self.assertFalse(t.has('remote/file'))
 
420