~bzr-pqm/bzr/bzr.dev

5609.26.1 by John Arbash Meinel
Fix bug #465517, 'bzr push' to a target with a repo but no branch
1
# Copyright (C) 2007-2011 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,
6472.2.2 by Jelmer Vernooij
Use controldir rather than bzrdir in a couple more places.
25
    controldir,
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
    errors,
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
28
    memorytree,
3904.3.5 by Andrew Bennetts
Improve the test; now 4/7 passing.
29
    push,
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
30
    revision,
5348.1.2 by Martin Pool
Deprecate casting PushResult and PullResult to int to get the relative revno change
31
    symbol_versioning,
3703.3.7 by Andrew Bennetts
Move empty push effort tests to branch_implementations.
32
    tests,
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
33
    transport,
34
    )
35
from bzrlib.smart import (
36
    client,
37
    )
5017.3.29 by Vincent Ladeuil
-s bt.per_branch.test_push passing
38
from bzrlib.tests import (
39
    per_branch,
40
    test_server,
41
    )
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
42
43
44
class TestPush(per_branch.TestCaseWithBranch):
2245.2.1 by Robert Collins
Split branch pushing out of branch pulling.
45
46
    def test_push_convergence_simple(self):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
47
        # when revisions are pushed, the left-most accessible parents must
2245.2.1 by Robert Collins
Split branch pushing out of branch pulling.
48
        # become the revision-history.
49
        mine = self.make_branch_and_tree('mine')
50
        mine.commit('1st post', rev_id='P1', allow_pointless=True)
51
        other = mine.bzrdir.sprout('other').open_workingtree()
52
        other.commit('my change', rev_id='M1', allow_pointless=True)
53
        mine.merge_from_branch(other.branch)
54
        mine.commit('merge my change', rev_id='P2')
2297.1.4 by Martin Pool
Push now returns a PushResult rather than just an integer.
55
        result = mine.branch.push(other.branch)
6165.4.4 by Jelmer Vernooij
Avoid .revision_history().
56
        self.assertEqual('P2', other.branch.last_revision())
2297.1.4 by Martin Pool
Push now returns a PushResult rather than just an integer.
57
        # result object contains some structured data
58
        self.assertEqual(result.old_revid, 'M1')
59
        self.assertEqual(result.new_revid, 'P2')
60
        # and it can be treated as an integer for compatibility
5348.1.2 by Martin Pool
Deprecate casting PushResult and PullResult to int to get the relative revno change
61
        self.assertEqual(self.applyDeprecated(
62
            symbol_versioning.deprecated_in((2, 3, 0)),
63
            result.__int__),
64
            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)
6165.4.4 by Jelmer Vernooij
Avoid .revision_history().
81
        self.assertEqual('P2', target.branch.last_revision())
2245.2.1 by Robert Collins
Split branch pushing out of branch pulling.
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)
6165.4.4 by Jelmer Vernooij
Avoid .revision_history().
98
        self.assertEqual(rev2, checkout.branch.last_revision())
99
        self.assertEqual(rev2, master_tree.branch.last_revision())
2245.2.1 by Robert Collins
Split branch pushing out of branch pulling.
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
5609.25.1 by Andrew Bennetts
Add failing test for bug #733350.
117
    def test_push_new_tag_to_bound_branch(self):
118
        master = self.make_branch('master')
119
        bound = self.make_branch('bound')
120
        try:
121
            bound.bind(master)
122
        except errors.UpgradeRequired:
123
            raise tests.TestNotApplicable(
124
                'Format does not support bound branches')
125
        other = bound.bzrdir.sprout('other').open_branch()
126
        try:
127
            other.tags.set_tag('new-tag', 'some-rev')
128
        except errors.TagsNotSupported:
129
            raise tests.TestNotApplicable('Format does not support tags')
130
        other.push(bound)
