~bzr-pqm/bzr/bzr.dev

4988.10.5 by John Arbash Meinel
Merge bzr.dev 5021 to resolve NEWS
1
# Copyright (C) 2007-2010 Canonical Ltd
2245.2.1 by Robert Collins
Split branch pushing out of branch pulling.
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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2245.2.1 by Robert Collins
Split branch pushing out of branch pulling.
16
17
"""Tests for branch.push behaviour."""
18
3904.3.5 by Andrew Bennetts
Improve the test; now 4/7 passing.
19
from cStringIO import StringIO
2245.2.1 by Robert Collins
Split branch pushing out of branch pulling.
20
import os
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
21
3703.3.7 by Andrew Bennetts
Move empty push effort tests to branch_implementations.
22
from bzrlib import (
23
    branch,
24
    builtins,
25
    bzrdir,
4332.3.35 by Robert Collins
Fix failing tests.
26
    check,
3703.3.7 by Andrew Bennetts
Move empty push effort tests to branch_implementations.
27
    debug,
28
    errors,
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
29
    memorytree,
3904.3.5 by Andrew Bennetts
Improve the test; now 4/7 passing.
30
    push,
4035.2.1 by Andrew Bennetts
Fix unnecessary get_parent_map calls after insert_stream during push.
31
    repository,
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
32
    revision,
3703.3.7 by Andrew Bennetts
Move empty push effort tests to branch_implementations.
33
    tests,
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
34
    transport,
35
    )
36
from bzrlib.smart import (
37
    client,
38
    server,
39
    repository as _mod_smart_repo,
40
    )
5017.3.29 by Vincent Ladeuil
-s bt.per_branch.test_push passing
41
from bzrlib.tests import (
42
    per_branch,
43
    test_server,
44
    )
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
45
46
47
class TestPush(per_branch.TestCaseWithBranch):
2245.2.1 by Robert Collins
Split branch pushing out of branch pulling.
48
49
    def test_push_convergence_simple(self):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
50
        # when revisions are pushed, the left-most accessible parents must
2245.2.1 by Robert Collins
Split branch pushing out of branch pulling.
51
        # become the revision-history.
52
        mine = self.make_branch_and_tree('mine')
53
        mine.commit('1st post', rev_id='P1', allow_pointless=True)
54
        other = mine.bzrdir.sprout('other').open_workingtree()
55
        other.commit('my change', rev_id='M1', allow_pointless=True)
56
        mine.merge_from_branch(other.branch)
57
        mine.commit('merge my change', rev_id='P2')
2297.1.4 by Martin Pool
Push now returns a PushResult rather than just an integer.
58
        result = mine.branch.push(other.branch)
2245.2.1 by Robert Collins
Split branch pushing out of branch pulling.
59
        self.assertEqual(['P1', 'P2'], other.branch.revision_history())
2297.1.4 by Martin Pool
Push now returns a PushResult rather than just an integer.
60
        # result object contains some structured data
61
        self.assertEqual(result.old_revid, 'M1')
62
        self.assertEqual(result.new_revid, 'P2')
63
        # and it can be treated as an integer for compatibility
64
        self.assertEqual(int(result), 0)
2245.2.1 by Robert Collins
Split branch pushing out of branch pulling.
65
66
    def test_push_merged_indirect(self):
67
        # it should be possible to do a push from one branch into another
68
        # when the tip of the target was merged into the source branch
69
        # via a third branch - so its buried in the ancestry and is not
70
        # directly accessible.
71
        mine = self.make_branch_and_tree('mine')
72
        mine.commit('1st post', rev_id='P1', allow_pointless=True)
73
        target = mine.bzrdir.sprout('target').open_workingtree()
74
        target.commit('my change', rev_id='M1', allow_pointless=True)
75
        other = mine.bzrdir.sprout('other').open_workingtree()
76
        other.merge_from_branch(target.branch)
77
        other.commit('merge my change', rev_id='O2')
78
        mine.merge_from_branch(other.branch)
79
        mine.commit('merge other', rev_id='P2')
