/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/per_branch/test_push.py

  • Committer: Andrew Bennetts
  • Date: 2010-04-13 04:33:55 UTC
  • mfrom: (5147 +trunk)
  • mto: This revision was merged to the branch mainline in revision 5149.
  • Revision ID: andrew.bennetts@canonical.com-20100413043355-lg3id0uwtju0k3zs
MergeĀ lp:bzr.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2004, 2005, 2007 Canonical Ltd
 
1
# Copyright (C) 2007-2010 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
"""Tests for branch.push behaviour."""
18
18
 
 
19
from cStringIO import StringIO
19
20
import os
20
 
 
 
21
 
21
22
from bzrlib import (
22
23
    branch,
23
24
    builtins,
24
25
    bzrdir,
 
26
    check,
25
27
    debug,
26
28
    errors,
 
29
    memorytree,
 
30
    push,
 
31
    repository,
 
32
    revision,
27
33
    tests,
28
 
    )
29
 
from bzrlib.branch import Branch
30
 
from bzrlib.bzrdir import BzrDir
31
 
from bzrlib.memorytree import MemoryTree
32
 
from bzrlib.revision import NULL_REVISION
33
 
from bzrlib.smart import client, server
34
 
from bzrlib.tests.branch_implementations.test_branch import TestCaseWithBranch
35
 
from bzrlib.transport import get_transport
36
 
from bzrlib.transport.local import LocalURLServer
37
 
 
38
 
 
39
 
class TestPush(TestCaseWithBranch):
 
34
    transport,
 
35
    )
 
36
from bzrlib.smart import (
 
37
    client,
 
38
    server,
 
39
    repository as _mod_smart_repo,
 
40
    )
 
41
from bzrlib.tests import (
 
42
    per_branch,
 
43
    test_server,
 
44
    )
 
45
 
 
46
 
 
47
class TestPush(per_branch.TestCaseWithBranch):
40
48
 
41
49
    def test_push_convergence_simple(self):
42
 
        # when revisions are pushed, the left-most accessible parents must 
 
50
        # when revisions are pushed, the left-most accessible parents must
43
51
        # become the revision-history.
44
52
        mine = self.make_branch_and_tree('mine')
45
53
        mine.commit('1st post', rev_id='P1', allow_pointless=True)
143
151
        try:
144
152
            tree = a_branch.bzrdir.create_workingtree()
145
153
        except errors.NotLocalUrl:
146
 
            if self.vfs_transport_factory is LocalURLServer:
 
154
            if self.vfs_transport_factory is test_server.LocalURLServer:
147
155
                # the branch is colocated on disk, we cannot create a checkout.
148
156
                # hopefully callers will expect this.
149
 
                local_controldir= bzrdir.BzrDir.open(self.get_vfs_only_url('repo/tree'))
 
157
                local_controldir= bzrdir.BzrDir.open(
 
158
                    self.get_vfs_only_url('repo/tree'))
150
159
                tree = local_controldir.create_workingtree()
151
160
            else:
152
161
                tree = a_branch.create_checkout('repo/tree', lightweight=True)
163
172
 
164
173
    def test_push_overwrite_of_non_tip_with_stop_revision(self):
165
174
        """Combining the stop_revision and overwrite options works.
166
 
        
 
175
 
167
176
        This was <https://bugs.launchpad.net/bzr/+bug/234229>.
168
177
        """
169
178
        source = self.make_branch_and_tree('source')
177
186
        source.branch.push(target, stop_revision='rev-2', overwrite=True)
178
187
        self.assertEqual('rev-2', target.last_revision())
179
188
 
180
 
 
181
 
class TestPushHook(TestCaseWithBranch):
 
189
    def test_push_with_default_stacking_does_not_create_broken_branch(self):
 
190
        """Pushing a new standalone branch works even when there's a default
 
191
        stacking policy at the destination.
 
192
 
 
193
        The new branch will preserve the repo format (even if it isn't the
 
194
        default for the branch), and will be stacked when the repo format
 
195
        allows (which means that the branch format isn't necessarly preserved).
 
196
        """
 