5609.25.2 by Andrew Bennetts
Hackish fix: pass some extra state to our _basic_push implementation via a private instance variable, rather than changing the API of _basic_push (which bzr-svn and possibly other plugins implement).
131
        self.assertEqual({'new-tag': 'some-rev'}, bound.tags.get_tag_dict())
132
        self.assertEqual({'new-tag': 'some-rev'}, master.tags.get_tag_dict())
5609.25.1 by Andrew Bennetts
Add failing test for bug #733350.
133
2279.1.1 by John Arbash Meinel
Branch.push() only needs a read lock.
134
    def test_push_uses_read_lock(self):
135
        """Push should only need a read lock on the source side."""
136
        source = self.make_branch_and_tree('source')
137
        target = self.make_branch('target')
138
2381.1.3 by Robert Collins
Review feedback.
139
        self.build_tree(['source/a'])
2279.1.1 by John Arbash Meinel
Branch.push() only needs a read lock.
140
        source.add(['a'])
141
        source.commit('a')
142
143
        source.branch.lock_read()
144
        try:
145
            target.lock_write()
146
            try:
147
                source.branch.push(target, stop_revision=source.last_revision())
148
            finally:
149
                target.unlock()
150
        finally:
151
            source.branch.unlock()
152
2279.1.3 by John Arbash Meinel
Switch the test to being a branch_implementation test.
153
    def test_push_within_repository(self):
154
        """Push from one branch to another inside the same repository."""
155
        try:
156
            repo = self.make_repository('repo', shared=True)
157
        except (errors.IncompatibleFormat, errors.UninitializableFormat):
158
            # This Branch format cannot create shared repositories
159
            return
6145.2.1 by Jelmer Vernooij
Add RepositoryFormat.supports_nesting_repositories.
160
        if not repo._format.supports_nesting_repositories:
161
            return
2279.1.3 by John Arbash Meinel
Switch the test to being a branch_implementation test.
162
        # This is a little bit trickier because make_branch_and_tree will not
163
        # re-use a shared repository.
164
        a_bzrdir = self.make_bzrdir('repo/tree')
165
        try:
166
            a_branch = self.branch_format.initialize(a_bzrdir)
167
        except (errors.UninitializableFormat):
168
            # Cannot create these branches
169
            return
2018.5.97 by Andrew Bennetts
Fix more tests.
170
        try:
171
            tree = a_branch.bzrdir.create_workingtree()
172
        except errors.NotLocalUrl:
5017.3.29 by Vincent Ladeuil
-s bt.per_branch.test_push passing
173
            if self.vfs_transport_factory is test_server.LocalURLServer:
2018.5.130 by Robert Collins
Make all branch_implementations tests pass.
174
                # the branch is colocated on disk, we cannot create a checkout.
175
                # hopefully callers will expect this.
6472.2.2 by Jelmer Vernooij
Use controldir rather than bzrdir in a couple more places.
176
                local_controldir = controldir.ControlDir.open(
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
177
                    self.get_vfs_only_url('repo/tree'))
2018.5.130 by Robert Collins
Make all branch_implementations tests pass.
178
                tree = local_controldir.create_workingtree()
179
            else:
180
                tree = a_branch.create_checkout('repo/tree', lightweight=True)
2381.1.3 by Robert Collins
Review feedback.
181
        self.build_tree(['repo/tree/a'])
2279.1.3 by John Arbash Meinel
Switch the test to being a branch_implementation test.
182
        tree.add(['a'])
183
        tree.commit('a')
184
185
        to_bzrdir = self.make_bzrdir('repo/branch')
186
        to_branch = self.branch_format.initialize(to_bzrdir)
187
        tree.branch.push(to_branch)
188
189
        self.assertEqual(tree.branch.last_revision(),
190
                         to_branch.last_revision())
191
5611.2.1 by Jelmer Vernooij
Fix 'bzr push --overwrite -rOLD_MAINLINE_REV'.
192
    def test_push_overwrite_with_older_mainline_rev(self):
193
        """Pushing an older mainline revision with overwrite.
194
195
        This was <https://bugs.launchpad.net/bzr/+bug/386576>.
196
        """
