~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: 2007-04-04 06:17:31 UTC
  • mto: This revision was merged to the branch mainline in revision 2397.
  • Revision ID: mbp@sourcefrog.net-20070404061731-tt2xrzllqhbodn83
Contents of TODO file moved into bug tracker

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2008, 2009 Canonical Ltd
 
1
# Copyright (C) 2005, 2006 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 (branch, bzrdir, errors, repository)
 
22
from bzrlib import branch, bzrdir
23
23
from bzrlib.repofmt.knitrepo import RepositoryFormatKnit1
24
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
25
from bzrlib.workingtree import WorkingTree
29
26
 
30
27
 
31
28
class TestBranch(ExternalBase):
32
29
 
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')
 
30
    def example_branch(test):
 
31
        test.runbzr('init')
 
32
        file('hello', 'wt').write('foo')
 
33
        test.runbzr('add hello')
 
34
        test.runbzr('commit -m setup hello')
 
35
        file('goodbye', 'wt').write('baz')
 
36
        test.runbzr('add goodbye')
 
37
        test.runbzr('commit -m setup goodbye')
41
38
 
42
39
    def test_branch(self):
43
40
        """Branch from one branch to another."""
44
 
        self.example_branch('a')
45
 
        self.run_bzr('branch a b')
 
41
        os.mkdir('a')
 
42
        os.chdir('a')
 
43
        self.example_branch()
 
44
        os.chdir('..')
 
45
        self.runbzr('branch a b')
46
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)
 
47
        self.assertEqual('b\n', b.control_files.get_utf8('branch-name').read())
 
48
        self.runbzr('branch a c -r 1')
 
49
        os.chdir('b')
 
50
        self.runbzr('commit -m foo --unchanged')
 
51
        os.chdir('..')
51
52
 
52
53
    def test_branch_only_copies_history(self):
53
54
        # Knit branches should only push the history for the current revision.
80
81
 
81
82
        # Now that we have a repository with shared files, make sure
82
83
        # that things aren't copied out by a 'branch'
83
 
        self.run_bzr('branch repo/b branch-b')
 
84
        self.run_bzr('branch', 'repo/b', 'branch-b')
84
85
        pushed_tree = WorkingTree.open('branch-b')
85
86
        pushed_repo = pushed_tree.branch.repository
86
87
        self.assertFalse(pushed_repo.has_revision('a-1'))
87
88
        self.assertFalse(pushed_repo.has_revision('a-2'))
88
89
        self.assertTrue(pushed_repo.has_revision('b-1'))
89
90
 
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
 
 
117
 
class TestBranchStacked(ExternalBase):
118
 
    """Tests for branch --stacked"""
119
 
 
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
 
    def assertRevisionInRepository(self, repo_path, revid):
144
 
        """Check that a revision is in a repository, disregarding stacking."""
145
 
        repo = bzrdir.BzrDir.open(repo_path).open_repository()
146
 
        self.assertTrue(repo.has_revision(revid))
147
 
 
148
 
    def assertRevisionNotInRepository(self, repo_path, revid):
149
 
        """Check that a revision is not in a repository, disregarding stacking."""
150
 
        repo = bzrdir.BzrDir.open(repo_path).open_repository()
151
 
        self.assertFalse(repo.has_revision(revid))
152
 
 
153
 
    def assertRevisionsInBranchRepository(self, revid_list, branch_path):
154
 
        repo = branch.Branch.open(branch_path).repository
155
 
        self.assertEqual(set(revid_list),
156
 
            repo.has_revisions(revid_list))
157
 
 
158
 
    def test_branch_stacked_branch_not_stacked(self):
159
 
        """Branching a stacked branch is not stacked by default"""
160
 
        # We have a mainline
161
 
        trunk_tree = self.make_branch_and_tree('target',
162
 
            format='1.9')
163
 
        trunk_tree.commit('mainline')
164
 
        # and a branch from it which is stacked
165
 
        branch_tree = self.make_branch_and_tree('branch',
166
 
            format='1.9')
167
 
        branch_tree.branch.set_stacked_on_url(trunk_tree.branch.base)
168
 
        # with some work on it
169
 
        branch_tree.commit('moar work plz')
170
 
        # branching our local branch gives us a new stacked branch pointing at
171
 
        # mainline.