197
        if isinstance(self.branch_format, branch.BzrBranchFormat4):
 
198
            raise tests.TestNotApplicable('Not a metadir format.')
 
199
        if isinstance(self.branch_format, branch.BranchReferenceFormat):
 
200
            # This test could in principle apply to BranchReferenceFormat, but
 
201
            # make_branch_builder doesn't support it.
 
202
            raise tests.TestSkipped(
 
203
                "BranchBuilder can't make reference branches.")
 
204
        # Make a branch called "local" in a stackable repository
 
205
        # The branch has 3 revisions:
 
206
        #   - rev-1, adds a file
 
207
        #   - rev-2, no changes
 
208
        #   - rev-3, modifies the file.
 
209
        repo = self.make_repository('repo', shared=True, format='1.6')
 
210
        builder = self.make_branch_builder('repo/local')
 
211
        builder.start_series()
 
212
        builder.build_snapshot('rev-1', None, [
 
213
            ('add', ('', 'root-id', 'directory', '')),
 
214
            ('add', ('filename', 'f-id', 'file', 'content\n'))])
 
215
        builder.build_snapshot('rev-2', ['rev-1'], [])
 
216
        builder.build_snapshot('rev-3', ['rev-2'],
 
217
            [('modify', ('f-id', 'new-content\n'))])
 
218
        builder.finish_series()
 
219
        trunk = builder.get_branch()
 
220
        # Sprout rev-1 to "trunk", so that we can stack on it.
 
221
        trunk.bzrdir.sprout(self.get_url('trunk'), revision_id='rev-1')
 
222
        # Set a default stacking policy so that new branches will automatically
 
223
        # stack on trunk.
 
224
        self.make_bzrdir('.').get_config().set_default_stack_on('trunk')
 
225
        # Push rev-2 to a new branch "remote".  It will be stacked on "trunk".
 
226
        output = StringIO()
 
227
        push._show_push_branch(trunk, 'rev-2', self.get_url('remote'), output)
 
228
        # Push rev-3 onto "remote".  If "remote" not stacked and is missing the
 
229
        # fulltext record for f-id @ rev-1, then this will fail.
 
230
        remote_branch = branch.Branch.open(self.get_url('remote'))
 
231
        trunk.push(remote_branch)
 
232
        check.check_dwim(remote_branch.base, False, True, True)
 
233
 
 
234
    def test_no_get_parent_map_after_insert_stream(self):
 
235
        # Effort test for bug 331823
 
236
        self.setup_smart_server_with_call_log()
 
237
        # Make a local branch with four revisions.  Four revisions because:
 
238
        # one to push, one there for _walk_to_common_revisions to find, one we
 
239
        # don't want to access, one for luck :)
 
240
        if isinstance(self.branch_format, branch.BranchReferenceFormat):
 
241
            # This test could in principle apply to BranchReferenceFormat, but
 
242
            # make_branch_builder doesn't support it.
 
243
            raise tests.TestSkipped(
 
244
                "BranchBuilder can't make reference branches.")
 
245
        try:
 
246
            builder = self.make_branch_builder('local')
 
247
        except (errors.TransportNotPossible, errors.UninitializableFormat):
 
248
            raise tests.TestNotApplicable('format not directly constructable')
 
249
        builder.start_series()
 
250
        builder.build_snapshot('first', None, [
 
251
            ('add', ('', 'root-id', 'directory', ''))])
 
252
        builder.build_snapshot('second', ['first'], [])
 
253
        builder.build_snapshot('third', ['second'], [])
 
254
        builder.build_snapshot('fourth', ['third'], [])
 
255
        builder.finish_series()
 
256
        local = builder.get_branch()
 
257
        local = branch.Branch.open(self.get_vfs_only_url('local'))
 
258
        # Initial push of three revisions
 
259
        remote_bzrdir = local.bzrdir.sprout(
 
260
            self.get_url('remote'), revision_id='third')
 
261
        remote = remote_bzrdir.open_branch()
 
262
        # Push fourth revision
 
263
        self.reset_smart_call_log()
 
264
        self.disableOptimisticGetParentMap()
 
265
        self.assertFalse(local.is_locked())
 
