~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: 2009-04-09 20:23:07 UTC
  • mfrom: (4265.1.4 bbc-merge)
  • Revision ID: pqm@pqm.ubuntu.com-20090409202307-n0depb16qepoe21o
(jam) Change _fetch_uses_deltas = False for CHK repos until we can
        write a better fix.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2008, 2009 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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
 
22
from bzrlib import (branch, bzrdir, errors, repository)
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
25
28
from bzrlib.workingtree import WorkingTree
26
29
 
27
30
 
28
31
class TestBranch(ExternalBase):
29
32
 
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')
 
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')
38
41
 
39
42
    def test_branch(self):
40
43
        """Branch from one branch to another."""
41
 
        os.mkdir('a')
42
 
        os.chdir('a')
43
 
        self.example_branch()
44
 
        os.chdir('..')
45
 
        self.runbzr('branch a b')
 
44
        self.example_branch('a')
 
45
        self.run_bzr('branch a b')
46
46
        b = branch.Branch.open('b')
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('..')
 
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)
52
51
 
53
52
    def test_branch_only_copies_history(self):
54
53
        # Knit branches should only push the history for the current revision.
81
80
 
82
81
        # Now that we have a repository with shared files, make sure
83
82
        # that things aren't copied out by a 'branch'
84
 
        self.run_bzr('branch', 'repo/b', 'branch-b')
 
83
        self.run_bzr('branch repo/b branch-b')
85
84
        pushed_tree = WorkingTree.open('branch-b')
86
85
        pushed_repo = pushed_tree.branch.repository
87
86
        self.assertFalse(pushed_repo.has_revision('a-1'))
88
87
        self.assertFalse(pushed_repo.has_revision('a-2'))
89
88
        self.assertTrue(pushed_repo.has_revision('b-1'))
90
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
 
 
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(53, 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'))
91
333