197
        source = self.make_branch_and_tree('source')
198
        target = self.make_branch('target')
199
200
        source.commit('1st commit')
201
        source.commit('2nd commit', rev_id='rev-2')
202
        source.commit('3rd commit')
203
        source.branch.push(target)
204
        source.branch.push(target, stop_revision='rev-2', overwrite=True)
205
        self.assertEqual('rev-2', target.last_revision())
206
3449.1.2 by Andrew Bennetts
Add test and NEWS entry.
207
    def test_push_overwrite_of_non_tip_with_stop_revision(self):
208
        """Combining the stop_revision and overwrite options works.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
209
3449.1.2 by Andrew Bennetts
Add test and NEWS entry.
210
        This was <https://bugs.launchpad.net/bzr/+bug/234229>.
211
        """
212
        source = self.make_branch_and_tree('source')
213
        target = self.make_branch('target')
214
215
        source.commit('1st commit')
216
        source.branch.push(target)
217
        source.commit('2nd commit', rev_id='rev-2')
218
        source.commit('3rd commit')
219
220
        source.branch.push(target, stop_revision='rev-2', overwrite=True)
221
        self.assertEqual('rev-2', target.last_revision())
222
5609.26.1 by John Arbash Meinel
Fix bug #465517, 'bzr push' to a target with a repo but no branch
223
    def test_push_repository_no_branch_doesnt_fetch_all_revs(self):
224
        # See https://bugs.launchpad.net/bzr/+bug/465517
225
        t = self.get_transport('target')
226
        t.ensure_base()
227
        bzrdir = self.bzrdir_format.initialize_on_transport(t)
228
        try:
229
            bzrdir.open_branch()
230
        except errors.NotBranchError:
231
            pass
232
        else:
233
            raise tests.TestNotApplicable('older formats can\'t have a repo'
234
                                          ' without a branch')
235
        try:
236
            source = self.make_branch_builder('source',
237
                                              format=self.bzrdir_format)
238
        except errors.UninitializableFormat:
239
            raise tests.TestNotApplicable('cannot initialize this format')
240
        source.start_series()
241
        source.build_snapshot('A', None, [
242
            ('add', ('', 'root-id', 'directory', None))])
243
        source.build_snapshot('B', ['A'], [])
244
        source.build_snapshot('C', ['A'], [])
245
        source.finish_series()
246
        b = source.get_branch()
247
        # Note: We can't read lock the source branch. Some formats take a write
248
        # lock to 'set_push_location', which breaks
249
        self.addCleanup(b.lock_write().unlock)
250
        repo = bzrdir.create_repository()
251
        # This means 'push the source branch into this dir'
252
        bzrdir.push_branch(b)
253
        self.addCleanup(repo.lock_read().unlock)
254
        # We should have pushed 'C', but not 'B', since it isn't in the
255
        # ancestry
6113.1.3 by Jelmer Vernooij
Use all_revision_ids() when testing present revisions.
256
        self.assertEqual(['A', 'C'], sorted(repo.all_revision_ids()))
5609.26.1 by John Arbash Meinel
Fix bug #465517, 'bzr push' to a target with a repo but no branch
257
3904.3.5 by Andrew Bennetts
Improve the test; now 4/7 passing.
258
    def test_push_with_default_stacking_does_not_create_broken_branch(self):
3904.3.7 by Andrew Bennetts
Comment the new tests.
259
        """Pushing a new standalone branch works even when there's a default
260
        stacking policy at the destination.
261
262
        The new branch will preserve the repo format (even if it isn't the
263
        default for the branch), and will be stacked when the repo format
264
        allows (which means that the branch format isn't necessarly preserved).
265
        """
5673.1.3 by Jelmer Vernooij
Change flexible_components to fixed_components.
266
        if self.bzrdir_format.fixed_components:
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.
267
            raise tests.TestNotApplicable('Not a metadir format.')
268
        if isinstance(self.branch_format, branch.BranchReferenceFormat):
