~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Robert Collins
  • Date: 2005-08-23 06:52:09 UTC
  • mto: (974.1.50) (1185.1.10) (1092.3.1)
  • mto: This revision was merged to the branch mainline in revision 1139.
  • Revision ID: robertc@robertcollins.net-20050823065209-81cd5962c401751b
move io redirection into each test case from the global runner

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 (branch, bzrdir, errors, repository)
23
 
from bzrlib.repofmt.knitrepo import RepositoryFormatKnit1
24
 
from bzrlib.tests.blackbox import ExternalBase
25
 
from bzrlib.tests import HardlinkFeature
26
 
from bzrlib.tests.test_sftp_transport import TestCaseWithSFTPServer
27
 
from bzrlib.urlutils import local_path_to_url, strip_trailing_slash
28
 
from bzrlib.workingtree import WorkingTree
29
 
 
30
 
 
31
 
class TestBranch(ExternalBase):
32
 
 
33
 
    def example_branch(self, path='.'):
34
 
        tree = self.make_branch_and_tree(path)
35
 
        self.build_tree_contents([(path + '/hello', 'foo')])
36
 
        tree.add('hello')
37
 
        tree.commit(message='setup')
38
 
        self.build_tree_contents([(path + '/goodbye', 'baz')])
39
 
        tree.add('goodbye')
40
 
        tree.commit(message='setup')
41
 
 
42
 
    def test_branch(self):
43
 
        """Branch from one branch to another."""
44
 
        self.example_branch('a')
45
 
        self.run_bzr('branch a b')
46
 
        b = branch.Branch.open('b')
47
 
        self.run_bzr('branch a c -r 1')
48
 
        # previously was erroneously created by branching
49
 
        self.assertFalse(b._transport.has('branch-name'))
50
 
        b.bzrdir.open_workingtree().commit(message='foo', allow_pointless=True)
51
 
 
52
 
    def test_branch_only_copies_history(self):
53
 
        # Knit branches should only push the history for the current revision.
54
 
        format = bzrdir.BzrDirMetaFormat1()
55
 
        format.repository_format = RepositoryFormatKnit1()
56
 
        shared_repo = self.make_repository('repo', format=format, shared=True)
57
 
        shared_repo.set_make_working_trees(True)
58
 
 
59
 
        def make_shared_tree(path):
60
 
            shared_repo.bzrdir.root_transport.mkdir(path)
61
 
            shared_repo.bzrdir.create_branch_convenience('repo/' + path)
62
 
            return WorkingTree.open('repo/' + path)
63
 
        tree_a = make_shared_tree('a')
64
 
        self.build_tree(['repo/a/file'])
65
 
        tree_a.add('file')
66
 
        tree_a.commit('commit a-1', rev_id='a-1')
67
 
        f = open('repo/a/file', 'ab')
68
 
        f.write('more stuff\n')
69
 
        f.close()
70
 
        tree_a.commit('commit a-2', rev_id='a-2')
71
 
 
72
 
        tree_b = make_shared_tree('b')
73
 
        self.build_tree(['repo/b/file'])
74
 
        tree_b.add('file')
75
 
        tree_b.commit('commit b-1', rev_id='b-1')
76
 
 
77
 
        self.assertTrue(shared_repo.has_revision('a-1'))
78
 
        self.assertTrue(shared_repo.has_revision('a-2'))
79
 
        self.assertTrue(shared_repo.has_revision('b-1'))
80
 
 
81
 
        # Now that we have a repository with shared files, make sure
82
 
        # that things aren't copied out by a 'branch'
83
 
        self.run_bzr('branch repo/b branch-b')
84
 
        pushed_tree = WorkingTree.open('branch-b')
85
 
        pushed_repo = pushed_tree.branch.repository
86
 
        self.assertFalse(pushed_repo.has_revision('a-1'))
87
 
        self.assertFalse(pushed_repo.has_revision('a-2'))
88
 
        self.assertTrue(pushed_repo.has_revision('b-1'))
89
 
 
90
 
    def test_branch_hardlink(self):
91
 
        self.requireFeature(HardlinkFeature)
92
 
        source = self.make_branch_and_tree('source')
93
 
        self.build_tree(['source/file1'])
94
 
        source.add('file1')
95
 
        source.commit('added file')
96
 
        self.run_bzr(['branch', 'source', 'target', '--hardlink'])
97
 
        source_stat = os.stat('source/file1')
98
 
        target_stat = os.stat('target/file1')
99
 
        self.assertEqual(source_stat, target_stat)
100
 
 
101
 
    def test_branch_standalone(self):
102
 
        shared_repo = self.make_repository('repo', shared=True)
