~bzr-pqm/bzr/bzr.dev

5273.1.5 by Vincent Ladeuil
Merge bzr.dev into cleanup
1
# Copyright (C) 2009, 2010 Canonical Ltd
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
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
4000.5.16 by Jelmer Vernooij
Fix FSF address.
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
16
17
"""Tests for InterBranch.pull behaviour."""
18
19
from bzrlib.branch import Branch
6472.2.2 by Jelmer Vernooij
Use controldir rather than bzrdir in a couple more places.
20
from bzrlib.controldir import ControlDir
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
21
from bzrlib import errors
22
from bzrlib.memorytree import MemoryTree
23
from bzrlib.revision import NULL_REVISION
24
from bzrlib.tests.per_interbranch import TestCaseWithInterBranch
25
26
4000.5.23 by Jelmer Vernooij
Review feedback from Ian; add some comments about origin of tests, comment on further work in pull.
27
# The tests here are based on the tests in 
4523.1.1 by Martin Pool
Rename tests.branch_implementations to per_branch
28
# bzrlib.tests.per_branch.test_pull
4000.5.23 by Jelmer Vernooij
Review feedback from Ian; add some comments about origin of tests, comment on further work in pull.
29
30
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
31
class TestPull(TestCaseWithInterBranch):
32
33
    def test_pull_convergence_simple(self):
34
        # when revisions are pulled, the left-most accessible parents must
35
        # become the revision-history.
4000.5.20 by Jelmer Vernooij
Fix InterBranch.pull tests.
36
        parent = self.make_from_branch_and_tree('parent')
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
37
        parent.commit('1st post', rev_id='P1', allow_pointless=True)
38
        mine = self.sprout_to(parent.bzrdir, 'mine').open_workingtree()
39
        mine.commit('my change', rev_id='M1', allow_pointless=True)
40
        parent.merge_from_branch(mine.branch)
41
        parent.commit('merge my change', rev_id='P2')
42
        mine.pull(parent.branch)
6165.4.4 by Jelmer Vernooij
Avoid .revision_history().
43
        self.assertEqual('P2', mine.branch.last_revision())
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
44
45
    def test_pull_merged_indirect(self):
46
        # it should be possible to do a pull from one branch into another
47
        # when the tip of the target was merged into the source branch
48
        # via a third branch - so its buried in the ancestry and is not
49
        # directly accessible.
4000.5.20 by Jelmer Vernooij
Fix InterBranch.pull tests.
50
        parent = self.make_from_branch_and_tree('parent')
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
51
        parent.commit('1st post', rev_id='P1', allow_pointless=True)
52
        mine = self.sprout_to(parent.bzrdir, 'mine').open_workingtree()
53
        mine.commit('my change', rev_id='M1', allow_pointless=True)
4000.5.20 by Jelmer Vernooij
Fix InterBranch.pull tests.
54
        other = self.sprout_to(parent.bzrdir, 'other').open_workingtree()
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
55
        other.merge_from_branch(mine.branch)
56
        other.commit('merge my change', rev_id='O2')
57
        parent.merge_from_branch(other.branch)
58
        parent.commit('merge other', rev_id='P2')
59
        mine.pull(parent.branch)
6165.4.4 by Jelmer Vernooij
Avoid .revision_history().
60
        self.assertEqual('P2', mine.branch.last_revision())
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
61
62
    def test_pull_updates_checkout_and_master(self):
63
        """Pulling into a checkout updates the checkout and the master branch"""
4000.5.20 by Jelmer Vernooij
Fix InterBranch.pull tests.
64
        master_tree = self.make_from_branch_and_tree('master')
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
65
        rev1 = master_tree.commit('master')
66
        checkout = master_tree.branch.create_checkout('checkout')
4000.5.20 by Jelmer Vernooij
Fix InterBranch.pull tests.
67
        other = self.sprout_to(master_tree.branch.bzrdir, 'other').open_workingtree()
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
68
        rev2 = other.commit('other commit')
69
        # now pull, which should update both checkout and master.
70
        checkout.branch.pull(other.branch)