3904.3.7 by Andrew Bennetts
Comment the new tests.
269
            # This test could in principle apply to BranchReferenceFormat, but
270
            # 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.
271
            raise tests.TestSkipped(
272
                "BranchBuilder can't make reference branches.")
3904.3.7 by Andrew Bennetts
Comment the new tests.
273
        # Make a branch called "local" in a stackable repository
274
        # The branch has 3 revisions:
275
        #   - rev-1, adds a file
276
        #   - rev-2, no changes
277
        #   - rev-3, modifies the file.
3904.3.5 by Andrew Bennetts
Improve the test; now 4/7 passing.
278
        repo = self.make_repository('repo', shared=True, format='1.6')
279
        builder = self.make_branch_builder('repo/local')
3904.3.4 by Andrew Bennetts
First cut of a branch_implementations test. It fails.
280
        builder.start_series()
281
        builder.build_snapshot('rev-1', None, [
282
            ('add', ('', 'root-id', 'directory', '')),
283
            ('add', ('filename', 'f-id', 'file', 'content\n'))])
284
        builder.build_snapshot('rev-2', ['rev-1'], [])
285
        builder.build_snapshot('rev-3', ['rev-2'],
286
            [('modify', ('f-id', 'new-content\n'))])
287
        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.
288
        trunk = builder.get_branch()
3904.3.7 by Andrew Bennetts
Comment the new tests.
289
        # 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.
290
        trunk.bzrdir.sprout(self.get_url('trunk'), revision_id='rev-1')
3904.3.7 by Andrew Bennetts
Comment the new tests.
291
        # Set a default stacking policy so that new branches will automatically
292
        # stack on trunk.
3904.3.4 by Andrew Bennetts
First cut of a branch_implementations test. It fails.
293
        self.make_bzrdir('.').get_config().set_default_stack_on('trunk')
3904.3.7 by Andrew Bennetts
Comment the new tests.
294
        # 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.
295
        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.
296
        push._show_push_branch(trunk, 'rev-2', self.get_url('remote'), output)
3904.3.7 by Andrew Bennetts
Comment the new tests.
297
        # Push rev-3 onto "remote".  If "remote" not stacked and is missing the
298
        # 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.
299
        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.
300
        trunk.push(remote_branch)
4332.3.35 by Robert Collins
Fix failing tests.
301
        check.check_dwim(remote_branch.base, False, True, True)
3904.3.4 by Andrew Bennetts
First cut of a branch_implementations test. It fails.
302
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
303
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
304
class TestPushHook(per_branch.TestCaseWithBranch):
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
305
306
    def setUp(self):
307
        self.hook_calls = []
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
308
        super(TestPushHook, self).setUp()
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
309
2297.1.4 by Martin Pool
Push now returns a PushResult rather than just an integer.
310
    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
311
        """Capture post push hook calls to self.hook_calls.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
312
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
313
        The call is logged, as is some state of the two branches.
314
        """
2297.1.6 by Martin Pool
Add docs for Results, give some members cleaner names
315
        if result.local_branch:
316
            local_locked = result.local_branch.is_locked()
317
            local_base = result.local_branch.base
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
318
        else:
319
            local_locked = None
320
            local_base = None
321
        self.hook_calls.append(
2297.1.6 by Martin Pool
Add docs for Results, give some members cleaner names
322
            ('post_push', result.source_branch, local_base,
323
             result.master_branch.base,
2297.1.4 by Martin Pool
Push now returns a PushResult rather than just an integer.
324
             result.old_revno, result.old_revid,
2297.1.6 by Martin Pool
Add docs for Results, give some members cleaner names
325
             result.new_revno, result.new_revid,
326
             result.source_branch.is_locked(), local_locked,
327
             result.master_branch.is_locked()))
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
328
329
    def test_post_push_empty_history(self):
330
        target = self.make_branch('target')
