1
# Copyright (C) 2004, 2005, 2007 Canonical Ltd
1
# Copyright (C) 2006-2010 Canonical Ltd
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
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
17
17
"""Tests for branch.pull behaviour."""
21
from bzrlib.branch import Branch, BzrBranchFormat5
22
from bzrlib.bzrdir import BzrDir
23
from bzrlib import errors
24
from bzrlib.memorytree import MemoryTree
25
from bzrlib.revision import NULL_REVISION
26
from bzrlib.tests.branch_implementations.test_branch import TestCaseWithBranch
29
class TestPull(TestCaseWithBranch):
28
from bzrlib.tests import per_branch
31
class TestPull(per_branch.TestCaseWithBranch):
31
33
def test_pull_convergence_simple(self):
32
# when revisions are pulled, the left-most accessible parents must
34
# when revisions are pulled, the left-most accessible parents must
33
35
# become the revision-history.
34
36
parent = self.make_branch_and_tree('parent')
35
37
parent.commit('1st post', rev_id='P1', allow_pointless=True)
70
72
self.assertEqual([rev1, rev2], checkout.branch.revision_history())
71
73
self.assertEqual([rev1, rev2], master_tree.branch.revision_history())
75
def test_pull_local_updates_checkout_only(self):
76
"""Pulling --local into a checkout updates the checkout and not the
78
master_tree = self.make_branch_and_tree('master')
79
rev1 = master_tree.commit('master')
80
checkout = master_tree.branch.create_checkout('checkout')
82
other = master_tree.branch.bzrdir.sprout('other').open_workingtree()
83
rev2 = other.commit('other commit')
84
# now pull local, which should update checkout but not master.
85
checkout.branch.pull(other.branch, local = True)
86
self.assertEqual([rev1, rev2], checkout.branch.revision_history())
87
self.assertEqual([rev1], master_tree.branch.revision_history())
89
def test_pull_local_raises_LocalRequiresBoundBranch_on_unbound(self):
90
"""Pulling --local into a branch that is not bound should fail."""
91
master_tree = self.make_branch_and_tree('branch')
92
rev1 = master_tree.commit('master')
94
other = master_tree.branch.bzrdir.sprout('other').open_workingtree()
95
rev2 = other.commit('other commit')
96
# now pull --local, which should raise LocalRequiresBoundBranch error.
97
self.assertRaises(errors.LocalRequiresBoundBranch,
98
master_tree.branch.pull, other.branch, local = True)
99
self.assertEqual([rev1], master_tree.branch.revision_history())
73
101
def test_pull_raises_specific_error_on_master_connection_error(self):
74
102
master_tree = self.make_branch_and_tree('master')
75
103
checkout = master_tree.branch.create_checkout('checkout')
119
147
tree_a.branch.revision_history())
122
class TestPullHook(TestCaseWithBranch):
150
class TestPullHook(per_branch.TestCaseWithBranch):
125
153
self.hook_calls = []
126
TestCaseWithBranch.setUp(self)
154
super(TestPullHook, self).setUp()
128
156
def capture_post_pull_hook(self, result):
129
157
"""Capture post pull hook calls to self.hook_calls.
131
159
The call is logged, as is some state of the two branches.
133
161
if result.local_branch:
147
175
def test_post_pull_empty_history(self):
148
176
target = self.make_branch('target')
149
177
source = self.make_branch('source')
150
Branch.hooks.install_named_hook('post_pull',
151
self.capture_post_pull_hook, None)
178
branch.Branch.hooks.install_named_hook(
179
'post_pull', self.capture_post_pull_hook, None)
152
180
target.pull(source)
153
181
# with nothing there we should still get a notification, and
154
182
# have both branches locked at the notification time.
155
183
self.assertEqual([
156
('post_pull', source, None, target.base, 0, NULL_REVISION,
157
0, NULL_REVISION, True, None, True)
184
('post_pull', source, None, target.base, 0, revision.NULL_REVISION,
185
0, revision.NULL_REVISION, True, None, True)
161
189
def test_post_pull_bound_branch(self):
162
190
# pulling to a bound branch should pass in the master branch to the
163
191
# hook, allowing the correct number of emails to be sent, while still
164
# allowing hooks that want to modify the target to do so to both
192
# allowing hooks that want to modify the target to do so to both
166
194
target = self.make_branch('target')
167
195
local = self.make_branch('local')
173
201
# remotebranches can't be bound. Let's instead make a new local
174
202
# branch of the default type, which does allow binding.
175
203
# See https://bugs.launchpad.net/bzr/+bug/112020
176
local = BzrDir.create_branch_convenience('local2')
204
local = bzrdir.BzrDir.create_branch_convenience('local2')
177
205
local.bind(target)
178
206
source = self.make_branch('source')
179
Branch.hooks.install_named_hook('post_pull',
180
self.capture_post_pull_hook, None)
207
branch.Branch.hooks.install_named_hook(
208
'post_pull', self.capture_post_pull_hook, None)
181
209
local.pull(source)
182
210
# with nothing there we should still get a notification, and
183
211
# have both branches locked at the notification time.
184
212
self.assertEqual([
185
('post_pull', source, local.base, target.base, 0, NULL_REVISION,
186
0, NULL_REVISION, True, True, True)
213
('post_pull', source, local.base, target.base, 0,
214
revision.NULL_REVISION, 0, revision.NULL_REVISION,
194
223
rev1 = target.commit('rev 1')
196
225
sourcedir = target.bzrdir.clone(self.get_url('source'))
197
source = MemoryTree.create_on_branch(sourcedir.open_branch())
226
source = memorytree.MemoryTree.create_on_branch(sourcedir.open_branch())
198
227
rev2 = source.commit('rev 2')
199
Branch.hooks.install_named_hook('post_pull',
200
self.capture_post_pull_hook, None)
228
branch.Branch.hooks.install_named_hook(
229
'post_pull', self.capture_post_pull_hook, None)
201
230
target.branch.pull(source.branch)
202
231
# with nothing there we should still get a notification, and
203
232
# have both branches locked at the notification time.