266
        local.push(remote)
 
267
        hpss_call_names = [item.call.method for item in self.hpss_calls]
 
268
        self.assertTrue('Repository.insert_stream_1.19' in hpss_call_names)
 
269
        insert_stream_idx = hpss_call_names.index(
 
270
            'Repository.insert_stream_1.19')
 
271
        calls_after_insert_stream = hpss_call_names[insert_stream_idx:]
 
272
        # After inserting the stream the client has no reason to query the
 
273
        # remote graph any further.
 
274
        self.assertEqual(
 
275
            ['Repository.insert_stream_1.19', 'Repository.insert_stream_1.19',
 
276
             'get', 'Branch.set_last_revision_info', 'Branch.unlock'],
 
277
            calls_after_insert_stream)
 
278
 
 
279
    def disableOptimisticGetParentMap(self):
 
280
        # Tweak some class variables to stop remote get_parent_map calls asking
 
281
        # for or receiving more data than the caller asked for.
 
282
        self.overrideAttr(repository.InterRepository,
 
283
                          '_walk_to_common_revisions_batch_size', 1)
 
284
        self.overrideAttr(_mod_smart_repo.SmartServerRepositoryGetParentMap,
 
285
                          'no_extra_results', True)
 
286
 
 
287
 
 
288
class TestPushHook(per_branch.TestCaseWithBranch):
182
289
 
183
290
    def setUp(self):
184
291
        self.hook_calls = []
185
 
        TestCaseWithBranch.setUp(self)
 
292
        super(TestPushHook, self).setUp()
186
293
 
187
294
    def capture_post_push_hook(self, result):
188
295
        """Capture post push hook calls to self.hook_calls.
189
 
        
 
296
 
190
297
        The call is logged, as is some state of the two branches.
191
298
        """
192
299
        if result.local_branch:
206
313
    def test_post_push_empty_history(self):
207
314
        target = self.make_branch('target')
208
315
        source = self.make_branch('source')
209
 
        Branch.hooks.install_named_hook('post_push',
210
 
                                        self.capture_post_push_hook, None)
 
316
        branch.Branch.hooks.install_named_hook(
 
317
            'post_push', self.capture_post_push_hook, None)
211
318
        source.push(target)
212
319
        # with nothing there we should still get a notification, and
213
320
        # have both branches locked at the notification time.
214
321
        self.assertEqual([
215
 
            ('post_push', source, None, target.base, 0, NULL_REVISION,
216
 
             0, NULL_REVISION, True, None, True)
 
322
            ('post_push', source, None, target.base, 0, revision.NULL_REVISION,
 
323
             0, revision.NULL_REVISION, True, None, True)
217
324
            ],
218
325
            self.hook_calls)
219
326
 
220
327
    def test_post_push_bound_branch(self):
221
328
        # pushing to a bound branch should pass in the master branch to the
222
329
        # hook, allowing the correct number of emails to be sent, while still
223
 
        # allowing hooks that want to modify the target to do so to both 
 
330
        # allowing hooks that want to modify the target to do so to both
224
331
        # instances.
225
332
        target = self.make_branch('target')
226
333
        local = self.make_branch('local')
232
339
            # remotebranches can't be bound.  Let's instead make a new local
233
340
            # branch of the default type, which does allow binding.
234
341
            # See https://bugs.launchpad.net/bzr/+bug/112020
235
 
            local = BzrDir.create_branch_convenience('local2')
 
342
            local = bzrdir.BzrDir.create_branch_convenience('local2')
236
343
            local.bind(target)
237
344
        source = self.make_branch('source')
238
 
        Branch.hooks.install_named_hook('post_push',
239
 
                                        self.capture_post_push_hook, None)
 
345
        branch.Branch.hooks.install_named_hook(
 
346
            'post_push', self.capture_post_push_hook, None)
240
347
        source.push(local)
241
348
        # with nothing there we should still get a notification, and
242
349
        # have both branches locked at the notification time.
