53
56
parent.commit('merge other', rev_id='P2')
54
57
mine.pull(parent.branch)
55
58
self.assertEqual(['P1', 'P2'], mine.branch.revision_history())
60
def test_pull_updates_checkout_and_master(self):
61
"""Pulling into a checkout updates the checkout and the master branch"""
62
master_tree = self.make_branch_and_tree('master')
63
rev1 = master_tree.commit('master')
64
checkout = master_tree.branch.create_checkout('checkout')
66
other = master_tree.branch.bzrdir.sprout('other').open_workingtree()
67
rev2 = other.commit('other commit')
68
# now pull, which should update both checkout and master.
69
checkout.branch.pull(other.branch)
70
self.assertEqual([rev1, rev2], checkout.branch.revision_history())
71
self.assertEqual([rev1, rev2], master_tree.branch.revision_history())
73
def test_pull_raises_specific_error_on_master_connection_error(self):
74
master_tree = self.make_branch_and_tree('master')
75
checkout = master_tree.branch.create_checkout('checkout')
76
other = master_tree.branch.bzrdir.sprout('other').open_workingtree()
77
# move the branch out of the way on disk to cause a connection
79
os.rename('master', 'master_gone')
80
# try to pull, which should raise a BoundBranchConnectionFailure.
81
self.assertRaises(errors.BoundBranchConnectionFailure,
82
checkout.branch.pull, other.branch)
84
def test_pull_returns_result(self):
85
parent = self.make_branch_and_tree('parent')
86
parent.commit('1st post', rev_id='P1')
87
mine = parent.bzrdir.sprout('mine').open_workingtree()
88
mine.commit('my change', rev_id='M1')
89
result = parent.branch.pull(mine.branch)
90
self.assertIsNot(None, result)
91
self.assertIs(mine.branch, result.source_branch)
92
self.assertIs(parent.branch, result.target_branch)
93
self.assertIs(parent.branch, result.master_branch)
94
self.assertIs(None, result.local_branch)
95
self.assertEqual(1, result.old_revno)
96
self.assertEqual('P1', result.old_revid)
97
self.assertEqual(2, result.new_revno)
98
self.assertEqual('M1', result.new_revid)
99
self.assertEqual(None, result.tag_conflicts)
101
def test_pull_overwrite(self):
102
tree_a = self.make_branch_and_tree('tree_a')
103
tree_a.commit('message 1')
104
tree_b = tree_a.bzrdir.sprout('tree_b').open_workingtree()
105
tree_a.commit('message 2', rev_id='rev2a')
106
tree_b.commit('message 2', rev_id='rev2b')
107
self.assertRaises(errors.DivergedBranches, tree_a.pull, tree_b.branch)
108
self.assertRaises(errors.DivergedBranches,
109
tree_a.branch.pull, tree_b.branch,
110
overwrite=False, stop_revision='rev2b')
111
# It should not have updated the branch tip, but it should have fetched
113
self.assertEqual('rev2a', tree_a.branch.last_revision())
114
self.assertTrue(tree_a.branch.repository.has_revision('rev2b'))
115
tree_a.branch.pull(tree_b.branch, overwrite=True,
116
stop_revision='rev2b')
117
self.assertEqual('rev2b', tree_a.branch.last_revision())
118
self.assertEqual(tree_b.branch.revision_history(),
119
tree_a.branch.revision_history())
122
class TestPullHook(TestCaseWithBranch):
126
TestCaseWithBranch.setUp(self)
128
def capture_post_pull_hook(self, result):
129
"""Capture post pull hook calls to self.hook_calls.
131
The call is logged, as is some state of the two branches.
133
if result.local_branch:
134
local_locked = result.local_branch.is_locked()
135
local_base = result.local_branch.base
139
self.hook_calls.append(
140
('post_pull', result.source_branch, local_base,
141
result.master_branch.base, result.old_revno,
143
result.new_revno, result.new_revid,
144
result.source_branch.is_locked(), local_locked,
145
result.master_branch.is_locked()))
147
def test_post_pull_empty_history(self):
148
target = self.make_branch('target')
149
source = self.make_branch('source')
150
Branch.hooks.install_named_hook('post_pull',
151
self.capture_post_pull_hook, None)
153
# with nothing there we should still get a notification, and
154
# have both branches locked at the notification time.
156
('post_pull', source, None, target.base, 0, NULL_REVISION,
157
0, NULL_REVISION, True, None, True)
161
def test_post_pull_bound_branch(self):
162
# pulling to a bound branch should pass in the master branch to the
163
# 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
166
target = self.make_branch('target')
167
local = self.make_branch('local')
170
except errors.UpgradeRequired:
171
# We can't bind this format to itself- typically it is the local
172
# branch that doesn't support binding. As of May 2007
173
# remotebranches can't be bound. Let's instead make a new local
174
# branch of the default type, which does allow binding.
175
# See https://bugs.launchpad.net/bzr/+bug/112020
176
local = BzrDir.create_branch_convenience('local2')
178
source = self.make_branch('source')
179
Branch.hooks.install_named_hook('post_pull',
180
self.capture_post_pull_hook, None)
182
# with nothing there we should still get a notification, and
183
# have both branches locked at the notification time.
185
('post_pull', source, local.base, target.base, 0, NULL_REVISION,
186
0, NULL_REVISION, True, True, True)
190
def test_post_pull_nonempty_history(self):
191
target = self.make_branch_and_memory_tree('target')
194
rev1 = target.commit('rev 1')
196
sourcedir = target.bzrdir.clone(self.get_url('source'))
197
source = MemoryTree.create_on_branch(sourcedir.open_branch())
198
rev2 = source.commit('rev 2')
199
Branch.hooks.install_named_hook('post_pull',
200
self.capture_post_pull_hook, None)
201
target.branch.pull(source.branch)
202
# with nothing there we should still get a notification, and
203
# have both branches locked at the notification time.
205
('post_pull', source.branch, None, target.branch.base, 1, rev1,
206
2, rev2, True, None, True)