6165.4.4 by Jelmer Vernooij
Avoid .revision_history().
71
        self.assertEqual(rev2, checkout.branch.last_revision())
72
        self.assertEqual(rev2, master_tree.branch.last_revision())
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
73
74
    def test_pull_raises_specific_error_on_master_connection_error(self):
4000.5.20 by Jelmer Vernooij
Fix InterBranch.pull tests.
75
        master_tree = self.make_from_branch_and_tree('master')
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
76
        checkout = master_tree.branch.create_checkout('checkout')
5284.4.1 by Robert Collins
* Fetching was slightly confused about the best code to use and was
77
        other = self.sprout_to(master_tree.branch.bzrdir, 'other').open_branch()
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
78
        # move the branch out of the way on disk to cause a connection
79
        # error.
6155.1.3 by Jelmer Vernooij
Use standard mechanism for destroying branch.
80
        master_tree.branch.bzrdir.destroy_branch()
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
81
        # try to pull, which should raise a BoundBranchConnectionFailure.
82
        self.assertRaises(errors.BoundBranchConnectionFailure,
5284.4.1 by Robert Collins
* Fetching was slightly confused about the best code to use and was
83
                checkout.branch.pull, other)
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
84
85
    def test_pull_returns_result(self):
4000.5.20 by Jelmer Vernooij
Fix InterBranch.pull tests.
86
        parent = self.make_from_branch_and_tree('parent')
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
87
        parent.commit('1st post', rev_id='P1')
88
        mine = self.sprout_to(parent.bzrdir, 'mine').open_workingtree()
89
        mine.commit('my change', rev_id='M1')
90
        result = parent.branch.pull(mine.branch)
91
        self.assertIsNot(None, result)
92
        self.assertIs(mine.branch, result.source_branch)
93
        self.assertIs(parent.branch, result.target_branch)
94
        self.assertIs(parent.branch, result.master_branch)
95
        self.assertIs(None, result.local_branch)
96
        self.assertEqual(1, result.old_revno)
97
        self.assertEqual('P1', result.old_revid)
98
        self.assertEqual(2, result.new_revno)
99
        self.assertEqual('M1', result.new_revid)
6112.4.7 by Jelmer Vernooij
Fix tests.
100
        self.assertEqual([], result.tag_conflicts)
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
101
102
    def test_pull_overwrite(self):
4000.5.20 by Jelmer Vernooij
Fix InterBranch.pull tests.
103
        tree_a = self.make_from_branch_and_tree('tree_a')
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
104
        tree_a.commit('message 1')
105
        tree_b = self.sprout_to(tree_a.bzrdir, 'tree_b').open_workingtree()
106
        tree_a.commit('message 2', rev_id='rev2a')
107
        tree_b.commit('message 2', rev_id='rev2b')
108
        self.assertRaises(errors.DivergedBranches, tree_a.pull, tree_b.branch)
109
        self.assertRaises(errors.DivergedBranches,
110
                          tree_a.branch.pull, tree_b.branch,
111
                          overwrite=False, stop_revision='rev2b')
112
        # It should not have updated the branch tip, but it should have fetched
6217.4.1 by Jelmer Vernooij
Add RepositoryFormat.supports_invisible_revisions.
113
        # the revision if the repository supports "invisible" revisions.
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
114
        self.assertEqual('rev2a', tree_a.branch.last_revision())
6217.4.2 by Jelmer Vernooij
s/invisible/unreferenced.
115
        if tree_a.branch.repository._format.supports_unreferenced_revisions:
6217.4.1 by Jelmer Vernooij
Add RepositoryFormat.supports_invisible_revisions.
116
            self.assertTrue(tree_a.branch.repository.has_revision('rev2b'))
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
117
        tree_a.branch.pull(tree_b.branch, overwrite=True,
118
                           stop_revision='rev2b')
119
        self.assertEqual('rev2b', tree_a.branch.last_revision())
6165.4.4 by Jelmer Vernooij
Avoid .revision_history().
120
        self.assertEqual(tree_b.branch.last_revision(),
121
                         tree_a.branch.last_revision())
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
122
123
124
class TestPullHook(TestCaseWithInterBranch):
125
126
    def setUp(self):