80
        mine.branch.push(target.branch)
81
        self.assertEqual(['P1', 'P2'], target.branch.revision_history())
82
83
    def test_push_to_checkout_updates_master(self):
84
        """Pushing into a checkout updates the checkout and the master branch"""
85
        master_tree = self.make_branch_and_tree('master')
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
86
        checkout = self.make_branch_and_tree('checkout')
87
        try:
88
            checkout.branch.bind(master_tree.branch)
89
        except errors.UpgradeRequired:
90
            # cant bind this format, the test is irrelevant.
91
            return
92
        rev1 = checkout.commit('master')
2245.2.1 by Robert Collins
Split branch pushing out of branch pulling.
93
94
        other = master_tree.branch.bzrdir.sprout('other').open_workingtree()
95
        rev2 = other.commit('other commit')
96
        # now push, which should update both checkout and master.
97
        other.branch.push(checkout.branch)
98
        self.assertEqual([rev1, rev2], checkout.branch.revision_history())
99
        self.assertEqual([rev1, rev2], master_tree.branch.revision_history())
100
101
    def test_push_raises_specific_error_on_master_connection_error(self):
102
        master_tree = self.make_branch_and_tree('master')
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
103
        checkout = self.make_branch_and_tree('checkout')
104
        try:
105
            checkout.branch.bind(master_tree.branch)
106
        except errors.UpgradeRequired:
107
            # cant bind this format, the test is irrelevant.
108
            return
2245.2.1 by Robert Collins
Split branch pushing out of branch pulling.
109
        other = master_tree.branch.bzrdir.sprout('other').open_workingtree()
110
        # move the branch out of the way on disk to cause a connection
111
        # error.
112
        os.rename('master', 'master_gone')
113
        # try to push, which should raise a BoundBranchConnectionFailure.
114
        self.assertRaises(errors.BoundBranchConnectionFailure,
115
                other.branch.push, checkout.branch)
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
116
2279.1.1 by John Arbash Meinel
Branch.push() only needs a read lock.
117
    def test_push_uses_read_lock(self):
118
        """Push should only need a read lock on the source side."""
119
        source = self.make_branch_and_tree('source')
120
        target = self.make_branch('target')
121
2381.1.3 by Robert Collins
Review feedback.
122
        self.build_tree(['source/a'])
2279.1.1 by John Arbash Meinel
Branch.push() only needs a read lock.
123
        source.add(['a'])
124
        source.commit('a')
125
126
        source.branch.lock_read()
127
        try:
128
            target.lock_write()
129
            try:
130
                source.branch.push(target, stop_revision=source.last_revision())
131
            finally:
132
                target.unlock()
133
        finally:
134
            source.branch.unlock()
135
2279.1.3 by John Arbash Meinel
Switch the test to being a branch_implementation test.
136
    def test_push_within_repository(self):
137
        """Push from one branch to another inside the same repository."""
138
        try:
139
            repo = self.make_repository('repo', shared=True)
140
        except (errors.IncompatibleFormat, errors.UninitializableFormat):
141
            # This Branch format cannot create shared repositories
142
            return
143
        # This is a little bit trickier because make_branch_and_tree will not
144
        # re-use a shared repository.
145
        a_bzrdir = self.make_bzrdir('repo/tree')
146
        try:
147
            a_branch = self.branch_format.initialize(a_bzrdir)
148
        except (errors.UninitializableFormat):
149
            # Cannot create these branches
150
            return
2018.5.97 by Andrew Bennetts
Fix more tests.
151
        try:
152
            tree = a_branch.bzrdir.create_workingtree()
153
        except errors.NotLocalUrl:
5017.3.29 by Vincent Ladeuil
-s bt.per_branch.test_push passing
154
            if self.vfs_transport_factory is test_server.LocalURLServer:
2018.5.130 by Robert Collins
Make all branch_implementations tests pass.
155
                # the branch is colocated on disk, we cannot create a checkout.
156
                # hopefully callers will expect this.
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
157
                local_controldir= bzrdir.BzrDir.open(
158
                    self.get_vfs_only_url('repo/tree'))