103
 
        self.example_branch('source')
104
 
        self.run_bzr('branch --standalone source repo/target')
105
 
        b = branch.Branch.open('repo/target')
106
 
        expected_repo_path = os.path.abspath('repo/target/.bzr/repository')
107
 
        self.assertEqual(strip_trailing_slash(b.repository.base),
108
 
            strip_trailing_slash(local_path_to_url(expected_repo_path)))
109
 
 
110
 
    def test_branch_no_tree(self):
111
 
        self.example_branch('source')
112
 
        self.run_bzr('branch --no-tree source target')
113
 
        self.failIfExists('target/hello')
114
 
        self.failIfExists('target/goodbye')
115
 
 
116
 
    def test_branch_into_existing_dir(self):
117
 
        self.example_branch('a')
118
 
        # existing dir with similar files but no .bzr dir
119
 
        self.build_tree_contents([('b/',)])
120
 
        self.build_tree_contents([('b/hello', 'bar')])  # different content
121
 
        self.build_tree_contents([('b/goodbye', 'baz')])# same content
122
 
        # fails without --use-existing-dir
123
 
        out,err = self.run_bzr('branch a b', retcode=3)
124
 
        self.assertEqual('', out)
125
 
        self.assertEqual('bzr: ERROR: Target directory "b" already exists.\n',
126
 
            err)
127
 
        # force operation
128
 
        self.run_bzr('branch a b --use-existing-dir')
129
 
        # check conflicts
130
 
        self.failUnlessExists('b/hello.moved')
131
 
        self.failIfExists('b/godbye.moved')
132
 
        # we can't branch into branch
133
 
        out,err = self.run_bzr('branch a b --use-existing-dir', retcode=3)
134
 
        self.assertEqual('', out)
135
 
        self.assertEqual('bzr: ERROR: Already a branch: "b".\n', err)
136
 
 
137
 
 
138
 
class TestBranchStacked(ExternalBase):
139
 
    """Tests for branch --stacked"""
140
 
 
141
 
    def check_shallow_branch(self, branch_revid, stacked_on):
142
 
        """Assert that the branch 'newbranch' has been published correctly.
143
 
 
144
 
        :param stacked_on: url of a branch this one is stacked upon.
145
 
        :param branch_revid: a revision id that should be the only
146
 
            revision present in the stacked branch, and it should not be in
147
 
            the reference branch.
148
 
        """
149
 
        new_branch = branch.Branch.open('newbranch')
150
 
        # The branch refers to the mainline
151
 
        self.assertEqual(stacked_on, new_branch.get_stacked_on_url())
152
 
        # and the branch's work was pushed
153
 
        self.assertTrue(new_branch.repository.has_revision(branch_revid))
154
 
        # The newly committed revision shoud be present in the stacked branch,
155
 
        # but not in the stacked-on branch.  Because stacking is set up by the
156
 
        # branch object, if we open the stacked branch's repository directly,
157
 
        # bypassing the branch, we see only what's in the stacked repository.
158
 
        stacked_repo = bzrdir.BzrDir.open('newbranch').open_repository()
159
 
        stacked_repo_revisions = set(stacked_repo.all_revision_ids())
160
 
        if len(stacked_repo_revisions) != 1:
161
 
            self.fail("wrong revisions in stacked repository: %r"
162
 
                % (stacked_repo_revisions,))
163
 
 
164
 
    def assertRevisionInRepository(self, repo_path, revid):
165
 
        """Check that a revision is in a repository, disregarding stacking."""
166
 
        repo = bzrdir.BzrDir.open(repo_path).open_repository()
167
 
        self.assertTrue(repo.has_revision(revid))
168
 
 
169
 
    def assertRevisionNotInRepository(self, repo_path, revid):
170
 
        """Check that a revision is not in a repository, disregarding stacking."""
171
 
        repo = bzrdir.BzrDir.open(repo_path).open_repository()
172
 
        self.assertFalse(repo.has_revision(revid))
173
 
 
174
 
    def assertRevisionsInBranchRepository(self, revid_list, branch_path):
175
 
        repo = branch.Branch.open(branch_path).repository
176
 
        self.assertEqual(set(revid_list),
177
 
            repo.has_revisions(revid_list))
178
 
 
179
 
    def test_branch_stacked_branch_not_stacked(self):
180
 
        """Branching a stacked branch is not stacked by default"""
181
 
        # We have a mainline
182
 
        trunk_tree = self.make_branch_and_tree('target',
183
 
            format='1.9')
184
 
        trunk_tree.commit('mainline')
185
 
        # and a branch from it which is stacked
