~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: 2006-01-13 09:57:13 UTC
  • mto: This revision was merged to the branch mainline in revision 1611.
  • Revision ID: mbp@sourcefrog.net-20060113095713-1fa5912229a3898e
Review updates of pycurl transport

Split them out into 

  bzrlib.transport.http             common base
  bzrlib.transport.http._urllib     pure python
  bzrlib.transport.http._pycurl     calls pycurl

Update to work with robert's nice transport test multiplexer.

Add PyCurlTransport.has() which does just a HEAD request; should be faster.

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