127
        self.hook_calls = []
128
        TestCaseWithInterBranch.setUp(self)
129
130
    def capture_post_pull_hook(self, result):
131
        """Capture post pull hook calls to self.hook_calls.
132
133
        The call is logged, as is some state of the two branches.
134
        """
135
        if result.local_branch:
136
            local_locked = result.local_branch.is_locked()
137
            local_base = result.local_branch.base
138
        else:
139
            local_locked = None
140
            local_base = None
141
        self.hook_calls.append(
142
            ('post_pull', result.source_branch, local_base,
143
             result.master_branch.base, result.old_revno,
144
             result.old_revid,
145
             result.new_revno, result.new_revid,
146
             result.source_branch.is_locked(), local_locked,
147
             result.master_branch.is_locked()))
148
149
    def test_post_pull_empty_history(self):
150
        target = self.make_to_branch('target')
4000.5.20 by Jelmer Vernooij
Fix InterBranch.pull tests.
151
        source = self.make_from_branch('source')
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
152
        Branch.hooks.install_named_hook('post_pull',
153
            self.capture_post_pull_hook, None)
154
        target.pull(source)
155
        # with nothing there we should still get a notification, and
156
        # have both branches locked at the notification time.
157
        self.assertEqual([
158
            ('post_pull', source, None, target.base, 0, NULL_REVISION,
159
             0, NULL_REVISION, True, None, True)
160
            ],
161
            self.hook_calls)
162
163
    def test_post_pull_bound_branch(self):
164
        # pulling to a bound branch should pass in the master branch to the
165
        # hook, allowing the correct number of emails to be sent, while still
166
        # allowing hooks that want to modify the target to do so to both
167
        # instances.
168
        target = self.make_to_branch('target')
4000.5.20 by Jelmer Vernooij
Fix InterBranch.pull tests.
169
        local = self.make_from_branch('local')
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
170
        try:
171
            local.bind(target)
172
        except errors.UpgradeRequired:
173
            # We can't bind this format to itself- typically it is the local
174
            # branch that doesn't support binding.  As of May 2007
175
            # remotebranches can't be bound.  Let's instead make a new local
176
            # branch of the default type, which does allow binding.
177
            # See https://bugs.launchpad.net/bzr/+bug/112020
6472.2.2 by Jelmer Vernooij
Use controldir rather than bzrdir in a couple more places.
178
            local = ControlDir.create_branch_convenience('local2')
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
179
            local.bind(target)
4000.5.20 by Jelmer Vernooij
Fix InterBranch.pull tests.
180
        source = self.make_from_branch('source')
4000.5.11 by Jelmer Vernooij
Improve tests for InterBranch.pull.
181
        Branch.hooks.install_named_hook('post_pull',
182
            self.capture_post_pull_hook, None)
183
        local.pull(source)
184
        # with nothing there we should still get a notification, and
185
        # have both branches locked at the notification time.
186
        self.assertEqual([
187
            ('post_pull', source, local.base, target.base, 0, NULL_REVISION,
188
             0, NULL_REVISION, True, True, True)
189
            ],
190
            self.hook_calls)
191
192
    def test_post_pull_nonempty_history(self):
193
        target = self.make_to_branch_and_memory_tree('target')
194
        target.lock_write()
195
        target.add('')
196
        rev1 = target.commit('rev 1')
197
        target.unlock()
198
        sourcedir = target.bzrdir.clone(self.get_url('source'))
199
        source = MemoryTree.create_on_branch(sourcedir.open_branch())
200
        rev2 = source.commit('rev 2')
201
        Branch.hooks.install_named_hook('post_pull',
202
            self.capture_post_pull_hook, None)
203
        target.branch.pull(source.branch)
204
        # with nothing there we should still get a notification, and
205
        # have both branches locked at the notification time.
206
        self.assertEqual([
207
            ('post_pull', source.branch, None, target.branch.base, 1, rev1,
208
             2, rev2, True, None, True)
209
            ],
210
            self.hook_calls)