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

  • Committer: John Arbash Meinel
  • Date: 2007-02-13 20:33:57 UTC
  • mfrom: (2283 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2294.
  • Revision ID: john@arbash-meinel.com-20070213203357-b7yg41mi9sk6cqd0
[merge] bzr.dev 2283
resolve conflicts in moved repository formats
small issue with osutils.contains_whitespace()

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2004, 2005, 2007 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
 
 
17
"""Tests for branch.push behaviour."""
 
18
 
 
19
import os
 
20
 
 
21
from bzrlib.branch import Branch
 
22
from bzrlib import errors
 
23
from bzrlib.memorytree import MemoryTree
 
24
from bzrlib.revision import NULL_REVISION
 
25
from bzrlib.tests.branch_implementations.test_branch import TestCaseWithBranch
 
26
 
 
27
 
 
28
class TestPush(TestCaseWithBranch):
 
29
 
 
30
    def test_push_convergence_simple(self):
 
31
        # when revisions are pushed, the left-most accessible parents must 
 
32
        # become the revision-history.
 
33
        mine = self.make_branch_and_tree('mine')
 
34
        mine.commit('1st post', rev_id='P1', allow_pointless=True)
 
35
        other = mine.bzrdir.sprout('other').open_workingtree()
 
36
        other.commit('my change', rev_id='M1', allow_pointless=True)
 
37
        mine.merge_from_branch(other.branch)
 
38
        mine.commit('merge my change', rev_id='P2')
 
39
        mine.branch.push(other.branch)
 
40
        self.assertEqual(['P1', 'P2'], other.branch.revision_history())
 
41
 
 
42
    def test_push_merged_indirect(self):
 
43
        # it should be possible to do a push from one branch into another
 
44
        # when the tip of the target was merged into the source branch
 
45
        # via a third branch - so its buried in the ancestry and is not
 
46
        # directly accessible.
 
47
        mine = self.make_branch_and_tree('mine')
 
48
        mine.commit('1st post', rev_id='P1', allow_pointless=True)
 
49
        target = mine.bzrdir.sprout('target').open_workingtree()
 
50
        target.commit('my change', rev_id='M1', allow_pointless=True)
 
51
        other = mine.bzrdir.sprout('other').open_workingtree()
 
52
        other.merge_from_branch(target.branch)
 
53
        other.commit('merge my change', rev_id='O2')
 
54
        mine.merge_from_branch(other.branch)
 
55
        mine.commit('merge other', rev_id='P2')
 
56
        mine.branch.push(target.branch)
 
57
        self.assertEqual(['P1', 'P2'], target.branch.revision_history())
 
58
 
 
59
    def test_push_to_checkout_updates_master(self):
 
60
        """Pushing into a checkout updates the checkout and the master branch"""
 
61
        master_tree = self.make_branch_and_tree('master')
 
62
        checkout = self.make_branch_and_tree('checkout')
 
63
        try:
 
64
            checkout.branch.bind(master_tree.branch)
 
65
        except errors.UpgradeRequired:
 
66
            # cant bind this format, the test is irrelevant.
 
67
            return
 
68
        rev1 = checkout.commit('master')
 
69
 
 
70
        other = master_tree.branch.bzrdir.sprout('other').open_workingtree()
 
71
        rev2 = other.commit('other commit')
 
72
        # now push, which should update both checkout and master.
 
73
        other.branch.push(checkout.branch)
 
74
        self.assertEqual([rev1, rev2], checkout.branch.revision_history())
 
75
        self.assertEqual([rev1, rev2], master_tree.branch.revision_history())
 
76
 
 
77
    def test_push_raises_specific_error_on_master_connection_error(self):
 
78
        master_tree = self.make_branch_and_tree('master')
 
79
        checkout = self.make_branch_and_tree('checkout')
 
80
        try:
 
81
            checkout.branch.bind(master_tree.branch)
 
82
        except errors.UpgradeRequired:
 
83
            # cant bind this format, the test is irrelevant.
 
84
            return
 
85
        other = master_tree.branch.bzrdir.sprout('other').open_workingtree()
 
86
        # move the branch out of the way on disk to cause a connection
 
87
        # error.
 
88
        os.rename('master', 'master_gone')
 
89
        # try to push, which should raise a BoundBranchConnectionFailure.
 
90
        self.assertRaises(errors.BoundBranchConnectionFailure,
 
91
                other.branch.push, checkout.branch)
 
92
 
 
93
    def test_push_uses_read_lock(self):
 
94
        """Push should only need a read lock on the source side."""
 
95
        source = self.make_branch_and_tree('source')
 
96
        target = self.make_branch('target')
 
97
 
 
98
        self.build_tree(['source/a'])
 
99
        source.add(['a'])
 
100
        source.commit('a')
 
101
 
 
102
        source.branch.lock_read()
 
103
        try:
 
104
            target.lock_write()
 
105
            try:
 
106
                source.branch.push(target, stop_revision=source.last_revision())
 
107
            finally:
 
108
                target.unlock()
 
109
        finally:
 
110
            source.branch.unlock()
 
111
 
 
112
    def test_push_within_repository(self):
 
113
        """Push from one branch to another inside the same repository."""
 
114
        try:
 
115
            repo = self.make_repository('repo', shared=True)
 
116
        except (errors.IncompatibleFormat, errors.UninitializableFormat):
 
117
            # This Branch format cannot create shared repositories
 
118
            return
 
119
        # This is a little bit trickier because make_branch_and_tree will not
 
120
        # re-use a shared repository.
 
121
        a_bzrdir = self.make_bzrdir('repo/tree')
 
122
        try:
 
123
            a_branch = self.branch_format.initialize(a_bzrdir)
 
124
        except (errors.UninitializableFormat):
 
125
            # Cannot create these branches
 
126
            return
 
127
        tree = a_branch.bzrdir.create_workingtree()
 
128
        self.build_tree(['repo/tree/a'])
 
129
        tree.add(['a'])
 
130
        tree.commit('a')
 
131
 
 
132
        to_bzrdir = self.make_bzrdir('repo/branch')
 
133
        to_branch = self.branch_format.initialize(to_bzrdir)
 
134
        tree.branch.push(to_branch)
 
135
 
 
136
        self.assertEqual(tree.branch.last_revision(),
 
137
                         to_branch.last_revision())
 
138
 
 
139
 
 
140
class TestPushHook(TestCaseWithBranch):
 
141
 
 
142
    def setUp(self):
 
143
        self.hook_calls = []
 
144
        TestCaseWithBranch.setUp(self)
 
145
 
 
146
    def capture_post_push_hook(self, source, local, master, old_revno,
 
147
        old_revid, new_revno, new_revid):
 
148
        """Capture post push hook calls to self.hook_calls.
 
149
        
 
150
        The call is logged, as is some state of the two branches.
 
151
        """
 
152
        if local:
 
153
            local_locked = local.is_locked()
 
154
            local_base = local.base
 
155
        else:
 
156
            local_locked = None
 
157
            local_base = None
 
158
        self.hook_calls.append(
 
159
            ('post_push', source, local_base, master.base, old_revno, old_revid,
 
160
             new_revno, new_revid, source.is_locked(), local_locked,
 
161
             master.is_locked()))
 
162
 
 
163
    def test_post_push_empty_history(self):
 
164
        target = self.make_branch('target')
 
165
        source = self.make_branch('source')
 
166
        Branch.hooks.install_hook('post_push', self.capture_post_push_hook)
 
167
        source.push(target)
 
168
        # with nothing there we should still get a notification, and
 
169
        # have both branches locked at the notification time.
 
170
        self.assertEqual([
 
171
            ('post_push', source, None, target.base, 0, NULL_REVISION,
 
172
             0, NULL_REVISION, True, None, True)
 
173
            ],
 
174
            self.hook_calls)
 
175
 
 
176
    def test_post_push_bound_branch(self):
 
177
        # pushing to a bound branch should pass in the master branch to the
 
178
        # hook, allowing the correct number of emails to be sent, while still
 
179
        # allowing hooks that want to modify the target to do so to both 
 
180
        # instances.
 
181
        target = self.make_branch('target')
 
182
        local = self.make_branch('local')
 
183
        try:
 
184
            local.bind(target)
 
185
        except errors.UpgradeRequired:
 
186
            # cant bind this format, the test is irrelevant.
 
187
            return
 
188
        source = self.make_branch('source')
 
189
        Branch.hooks.install_hook('post_push', self.capture_post_push_hook)
 
190
        source.push(local)
 
191
        # with nothing there we should still get a notification, and
 
192
        # have both branches locked at the notification time.
 
193
        self.assertEqual([
 
194
            ('post_push', source, local.base, target.base, 0, NULL_REVISION,
 
195
             0, NULL_REVISION, True, True, True)
 
196
            ],
 
197
            self.hook_calls)
 
198
 
 
199
    def test_post_push_nonempty_history(self):
 
200
        target = self.make_branch_and_memory_tree('target')
 
201
        target.lock_write()
 
202
        target.add('')
 
203
        rev1 = target.commit('rev 1')
 
204
        target.unlock()
 
205
        sourcedir = target.bzrdir.clone(self.get_url('source'))
 
206
        source = MemoryTree.create_on_branch(sourcedir.open_branch())
 
207
        rev2 = source.commit('rev 2')
 
208
        Branch.hooks.install_hook('post_push', self.capture_post_push_hook)
 
209
        source.branch.push(target.branch)
 
210
        # with nothing there we should still get a notification, and
 
211
        # have both branches locked at the notification time.
 
212
        self.assertEqual([
 
213
            ('post_push', source.branch, None, target.branch.base, 1, rev1,
 
214
             2, rev2, True, None, True)
 
215
            ],
 
216
            self.hook_calls)