2018.5.130 by Robert Collins
Make all branch_implementations tests pass.
159
                tree = local_controldir.create_workingtree()
160
            else:
161
                tree = a_branch.create_checkout('repo/tree', lightweight=True)
2381.1.3 by Robert Collins
Review feedback.
162
        self.build_tree(['repo/tree/a'])
2279.1.3 by John Arbash Meinel
Switch the test to being a branch_implementation test.
163
        tree.add(['a'])
164
        tree.commit('a')
165
166
        to_bzrdir = self.make_bzrdir('repo/branch')
167
        to_branch = self.branch_format.initialize(to_bzrdir)
168
        tree.branch.push(to_branch)
169
170
        self.assertEqual(tree.branch.last_revision(),
171
                         to_branch.last_revision())
172
3449.1.2 by Andrew Bennetts
Add test and NEWS entry.
173
    def test_push_overwrite_of_non_tip_with_stop_revision(self):
174
        """Combining the stop_revision and overwrite options works.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
175
3449.1.2 by Andrew Bennetts
Add test and NEWS entry.
176
        This was <https://bugs.launchpad.net/bzr/+bug/234229>.
177
        """
178
        source = self.make_branch_and_tree('source')
179
        target = self.make_branch('target')
180
181
        source.commit('1st commit')
182
        source.branch.push(target)
183
        source.commit('2nd commit', rev_id='rev-2')
184
        source.commit('3rd commit')
185
186
        source.branch.push(target, stop_revision='rev-2', overwrite=True)
187
        self.assertEqual('rev-2', target.last_revision())
188
3904.3.5 by Andrew Bennetts
Improve the test; now 4/7 passing.
189
    def test_push_with_default_stacking_does_not_create_broken_branch(self):