172
 
        out, err = self.run_bzr(['branch', 'branch', 'newbranch'])
173
 
        self.assertEqual('', out)
174
 
        self.assertEqual('Branched 1 revision(s).\n',
175
 
            err)
176
 
        # it should have preserved the branch format, and so it should be
177
 
        # capable of supporting stacking, but not actually have a stacked_on
178
 
        # branch configured
179
 
        self.assertRaises(errors.NotStacked,
180
 
            bzrdir.BzrDir.open('newbranch').open_branch().get_stacked_on_url)
181
 
 
182
 
    def test_branch_stacked_branch_stacked(self):
183
 
        """Asking to stack on a stacked branch does work"""
184
 
        # We have a mainline
185
 
        trunk_tree = self.make_branch_and_tree('target',
186
 
            format='1.9')
187
 
        trunk_revid = trunk_tree.commit('mainline')
188
 
        # and a branch from it which is stacked
189
 
        branch_tree = self.make_branch_and_tree('branch',
190
 
            format='1.9')
191
 
        branch_tree.branch.set_stacked_on_url(trunk_tree.branch.base)
192
 
        # with some work on it
193
 
        branch_revid = branch_tree.commit('moar work plz')
194
 
        # you can chain branches on from there
195
 
        out, err = self.run_bzr(['branch', 'branch', '--stacked', 'branch2'])
196
 
        self.assertEqual('', out)
197
 
        self.assertEqual('Created new stacked branch referring to %s.\n' %
198
 
            branch_tree.branch.base, err)
199
 
        self.assertEqual(branch_tree.branch.base,
200
 
            branch.Branch.open('branch2').get_stacked_on_url())
201
 
        branch2_tree = WorkingTree.open('branch2')
202
 
        branch2_revid = branch2_tree.commit('work on second stacked branch')
203
 
        self.assertRevisionInRepository('branch2', branch2_revid)
204
 
        self.assertRevisionsInBranchRepository(
205
 
            [trunk_revid, branch_revid, branch2_revid],
206
 
            'branch2')
207
 
 
208
 
    def test_branch_stacked(self):
209
 
        # We have a mainline
210
 
        trunk_tree = self.make_branch_and_tree('mainline',
211
 
            format='1.9')
212
 
        original_revid = trunk_tree.commit('mainline')
213
 
        self.assertRevisionInRepository('mainline', original_revid)
214
 
        # and a branch from it which is stacked
215
 
        out, err = self.run_bzr(['branch', '--stacked', 'mainline',
216
 
            'newbranch'])
217
 
        self.assertEqual('', out)
218
 
        self.assertEqual('Created new stacked branch referring to %s.\n' %
219
 
            trunk_tree.branch.base, err)
220
 
        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)
224
 
 
225
 
    def test_branch_stacked_from_smart_server(self):
226
 
        # We can branch stacking on a smart server
227
 
        from bzrlib.smart.server import SmartTCPServer_for_testing
228
 
        self.transport_server = SmartTCPServer_for_testing
229
 
        trunk = self.make_branch('mainline', format='1.9')
230
 
        out, err = self.run_bzr(
231
 
            ['branch', '--stacked', self.get_url('mainline'), 'shallow'])
232
 
 
233
 
    def test_branch_stacked_from_non_stacked_format(self):
234
 
        """The origin format doesn't support stacking"""
235
 
        trunk = self.make_branch('trunk', format='pack-0.92')
236
 
        out, err = self.run_bzr(
237
 
            ['branch', '--stacked', 'trunk', 'shallow'])
238
 
        # We should notify the user that we upgraded their format
239
 
        self.assertEqualDiff(
240
 
            'Source format does not support stacking, using format: \'1.6\'\n'
241
 
            '  Packs 5 (adds stacking support, requires bzr 1.6)\n'
242
 
            '\n'
243
 
            'Created new stacked branch referring to %s.\n' % (trunk.base,),
244
 
            err)
245
 
 
246
 
    def test_branch_stacked_from_rich_root_non_stackable(self):
247
 
        trunk = self.make_branch('trunk', format='rich-root-pack')
248
 
        out, err = self.run_bzr(
249
 
            ['branch', '--stacked', 'trunk', 'shallow'])
250
 
        # We should notify the user that we upgraded their format