331
        source = self.make_branch('source')
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
332
        branch.Branch.hooks.install_named_hook(
333
            '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
334
        source.push(target)
335
        # with nothing there we should still get a notification, and
336
        # have both branches locked at the notification time.
337
        self.assertEqual([
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
338
            ('post_push', source, None, target.base, 0, revision.NULL_REVISION,
339
             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
340
            ],
341
            self.hook_calls)
342
343
    def test_post_push_bound_branch(self):
344
        # pushing to a bound branch should pass in the master branch to the
345
        # 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
346
        # 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
347
        # instances.
348
        target = self.make_branch('target')
349
        local = self.make_branch('local')
350
        try:
351
            local.bind(target)
352
        except errors.UpgradeRequired:
2477.1.2 by Martin Pool
Rename push/pull back to 'run_hooks' (jameinel)
353
            # We can't bind this format to itself- typically it is the local
354
            # branch that doesn't support binding.  As of May 2007
355
            # remotebranches can't be bound.  Let's instead make a new local
356
            # branch of the default type, which does allow binding.
357
            # See https://bugs.launchpad.net/bzr/+bug/112020
6472.2.2 by Jelmer Vernooij
Use controldir rather than bzrdir in a couple more places.
358
            local = controldir.ControlDir.create_branch_convenience('local2')
2477.1.9 by Martin Pool
Review cleanups from John, mostly docs
359
            local.bind(target)
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
360
        source = self.make_branch('source')
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
361
        branch.Branch.hooks.install_named_hook(
362
            '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
363
        source.push(local)
364
        # with nothing there we should still get a notification, and
365
        # have both branches locked at the notification time.
366
        self.assertEqual([
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
367
            ('post_push', source, local.base, target.base, 0,
368
             revision.NULL_REVISION, 0, revision.NULL_REVISION,
369
             True, True, True)
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
370
            ],
371
            self.hook_calls)
372
373
    def test_post_push_nonempty_history(self):
374
        target = self.make_branch_and_memory_tree('target')
375
        target.lock_write()
376
        target.add('')
377
        rev1 = target.commit('rev 1')
378
        target.unlock()
379
        sourcedir = target.bzrdir.clone(self.get_url('source'))
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
380
        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
381
        rev2 = source.commit('rev 2')
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
382
        branch.Branch.hooks.install_named_hook(
383
            '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
384
        source.branch.push(target.branch)
385
        # with nothing there we should still get a notification, and
386
        # have both branches locked at the notification time.
387
        self.assertEqual([
388
            ('post_push', source.branch, None, target.branch.base, 1, rev1,
389
             2, rev2, True, None, True)
390
            ],
391
            self.hook_calls)
3703.3.7 by Andrew Bennetts
Move empty push effort tests to branch_implementations.
392
393
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
394
class EmptyPushSmartEffortTests(per_branch.TestCaseWithBranch):
3703.3.7 by Andrew Bennetts
Move empty push effort tests to branch_implementations.
395
    """Tests that a push of 0 revisions should make a limited number of smart
396
    protocol RPCs.
397
    """
398
399
    def setUp(self):
400
        # Skip some scenarios that don't apply to these tests.
5247.3.38 by Vincent Ladeuil
Fix the last remaining failures.
401
        if (self.transport_server is not None
402
            and issubclass(self.transport_server,
403
                           test_server.SmartTCPServer_for_testing)):
3703.3.7 by Andrew Bennetts
Move empty push effort tests to branch_implementations.
404
            raise tests.TestNotApplicable(
405
                'Does not apply when remote backing branch is also '
406
                'a smart branch')
5674.1.1 by Jelmer Vernooij
Add supports_leave_lock flag to BranchFormat and RepositoryFormat.
407
        if not self.branch_format.supports_leaving_lock():
3703.3.7 by Andrew Bennetts
Move empty push effort tests to branch_implementations.
408
            raise tests.TestNotApplicable(
5674.1.1 by Jelmer Vernooij
Add supports_leave_lock flag to BranchFormat and RepositoryFormat.
409
                'Branch format is not usable via HPSS.')
3703.3.7 by Andrew Bennetts
Move empty push effort tests to branch_implementations.
410
        super(EmptyPushSmartEffortTests, self).setUp()
411
        # Create a smart server that publishes whatever the backing VFS server
412
        # does.
5017.3.29 by Vincent Ladeuil
-s bt.per_branch.test_push passing
413
        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,
414
        self.start_server(self.smart_server, self.get_server())
3703.3.7 by Andrew Bennetts
Move empty push effort tests to branch_implementations.
415
        # Make two empty branches, 'empty' and 'target'.
416
        self.empty_branch = self.make_branch('empty')
417
        self.make_branch('target')
418
        # Log all HPSS calls into self.hpss_calls.
419
        client._SmartClient.hooks.install_named_hook(
420
            'call', self.capture_hpss_call, None)
421
        self.hpss_calls = []
422
423
    def capture_hpss_call(self, params):
424
        self.hpss_calls.append(params.method)
425
426
    def test_empty_branch_api(self):
427
        """The branch_obj.push API should make a limited number of HPSS calls.
428
        """
6039.1.5 by Jelmer Vernooij
Add get_transport_from_url and get_transport_from_path functions.
429
        t = transport.get_transport_from_url(self.smart_server.get_url()).clone('target')
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
430
        target = branch.Branch.open_from_transport(t)
3703.3.7 by Andrew Bennetts
Move empty push effort tests to branch_implementations.
431
        self.empty_branch.push(target)
432
        self.assertEqual(
4634.47.8 by Andrew Bennetts
Fix per_branch.test_push effort test to expect new verb.
433
            ['BzrDir.open_2.1',
4734.4.13 by Andrew Bennetts
Fix trivial test failure.
434
             'BzrDir.open_branchV3',
4053.1.4 by Robert Collins
Move the fetch control attributes from Repository to RepositoryFormat.
435
             'BzrDir.find_repositoryV3',
3703.3.7 by Andrew Bennetts
Move empty push effort tests to branch_implementations.
436
             'Branch.get_stacked_on_url',
437
             'Branch.lock_write',
438
             'Branch.last_revision_info',
439
             'Branch.unlock'],
440
            self.hpss_calls)
441
442
    def test_empty_branch_command(self):
443
        """The 'bzr push' command should make a limited number of HPSS calls.
444
        """
445
        cmd = builtins.cmd_push()
446
        cmd.outf = tests.StringIOWrapper()
447
        cmd.run(
4420.1.2 by Vincent Ladeuil
Fix bug #284038 by adding a --strict option to push.
448
            directory=self.get_url('empty'),
4420.1.4 by Vincent Ladeuil
Cleanup.
449
            location=self.smart_server.get_url() + 'target')
3703.3.7 by Andrew Bennetts
Move empty push effort tests to branch_implementations.
450
        # HPSS calls as of 2008/09/22:
451
        # [BzrDir.open, BzrDir.open_branch, BzrDir.find_repositoryV2,
452
        # Branch.get_stacked_on_url, get, get, Branch.lock_write,
453
        # Branch.last_revision_info, Branch.unlock]
454
        self.assertTrue(len(self.hpss_calls) <= 9, self.hpss_calls)
455
456
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
457
class TestLossyPush(per_branch.TestCaseWithBranch):
4347.3.2 by Jelmer Vernooij
Add some basic tests for lossy_push.
458
459
    def setUp(self):
460
        self.hook_calls = []
5010.2.18 by Vincent Ladeuil
Fix imports in per_branch/test_push.py.
461
        super(TestLossyPush, self).setUp()
4347.3.2 by Jelmer Vernooij
Add some basic tests for lossy_push.
462
463
    def test_lossy_push_raises_same_vcs(self):
464
        target = self.make_branch('target')
465
        source = self.make_branch('source')
5853.2.3 by Jelmer Vernooij
Fix lossy tests.
466
        self.assertRaises(errors.LossyPushToSameVCS, source.push, target, lossy=True)