3904.3.7 by Andrew Bennetts
Comment the new tests.
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
        """
3904.3.6 by Andrew Bennetts
Skip test for two formats, and fix format 5 by avoiding a full history sync with non-format5 branches.
197
        if isinstance(self.branch_format, branch.BzrBranchFormat4):
198
            raise tests.TestNotApplicable('Not a metadir format.')
199
        if isinstance(self.branch_format, branch.BranchReferenceFormat):
3904.3.7 by Andrew Bennetts
Comment the new tests.
200
            # This test could in principle apply to BranchReferenceFormat, but
201
            # make_branch_builder doesn't support it.
3904.3.6 by Andrew Bennetts
Skip test for two formats, and fix format 5 by avoiding a full history sync with non-format5 branches.
202
            raise tests.TestSkipped(
203
                "BranchBuilder can't make reference branches.")
3904.3.7 by Andrew Bennetts
Comment the new tests.
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.
3904.3.5 by Andrew Bennetts
Improve the test; now 4/7 passing.
209
        repo = self.make_repository('repo', shared=True, format='1.6')
210
        builder = self.make_branch_builder('repo/local')
3904.3.4 by Andrew Bennetts
First cut of a branch_implementations test. It fails.
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()
3904.3.6 by Andrew Bennetts
Skip test for two formats, and fix format 5 by avoiding a full history sync with non-format5 branches.
219
        trunk = builder.get_branch()
3904.3.7 by Andrew Bennetts
Comment the new tests.
220
        # Sprout rev-1 to "trunk", so that we can stack on it.
3904.3.6 by Andrew Bennetts
Skip test for two formats, and fix format 5 by avoiding a full history sync with non-format5 branches.
221
        trunk.bzrdir.sprout(self.get_url('trunk'), revision_id='rev-1')
3904.3.7 by Andrew Bennetts
Comment the new tests.
222
        # Set a default stacking policy so that new branches will automatically
223
        # stack on trunk.
3904.3.4 by Andrew Bennetts
First cut of a branch_implementations test. It fails.
224
        self.make_bzrdir('.').get_config().set_default_stack_on('trunk')
3904.3.7 by Andrew Bennetts
Comment the new tests.
225
        # Push rev-2 to a new branch "remote".  It will be stacked on "trunk".
3904.3.5 by Andrew Bennetts
Improve the test; now 4/7 passing.
226
        output = StringIO()
3904.3.6 by Andrew Bennetts
Skip test for two formats, and fix format 5 by avoiding a full history sync with non-format5 branches.
227
        push._show_push_branch(trunk, 'rev-2', self.get_url('remote'), output)
3904.3.7 by Andrew Bennetts
Comment the new tests.
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.
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
230
        remote_branch = branch.Branch.open(self.get_url('remote'))
3904.3.6 by Andrew Bennetts
Skip test for two formats, and fix format 5 by avoiding a full history sync with non-format5 branches.
231
        trunk.push(remote_branch)
4332.3.35 by Robert Collins
Fix failing tests.
232
        check.check_dwim(remote_branch.base, False, True, True)
3904.3.4 by Andrew Bennetts
First cut of a branch_implementations test. It fails.
233
4035.2.1 by Andrew Bennetts
Fix unnecessary get_parent_map calls after insert_stream during push.
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 :)
4035.2.2 by Robert Collins
Minor tweaks to fix failing tests.
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.")
4035.2.1 by Andrew Bennetts
Fix unnecessary get_parent_map calls after insert_stream during push.
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)
4070.2.6 by Robert Collins
Missed one test.
267
        hpss_call_names = [item.call.method for item in self.hpss_calls]
4476.3.82 by Andrew Bennetts
Mention another bug fix in NEWS, and update verb name, comments, and NEWS additions for landing on 1.19 rather than 1.18.
268
        self.assertTrue('Repository.insert_stream_1.19' in hpss_call_names)
4476.3.18 by Andrew Bennetts
Update some tests that were expecting the pre-1.17 insert_stream verb.
269
        insert_stream_idx = hpss_call_names.index(
4476.3.82 by Andrew Bennetts
Mention another bug fix in NEWS, and update verb name, comments, and NEWS additions for landing on 1.19 rather than 1.18.
270
            'Repository.insert_stream_1.19')
4035.2.1 by Andrew Bennetts
Fix unnecessary get_parent_map calls after insert_stream during push.
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(
4476.3.82 by Andrew Bennetts
Mention another bug fix in NEWS, and update verb name, comments, and NEWS additions for landing on 1.19 rather than 1.18.
275
            ['Repository.insert_stream_1.19', 'Repository.insert_stream_1.19',
4476.3.18 by Andrew Bennetts
Update some tests that were expecting the pre-1.17 insert_stream verb.
276
             'get', 'Branch.set_last_revision_info', 'Branch.unlock'],
4035.2.1 by Andrew Bennetts
Fix unnecessary get_parent_map calls after insert_stream during push.
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.
4985.1.5 by Vincent Ladeuil
Deploying the new overrideAttr facility further reduces the complexity
282
        self.overrideAttr(repository.InterRepository,
283
                          '_walk_to_common_revisions_batch_size', 1)
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
284
        self.overrideAttr(_mod_smart_repo.SmartServerRepositoryGetParentMap,
4985.1.5 by Vincent Ladeuil
Deploying the new overrideAttr facility further reduces the complexity
285
                          'no_extra_results', True)
4035.2.1 by Andrew Bennetts
Fix unnecessary get_parent_map calls after insert_stream during push.
286
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
287
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
288
class TestPushHook(per_branch.TestCaseWithBranch):
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
289
290
    def setUp(self):
291
        self.hook_calls = []
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
292
        super(TestPushHook, self).setUp()
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
293
2297.1.4 by Martin Pool
Push now returns a PushResult rather than just an integer.
294
    def capture_post_push_hook(self, result):
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
295
        """Capture post push hook calls to self.hook_calls.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
296
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
297
        The call is logged, as is some state of the two branches.