251
 
        self.assertEqualDiff(
252
 
            'Source format does not support stacking, using format:'
253
 
            ' \'1.6.1-rich-root\'\n'
254
 
            '  Packs 5 rich-root (adds stacking support, requires bzr 1.6.1)\n'
255
 
            '\n'
256
 
            'Created new stacked branch referring to %s.\n' % (trunk.base,),
257
 
            err)
258
 
 
259
 
 
260
 
class TestSmartServerBranching(ExternalBase):
261
 
 
262
 
    def test_branch_from_trivial_branch_to_same_server_branch_acceptance(self):
263
 
        self.setup_smart_server_with_call_log()
264
 
        t = self.make_branch_and_tree('from')
265
 
        for count in range(9):
266
 
            t.commit(message='commit %d' % count)
267
 
        self.reset_smart_call_log()
268
 
        out, err = self.run_bzr(['branch', self.get_url('from'),
269
 
            self.get_url('target')])
270
 
        # This figure represent the amount of work to perform this use case. It
271
 
        # is entirely ok to reduce this number if a test fails due to rpc_count
272
 
        # being too low. If rpc_count increases, more network roundtrips have
273
 
        # become necessary for this use case. Please do not adjust this number
274
 
        # upwards without agreement from bzr's network support maintainers.
275
 
        self.assertLength(39, self.hpss_calls)
276
 
 
277
 
    def test_branch_from_trivial_branch_streaming_acceptance(self):
278
 
        self.setup_smart_server_with_call_log()
279
 
        t = self.make_branch_and_tree('from')
280
 
        for count in range(9):
281
 
            t.commit(message='commit %d' % count)
282
 
        self.reset_smart_call_log()
283
 
        out, err = self.run_bzr(['branch', self.get_url('from'),
284
 
            'local-target'])
285
 
        # This figure represent the amount of work to perform this use case. It
286
 
        # is entirely ok to reduce this number if a test fails due to rpc_count
287
 
        # being too low. If rpc_count increases, more network roundtrips have
288
 
        # become necessary for this use case. Please do not adjust this number
289
 
        # upwards without agreement from bzr's network support maintainers.
290
 
        self.assertLength(10, self.hpss_calls)
291
 
 
292
 
    def test_branch_from_trivial_stacked_branch_streaming_acceptance(self):
293
 
        self.setup_smart_server_with_call_log()
294
 
        t = self.make_branch_and_tree('trunk')
295
 
        for count in range(8):
296
 
            t.commit(message='commit %d' % count)
297
 
        tree2 = t.branch.bzrdir.sprout('feature', stacked=True
298
 
            ).open_workingtree()
299
 
        tree2.commit('feature change')
300
 
        self.reset_smart_call_log()
301
 
        out, err = self.run_bzr(['branch', self.get_url('feature'),
302
 
            'local-target'])
303
 
        # This figure represent the amount of work to perform this use case. It
304
 
        # is entirely ok to reduce this number if a test fails due to rpc_count
305
 
        # being too low. If rpc_count increases, more network roundtrips have
306
 
        # become necessary for this use case. Please do not adjust this number
307
 
        # upwards without agreement from bzr's network support maintainers.
308
 
        self.assertLength(15, self.hpss_calls)
309
 
 
310
 
 
311
 
class TestRemoteBranch(TestCaseWithSFTPServer):
312
 
 
313
 
    def setUp(self):
314
 
        super(TestRemoteBranch, self).setUp()
315
 
        tree = self.make_branch_and_tree('branch')
316
 
        self.build_tree_contents([('branch/file', 'file content\n')])
317
 
        tree.add('file')
318
 
        tree.commit('file created')
319
 
 
320
 
    def test_branch_local_remote(self):
321
 
        self.run_bzr(['branch', 'branch', self.get_url('remote')])
322
 
        t = self.get_transport()
323
 
        # Ensure that no working tree what created remotely
324
 
        self.assertFalse(t.has('remote/file'))
325
 
 
326
 
    def test_branch_remote_remote(self):
327
 
        # Light cheat: we access the branch remotely
328
 
        self.run_bzr(['branch', self.get_url('branch'),
329
 
                      self.get_url('remote')])
330
 
        t = self.get_transport()
331
 
        # Ensure that no working tree what created remotely
332
 
        self.assertFalse(t.has('remote/file'))
333
91