186
 
        branch_tree = self.make_branch_and_tree('branch',
187
 
            format='1.9')
188
 
        branch_tree.branch.set_stacked_on_url(trunk_tree.branch.base)
189
 
        # with some work on it
190
 
        branch_tree.commit('moar work plz')
191
 
        # branching our local branch gives us a new stacked branch pointing at
192
 
        # mainline.
193
 
        out, err = self.run_bzr(['branch', 'branch', 'newbranch'])
194
 
        self.assertEqual('', out)
195
 
        self.assertEqual('Branched 1 revision(s).\n',
196
 
            err)
197
 
        # it should have preserved the branch format, and so it should be
198
 
        # capable of supporting stacking, but not actually have a stacked_on
199
 
        # branch configured
200
 
        self.assertRaises(errors.NotStacked,
201
 
            bzrdir.BzrDir.open('newbranch').open_branch().get_stacked_on_url)
202
 
 
203
 
    def test_branch_stacked_branch_stacked(self):
204
 
        """Asking to stack on a stacked branch does work"""
205
 
        # We have a mainline
206
 
        trunk_tree = self.make_branch_and_tree('target',
207
 
            format='1.9')
208
 
        trunk_revid = trunk_tree.commit('mainline')
209
 
        # and a branch from it which is stacked
210
 
        branch_tree = self.make_branch_and_tree('branch',
211
 
            format='1.9')
212
 
        branch_tree.branch.set_stacked_on_url(trunk_tree.branch.base)
213
 
        # with some work on it
214
 
        branch_revid = branch_tree.commit('moar work plz')
215
 
        # you can chain branches on from there
216
 
        out, err = self.run_bzr(['branch', 'branch', '--stacked', 'branch2'])
217
 
        self.assertEqual('', out)
218
 
        self.assertEqual('Created new stacked branch referring to %s.\n' %
219
 
            branch_tree.branch.base, err)
220
 
        self.assertEqual(branch_tree.branch.base,
221
 
            branch.Branch.open('branch2').get_stacked_on_url())
222
 
        branch2_tree = WorkingTree.open('branch2')
223
 
        branch2_revid = branch2_tree.commit('work on second stacked branch')
224
 
        self.assertRevisionInRepository('branch2', branch2_revid)
225
 
        self.assertRevisionsInBranchRepository(
226
 
            [trunk_revid, branch_revid, branch2_revid],
227
 
            'branch2')
228
 
 
229
 
    def test_branch_stacked(self):
230
 
        # We have a mainline
231
 
        trunk_tree = self.make_branch_and_tree('mainline',
232
 
            format='1.9')
233
 
        original_revid = trunk_tree.commit('mainline')
234
 
        self.assertRevisionInRepository('mainline', original_revid)
235
 
        # and a branch from it which is stacked
236
 
        out, err = self.run_bzr(['branch', '--stacked', 'mainline',
237
 
            'newbranch'])
238
 
        self.assertEqual('', out)
239
 
        self.assertEqual('Created new stacked branch referring to %s.\n' %
240
 
            trunk_tree.branch.base, err)
241
 
        self.assertRevisionNotInRepository('newbranch', original_revid)
242
 
        new_tree = WorkingTree.open('newbranch')
243
 
        new_revid = new_tree.commit('new work')
244
 
        self.check_shallow_branch(new_revid, trunk_tree.branch.base)
245
 
 
246
 
    def test_branch_stacked_from_smart_server(self):
247
 
        # We can branch stacking on a smart server
248
 
        from bzrlib.smart.server import SmartTCPServer_for_testing
249
 
        self.transport_server = SmartTCPServer_for_testing
250
 
        trunk = self.make_branch('mainline', format='1.9')
251
 
        out, err = self.run_bzr(
252
 
            ['branch', '--stacked', self.get_url('mainline'), 'shallow'])
253
 
 
254
 
    def test_branch_stacked_from_non_stacked_format(self):
255
 
        """The origin format doesn't support stacking"""
256
 
        trunk = self.make_branch('trunk', format='pack-0.92')
257
 
        out, err = self.run_bzr(
258
 
            ['branch', '--stacked', 'trunk', 'shallow'])
259
 
        # We should notify the user that we upgraded their format
260
 
        self.assertEqualDiff(
261
 
            'Source repository format does not support stacking, using format:\n'
262
 
            '  Packs 5 (adds stacking support, requires bzr 1.6)\n'
263
 
            'Source branch format does not support stacking, using format:\n'
264
 
            '  Branch format 7\n'
265
 
            'Created new stacked branch referring to %s.\n' % (trunk.base,),
266
 
            err)
267
 
 
268
 
    def test_branch_stacked_from_rich_root_non_stackable(self):