298
        """
2297.1.6 by Martin Pool
Add docs for Results, give some members cleaner names
299
        if result.local_branch:
300
            local_locked = result.local_branch.is_locked()
301
            local_base = result.local_branch.base
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
302
        else:
303
            local_locked = None
304
            local_base = None
305
        self.hook_calls.append(
2297.1.6 by Martin Pool
Add docs for Results, give some members cleaner names
306
            ('post_push', result.source_branch, local_base,
307
             result.master_branch.base,
2297.1.4 by Martin Pool
Push now returns a PushResult rather than just an integer.
308
             result.old_revno, result.old_revid,
2297.1.6 by Martin Pool
Add docs for Results, give some members cleaner names
309
             result.new_revno, result.new_revid,
310
             result.source_branch.is_locked(), local_locked,
311
             result.master_branch.is_locked()))
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
312
313
    def test_post_push_empty_history(self):
314
        target = self.make_branch('target')
315
        source = self.make_branch('source')
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
316
        branch.Branch.hooks.install_named_hook(
317
            'post_push', self.capture_post_push_hook, None)
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
318
        source.push(target)
319
        # with nothing there we should still get a notification, and
320
        # have both branches locked at the notification time.
321
        self.assertEqual([
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
322
            ('post_push', source, None, target.base, 0, revision.NULL_REVISION,
323
             0, revision.NULL_REVISION, True, None, True)
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
324
            ],
325
            self.hook_calls)
326
327
    def test_post_push_bound_branch(self):
328
        # pushing to a bound branch should pass in the master branch to the
329
        # hook, allowing the correct number of emails to be sent, while still
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
330
        # allowing hooks that want to modify the target to do so to both
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
331
        # instances.
332
        target = self.make_branch('target')
333
        local = self.make_branch('local')
334
        try:
335
            local.bind(target)
336
        except errors.UpgradeRequired:
2477.1.2 by Martin Pool
Rename push/pull back to 'run_hooks' (jameinel)
337
            # We can't bind this format to itself- typically it is the local
338
            # branch that doesn't support binding.  As of May 2007
339
            # remotebranches can't be bound.  Let's instead make a new local
340
            # branch of the default type, which does allow binding.
341
            # See https://bugs.launchpad.net/bzr/+bug/112020
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
342
            local = bzrdir.BzrDir.create_branch_convenience('local2')
2477.1.9 by Martin Pool
Review cleanups from John, mostly docs
343
            local.bind(target)
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
344
        source = self.make_branch('source')
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
345
        branch.Branch.hooks.install_named_hook(
346
            'post_push', self.capture_post_push_hook, None)
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
347
        source.push(local)
348
        # with nothing there we should still get a notification, and
349
        # have both branches locked at the notification time.
350
        self.assertEqual([
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
351
            ('post_push', source, local.base, target.base, 0,
352
             revision.NULL_REVISION, 0, revision.NULL_REVISION,
353
             True, True, True)
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
354
            ],
355
            self.hook_calls)
356
357
    def test_post_push_nonempty_history(self):
358
        target = self.make_branch_and_memory_tree('target')
359
        target.lock_write()
360
        target.add('')
361
        rev1 = target.commit('rev 1')
362
        target.unlock()
363
        sourcedir = target.bzrdir.clone(self.get_url('source'))
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
364
        source = memorytree.MemoryTree.create_on_branch(sourcedir.open_branch())
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
365
        rev2 = source.commit('rev 2')
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
366
        branch.Branch.hooks.install_named_hook(
367
            'post_push', self.capture_post_push_hook, None)
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
368
        source.branch.push(target.branch)
369
        # with nothing there we should still get a notification, and
370
        # have both branches locked at the notification time.
371
        self.assertEqual([
372
            ('post_push', source.branch, None, target.branch.base, 1, rev1,
373
             2, rev2, True, None, True)
374
            ],
375
            self.hook_calls)
3703.3.7 by Andrew Bennetts
Move empty push effort tests to branch_implementations.
376
377
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
378
class EmptyPushSmartEffortTests(per_branch.TestCaseWithBranch):
3703.3.7 by Andrew Bennetts
Move empty push effort tests to branch_implementations.
379
    """Tests that a push of 0 revisions should make a limited number of smart
380
    protocol RPCs.