243
350
        self.assertEqual([
244
 
            ('post_push', source, local.base, target.base, 0, NULL_REVISION,
245
 
             0, NULL_REVISION, True, True, True)
 
351
            ('post_push', source, local.base, target.base, 0,
 
352
             revision.NULL_REVISION, 0, revision.NULL_REVISION,
 
353
             True, True, True)
246
354
            ],
247
355
            self.hook_calls)
248
356
 
253
361
        rev1 = target.commit('rev 1')
254
362
        target.unlock()
255
363
        sourcedir = target.bzrdir.clone(self.get_url('source'))
256
 
        source = MemoryTree.create_on_branch(sourcedir.open_branch())
 
364
        source = memorytree.MemoryTree.create_on_branch(sourcedir.open_branch())
257
365
        rev2 = source.commit('rev 2')
258
 
        Branch.hooks.install_named_hook('post_push',
259
 
                                        self.capture_post_push_hook, None)
 
366
        branch.Branch.hooks.install_named_hook(
 
367
            'post_push', self.capture_post_push_hook, None)
260
368
        source.branch.push(target.branch)
261
369
        # with nothing there we should still get a notification, and
262
370
        # have both branches locked at the notification time.
267
375
            self.hook_calls)
268
376
 
269
377
 
270
 
class EmptyPushSmartEffortTests(TestCaseWithBranch):
 
378
class EmptyPushSmartEffortTests(per_branch.TestCaseWithBranch):
271
379
    """Tests that a push of 0 revisions should make a limited number of smart
272
380
    protocol RPCs.
273
381
    """
285
393
        super(EmptyPushSmartEffortTests, self).setUp()
286
394
        # Create a smart server that publishes whatever the backing VFS server
287
395
        # does.
288
 
        self.smart_server = server.SmartTCPServer_for_testing()
289
 
        self.smart_server.setUp(self.get_server())
290
 
        self.addCleanup(self.smart_server.tearDown)
 
396
        self.smart_server = test_server.SmartTCPServer_for_testing()
 
397
        self.start_server(self.smart_server, self.get_server())
291
398
        # Make two empty branches, 'empty' and 'target'.
292
399
        self.empty_branch = self.make_branch('empty')
293
400
        self.make_branch('target')
302
409
    def test_empty_branch_api(self):
303
410
        """The branch_obj.push API should make a limited number of HPSS calls.
304
411
        """
305
 
        transport = get_transport(self.smart_server.get_url()).clone('target')
306
 
        target = Branch.open_from_transport(transport)
 
412
        t = transport.get_transport(self.smart_server.get_url()).clone('target')
 
413
        target = branch.Branch.open_from_transport(t)
307
414
        self.empty_branch.push(target)
308
415
        self.assertEqual(
309
 
            ['BzrDir.open',
310
 
             'BzrDir.open_branch',
311
 
             'BzrDir.find_repositoryV2',
 
416
            ['BzrDir.open_2.1',
 
417
             'BzrDir.open_branchV3',
 
418
             'BzrDir.find_repositoryV3',
312
419
             'Branch.get_stacked_on_url',
313
420
             'Branch.lock_write',
314
421
             'Branch.last_revision_info',
321
428
        cmd = builtins.cmd_push()
322
429
        cmd.outf = tests.StringIOWrapper()
323
430
        cmd.run(
324
 
            directory=self.get_url() + 'empty',
 
431
            directory=self.get_url('empty'),
325
432
            location=self.smart_server.get_url() + 'target')
326
433
        # HPSS calls as of 2008/09/22:
327
434
        # [BzrDir.open, BzrDir.open_branch, BzrDir.find_repositoryV2,
330
437
        self.assertTrue(len(self.hpss_calls) <= 9, self.hpss_calls)
331
438
 
332
439
 
 
440
class TestLossyPush(per_branch.TestCaseWithBranch):
 
441
 
 
442
    def setUp(self):
 
443
        self.hook_calls = []
 
444
        super(TestLossyPush, self).setUp()
 
445
 
 
446
    def test_lossy_push_raises_same_vcs(self):
 
447
        target = self.make_branch('target')
 
448
        source = self.make_branch('source')
 
449
        self.assertRaises(errors.LossyPushToSameVCS, source.lossy_push, target)