269
 
        trunk = self.make_branch('trunk', format='rich-root-pack')
270
 
        out, err = self.run_bzr(
271
 
            ['branch', '--stacked', 'trunk', 'shallow'])
272
 
        # We should notify the user that we upgraded their format
273
 
        self.assertEqualDiff(
274
 
            'Source repository format does not support stacking, using format:\n'
275
 
            '  Packs 5 rich-root (adds stacking support, requires bzr 1.6.1)\n'
276
 
            'Source branch format does not support stacking, using format:\n'
277
 
            '  Branch format 7\n'
278
 
            'Created new stacked branch referring to %s.\n' % (trunk.base,),
279
 
            err)
280
 
 
281
 
 
282
 
class TestSmartServerBranching(ExternalBase):
283
 
 
284
 
    def test_branch_from_trivial_branch_to_same_server_branch_acceptance(self):
285
 
        self.setup_smart_server_with_call_log()
286
 
        t = self.make_branch_and_tree('from')
287
 
        for count in range(9):
288
 
            t.commit(message='commit %d' % count)
289
 
        self.reset_smart_call_log()
290
 
        out, err = self.run_bzr(['branch', self.get_url('from'),
291
 
            self.get_url('target')])
292
 
        # This figure represent the amount of work to perform this use case. It
293
 
        # is entirely ok to reduce this number if a test fails due to rpc_count
294
 
        # being too low. If rpc_count increases, more network roundtrips have
295
 
        # become necessary for this use case. Please do not adjust this number
296
 
        # upwards without agreement from bzr's network support maintainers.
297
 
        self.assertLength(38, self.hpss_calls)
298
 
 
299
 
    def test_branch_from_trivial_branch_streaming_acceptance(self):
300
 
        self.setup_smart_server_with_call_log()
301
 
        t = self.make_branch_and_tree('from')
302
 
        for count in range(9):
303
 
            t.commit(message='commit %d' % count)
304
 
        self.reset_smart_call_log()
305
 
        out, err = self.run_bzr(['branch', self.get_url('from'),
306
 
            'local-target'])
307
 
        # This figure represent the amount of work to perform this use case. It
308
 
        # is entirely ok to reduce this number if a test fails due to rpc_count
309
 
        # being too low. If rpc_count increases, more network roundtrips have
310
 
        # become necessary for this use case. Please do not adjust this number
311
 
        # upwards without agreement from bzr's network support maintainers.
312
 
        self.assertLength(10, self.hpss_calls)
313
 
 
314
 
    def test_branch_from_trivial_stacked_branch_streaming_acceptance(self):
315
 
        self.setup_smart_server_with_call_log()
316
 
        t = self.make_branch_and_tree('trunk')
317
 
        for count in range(8):
318
 
            t.commit(message='commit %d' % count)
319
 
        tree2 = t.branch.bzrdir.sprout('feature', stacked=True
320
 
            ).open_workingtree()
321
 
        tree2.commit('feature change')
322
 
        self.reset_smart_call_log()
323
 
        out, err = self.run_bzr(['branch', self.get_url('feature'),
324
 
            'local-target'])
325
 
        # This figure represent the amount of work to perform this use case. It
326
 
        # is entirely ok to reduce this number if a test fails due to rpc_count
327
 
        # being too low. If rpc_count increases, more network roundtrips have
328
 
        # become necessary for this use case. Please do not adjust this number
329
 
        # upwards without agreement from bzr's network support maintainers.
330
 
        self.assertLength(15, self.hpss_calls)
331
 
 
332
 
 
333
 
class TestRemoteBranch(TestCaseWithSFTPServer):
334
 
 
335
 
    def setUp(self):
336
 
        super(TestRemoteBranch, self).setUp()
337
 
        tree = self.make_branch_and_tree('branch')
338
 
        self.build_tree_contents([('branch/file', 'file content\n')])
339
 
        tree.add('file')
340
 
        tree.commit('file created')
341
 
 
342
 
    def test_branch_local_remote(self):
343
 
        self.run_bzr(['branch', 'branch', self.get_url('remote')])
344
 
        t = self.get_transport()
345
 
        # Ensure that no working tree what created remotely
346
 
        self.assertFalse(t.has('remote/file'))
347
 
 
348
 
    def test_branch_remote_remote(self):
349
 
        # Light cheat: we access the branch remotely
350
 
        self.run_bzr(['branch', self.get_url('branch'),
351
 
                      self.get_url('remote')])
352
 
        t = self.get_transport()
353
 
        # Ensure that no working tree what created remotely
354
 
        self.assertFalse(t.has('remote/file'))
355