381
    """
382
383
    def setUp(self):
384
        # Skip some scenarios that don't apply to these tests.
385
        if (self.transport_server is not None and
386
            issubclass(self.transport_server, server.SmartTCPServer)):
387
            raise tests.TestNotApplicable(
388
                'Does not apply when remote backing branch is also '
389
                'a smart branch')
390
        if isinstance(self.branch_format, branch.BzrBranchFormat4):
391
            raise tests.TestNotApplicable(
392
                'Branch format 4 is not usable via HPSS.')
393
        super(EmptyPushSmartEffortTests, self).setUp()
394
        # Create a smart server that publishes whatever the backing VFS server
395
        # does.
5017.3.29 by Vincent Ladeuil
-s bt.per_branch.test_push passing
396
        self.smart_server = test_server.SmartTCPServer_for_testing()
4659.1.2 by Robert Collins
Refactor creation and shutdown of test servers to use a common helper,
397
        self.start_server(self.smart_server, self.get_server())
3703.3.7 by Andrew Bennetts
Move empty push effort tests to branch_implementations.
398
        # Make two empty branches, 'empty' and 'target'.
399
        self.empty_branch = self.make_branch('empty')
400
        self.make_branch('target')
401
        # Log all HPSS calls into self.hpss_calls.
402
        client._SmartClient.hooks.install_named_hook(
403
            'call', self.capture_hpss_call, None)
404
        self.hpss_calls = []
405
406
    def capture_hpss_call(self, params):
407
        self.hpss_calls.append(params.method)
408
409
    def test_empty_branch_api(self):
410
        """The branch_obj.push API should make a limited number of HPSS calls.
411
        """
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
412
        t = transport.get_transport(self.smart_server.get_url()).clone('target')
413
        target = branch.Branch.open_from_transport(t)
3703.3.7 by Andrew Bennetts
Move empty push effort tests to branch_implementations.
414
        self.empty_branch.push(target)
415
        self.assertEqual(
4634.47.8 by Andrew Bennetts
Fix per_branch.test_push effort test to expect new verb.
416
            ['BzrDir.open_2.1',
4734.4.13 by Andrew Bennetts
Fix trivial test failure.
417
             'BzrDir.open_branchV3',
4053.1.4 by Robert Collins
Move the fetch control attributes from Repository to RepositoryFormat.
418
             'BzrDir.find_repositoryV3',
3703.3.7 by Andrew Bennetts
Move empty push effort tests to branch_implementations.
419
             'Branch.get_stacked_on_url',
420
             'Branch.lock_write',
421
             'Branch.last_revision_info',
422
             'Branch.unlock'],
423
            self.hpss_calls)
424
425
    def test_empty_branch_command(self):
426
        """The 'bzr push' command should make a limited number of HPSS calls.
427
        """
428
        cmd = builtins.cmd_push()
429
        cmd.outf = tests.StringIOWrapper()
430
        cmd.run(
4420.1.2 by Vincent Ladeuil
Fix bug #284038 by adding a --strict option to push.
431
            directory=self.get_url('empty'),
4420.1.4 by Vincent Ladeuil
Cleanup.
432
            location=self.smart_server.get_url() + 'target')
3703.3.7 by Andrew Bennetts
Move empty push effort tests to branch_implementations.
433
        # HPSS calls as of 2008/09/22:
434
        # [BzrDir.open, BzrDir.open_branch, BzrDir.find_repositoryV2,
435
        # Branch.get_stacked_on_url, get, get, Branch.lock_write,
436
        # Branch.last_revision_info, Branch.unlock]
437
        self.assertTrue(len(self.hpss_calls) <= 9, self.hpss_calls)
438
439
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
440
class TestLossyPush(per_branch.TestCaseWithBranch):
4347.3.2 by Jelmer Vernooij
Add some basic tests for lossy_push.
441
442
    def setUp(self):
443
        self.hook_calls = []
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
444
        super(TestLossyPush, self).setUp()
4347.3.2 by Jelmer Vernooij
Add some basic tests for lossy_push.
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)