/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
4988.10.5 by John Arbash Meinel
Merge bzr.dev 5021 to resolve NEWS
1
# Copyright (C) 2006-2010 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1649.1.1 by Robert Collins
* 'pull' and 'push' now normalise the revision history, so that any two
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1649.1.1 by Robert Collins
* 'pull' and 'push' now normalise the revision history, so that any two
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1649.1.1 by Robert Collins
* 'pull' and 'push' now normalise the revision history, so that any two
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
1649.1.1 by Robert Collins
* 'pull' and 'push' now normalise the revision history, so that any two
16
17
"""Tests for branch.pull behaviour."""
18
19
import os
20
5010.2.17 by Vincent Ladeuil
Fix imports in per_branch/test_pull.py.
21
from bzrlib import (
22
    branch,
23
    bzrdir,
24
    errors,
25
    memorytree,
26
    revision,
27
    )
5535.3.29 by Andrew Bennetts
Add some per-branch tests.
28
from bzrlib.tests import per_branch, TestNotApplicable
5010.2.17 by Vincent Ladeuil
Fix imports in per_branch/test_pull.py.
29
30
31
class TestPull(per_branch.TestCaseWithBranch):
1649.1.1 by Robert Collins
* 'pull' and 'push' now normalise the revision history, so that any two
32
33
    def test_pull_convergence_simple(self):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
34
        # when revisions are pulled, the left-most accessible parents must
1649.1.1 by Robert Collins
* 'pull' and 'push' now normalise the revision history, so that any two
35
        # become the revision-history.
36
        parent = self.make_branch_and_tree('parent')
37
        parent.commit('1st post', rev_id='P1', allow_pointless=True)
38
        mine = parent.bzrdir.sprout('mine').open_workingtree()
39
        mine.commit('my change', rev_id='M1', allow_pointless=True)
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
40
        parent.merge_from_branch(mine.branch)
1649.1.1 by Robert Collins
* 'pull' and 'push' now normalise the revision history, so that any two
41
        parent.commit('merge my change', rev_id='P2')
42
        mine.pull(parent.branch)
43
        self.assertEqual(['P1', 'P2'], mine.branch.revision_history())
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.
50
        parent = self.make_branch_and_tree('parent')
51
        parent.commit('1st post', rev_id='P1', allow_pointless=True)
52
        mine = parent.bzrdir.sprout('mine').open_workingtree()
53
        mine.commit('my change', rev_id='M1', allow_pointless=True)
54
        other = parent.bzrdir.sprout('other').open_workingtree()
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
55
        other.merge_from_branch(mine.branch)
1649.1.1 by Robert Collins
* 'pull' and 'push' now normalise the revision history, so that any two
56
        other.commit('merge my change', rev_id='O2')
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
57
        parent.merge_from_branch(other.branch)
1649.1.1 by Robert Collins
* 'pull' and 'push' now normalise the revision history, so that any two
58
        parent.commit('merge other', rev_id='P2')
59
        mine.pull(parent.branch)
60
        self.assertEqual(['P1', 'P2'], mine.branch.revision_history())
2245.2.1 by Robert Collins
Split branch pushing out of branch pulling.
61
62
    def test_pull_updates_checkout_and_master(self):
63
        """Pulling into a checkout updates the checkout and the master branch"""
64
        master_tree = self.make_branch_and_tree('master')
65
        rev1 = master_tree.commit('master')
66
        checkout = master_tree.branch.create_checkout('checkout')
67
68
        other = master_tree.branch.bzrdir.sprout('other').open_workingtree()
69
        rev2 = other.commit('other commit')
70
        # now pull, which should update both checkout and master.
71
        checkout.branch.pull(other.branch)
72
        self.assertEqual([rev1, rev2], checkout.branch.revision_history())
73
        self.assertEqual([rev1, rev2], master_tree.branch.revision_history())
74
4056.6.3 by Gary van der Merwe
Add local args to pull methods, and add more tests
75
    def test_pull_local_updates_checkout_only(self):
76
        """Pulling --local into a checkout updates the checkout and not the
77
        master branch"""
78
        master_tree = self.make_branch_and_tree('master')
79
        rev1 = master_tree.commit('master')
80
        checkout = master_tree.branch.create_checkout('checkout')
81
82
        other = master_tree.branch.bzrdir.sprout('other').open_workingtree()
83
        rev2 = other.commit('other commit')
4335.1.1 by Ian Clatworthy
(igc) pull --local (Gary van der Merwe)
84
        # now pull local, which should update checkout but not master.
4056.6.3 by Gary van der Merwe
Add local args to pull methods, and add more tests
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())
88
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')
93
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())
100
3482.1.1 by John Arbash Meinel
Fix bug #238149, RemoteBranch.pull needs to return the _real_branch's pull result.
101
    def test_pull_returns_result(self):
102
        parent = self.make_branch_and_tree('parent')
103
        parent.commit('1st post', rev_id='P1')
104
        mine = parent.bzrdir.sprout('mine').open_workingtree()
105
        mine.commit('my change', rev_id='M1')
106
        result = parent.branch.pull(mine.branch)
107
        self.assertIsNot(None, result)
108
        self.assertIs(mine.branch, result.source_branch)
109
        self.assertIs(parent.branch, result.target_branch)
110
        self.assertIs(parent.branch, result.master_branch)
111
        self.assertIs(None, result.local_branch)
112
        self.assertEqual(1, result.old_revno)
113
        self.assertEqual('P1', result.old_revid)
114
        self.assertEqual(2, result.new_revno)
115
        self.assertEqual('M1', result.new_revid)
116
        self.assertEqual(None, result.tag_conflicts)
117
1551.10.23 by Aaron Bentley
Update test case per review
118
    def test_pull_overwrite(self):
119
        tree_a = self.make_branch_and_tree('tree_a')
120
        tree_a.commit('message 1')
121
        tree_b = tree_a.bzrdir.sprout('tree_b').open_workingtree()
122
        tree_a.commit('message 2', rev_id='rev2a')
123
        tree_b.commit('message 2', rev_id='rev2b')
124
        self.assertRaises(errors.DivergedBranches, tree_a.pull, tree_b.branch)
3052.5.2 by John Arbash Meinel
Use a Graph.heads() check to determine if the ancestries are compatible.
125
        self.assertRaises(errors.DivergedBranches,
126
                          tree_a.branch.pull, tree_b.branch,
127
                          overwrite=False, stop_revision='rev2b')
128
        # It should not have updated the branch tip, but it should have fetched
129
        # the revision
130
        self.assertEqual('rev2a', tree_a.branch.last_revision())
131
        self.assertTrue(tree_a.branch.repository.has_revision('rev2b'))
2975.1.1 by Robert Collins
Minor fixes for foreign format friendliness.
132
        tree_a.branch.pull(tree_b.branch, overwrite=True,
1551.10.23 by Aaron Bentley
Update test case per review
133
                           stop_revision='rev2b')
134
        self.assertEqual('rev2b', tree_a.branch.last_revision())
135
        self.assertEqual(tree_b.branch.revision_history(),
136
                         tree_a.branch.revision_history())
137
5535.3.29 by Andrew Bennetts
Add some per-branch tests.
138
    def test_pull_merges_and_fetches_tags(self):
139
        """Tags are updated by br.pull(source), and revisions named in those
140
        tags are fetched.
141
        """
142
        # Make a source, sprout a target off it
143
        try:
144
            builder = self.make_branch_builder('source')
145
        except errors.UninitializableFormat:
146
            raise TestNotApplicable('uninitializeable format')
147
        builder.build_commit(message="Rev 1", rev_id='rev-1')
148
        source = builder.get_branch()
149
        target = source.bzrdir.sprout('target').open_branch()
150
        # Add a non-ancestry tag to source
151
        builder.build_commit(message="Rev 2", rev_id='rev-2')
152
        try:
153
            source.tags.set_tag('tag-a', 'rev-2')
154
        except errors.TagsNotSupported:
155
            raise TestNotApplicable('format does not support tags.')
156
        source.set_last_revision_info(1, 'rev-1')
157
        # Pull from source
158
        target.pull(source)
159
        # The tag is present, and so is its revision.
160
        self.assertEqual('rev-2', target.tags.lookup_tag('tag-a'))
161
        target.repository.get_revision('rev-2')
162
163
    def test_pull_stop_revision_merges_and_fetches_tags(self):
164
        """br.pull(source, stop_revision=REV) updates and fetches tags."""
165
        # Make a source, sprout a target off it
166
        try:
167
            builder = self.make_branch_builder('source')
168
        except errors.UninitializableFormat:
169
            raise TestNotApplicable('uninitializeable format')
170
        builder.build_commit(message="Rev 1", rev_id='rev-1')
171
        source = builder.get_branch()
172
        target = source.bzrdir.sprout('target').open_branch()
173
        # Add a non-ancestry tag to source
174
        builder.build_commit(message="Rev 2", rev_id='rev-2')
175
        try:
176
            source.tags.set_tag('tag-a', 'rev-2')
177
        except errors.TagsNotSupported:
178
            raise TestNotApplicable('format does not support tags.')
179
        source.set_last_revision_info(1, 'rev-1')
180
        # Add a new commit to the ancestry
181
        builder.build_commit(message="Rev 2 again", rev_id='rev-2-again')
182
        # Pull from source
183
        target.pull(source, 'rev-2-again')
184
        # The tag is present, and so is its revision.
185
        self.assertEqual('rev-2', target.tags.lookup_tag('tag-a'))
186
        target.repository.get_revision('rev-2')
187
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
188
5010.2.17 by Vincent Ladeuil
Fix imports in per_branch/test_pull.py.
189
class TestPullHook(per_branch.TestCaseWithBranch):
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
190
191
    def setUp(self):
192
        self.hook_calls = []
5010.2.17 by Vincent Ladeuil
Fix imports in per_branch/test_pull.py.
193
        super(TestPullHook, self).setUp()
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
194
2297.1.1 by Martin Pool
Pull now returns a PullResult rather than just an integer.
195
    def capture_post_pull_hook(self, result):
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
196
        """Capture post pull hook calls to self.hook_calls.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
197
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
198
        The call is logged, as is some state of the two branches.
199
        """
2297.1.6 by Martin Pool
Add docs for Results, give some members cleaner names
200
        if result.local_branch:
201
            local_locked = result.local_branch.is_locked()
202
            local_base = result.local_branch.base
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
203
        else:
204
            local_locked = None
205
            local_base = None
206
        self.hook_calls.append(
2297.1.6 by Martin Pool
Add docs for Results, give some members cleaner names
207
            ('post_pull', result.source_branch, local_base,
208
             result.master_branch.base, result.old_revno,
2297.1.1 by Martin Pool
Pull now returns a PullResult rather than just an integer.
209
             result.old_revid,
2297.1.6 by Martin Pool
Add docs for Results, give some members cleaner names
210
             result.new_revno, result.new_revid,
211
             result.source_branch.is_locked(), local_locked,
212
             result.master_branch.is_locked()))
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
213
214
    def test_post_pull_empty_history(self):
215
        target = self.make_branch('target')
216
        source = self.make_branch('source')
5010.2.17 by Vincent Ladeuil
Fix imports in per_branch/test_pull.py.
217
        branch.Branch.hooks.install_named_hook(
218
            'post_pull', self.capture_post_pull_hook, None)
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
219
        target.pull(source)
220
        # with nothing there we should still get a notification, and
221
        # have both branches locked at the notification time.
222
        self.assertEqual([
5010.2.17 by Vincent Ladeuil
Fix imports in per_branch/test_pull.py.
223
            ('post_pull', source, None, target.base, 0, revision.NULL_REVISION,
224
             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
225
            ],
226
            self.hook_calls)
227
228
    def test_post_pull_bound_branch(self):
229
        # pulling to a bound branch should pass in the master branch to the
230
        # 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
231
        # 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
232
        # instances.
233
        target = self.make_branch('target')
234
        local = self.make_branch('local')
235
        try:
236
            local.bind(target)
237
        except errors.UpgradeRequired:
2477.1.2 by Martin Pool
Rename push/pull back to 'run_hooks' (jameinel)
238
            # We can't bind this format to itself- typically it is the local
239
            # branch that doesn't support binding.  As of May 2007
240
            # remotebranches can't be bound.  Let's instead make a new local
241
            # branch of the default type, which does allow binding.
242
            # See https://bugs.launchpad.net/bzr/+bug/112020
5010.2.17 by Vincent Ladeuil
Fix imports in per_branch/test_pull.py.
243
            local = bzrdir.BzrDir.create_branch_convenience('local2')
2477.1.2 by Martin Pool
Rename push/pull back to 'run_hooks' (jameinel)
244
            local.bind(target)
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
245
        source = self.make_branch('source')
5010.2.17 by Vincent Ladeuil
Fix imports in per_branch/test_pull.py.
246
        branch.Branch.hooks.install_named_hook(
247
            'post_pull', self.capture_post_pull_hook, None)
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
248
        local.pull(source)
249
        # with nothing there we should still get a notification, and
250
        # have both branches locked at the notification time.
251
        self.assertEqual([
5010.2.17 by Vincent Ladeuil
Fix imports in per_branch/test_pull.py.
252
            ('post_pull', source, local.base, target.base, 0,
253
             revision.NULL_REVISION, 0, revision.NULL_REVISION,
254
             True, True, True)
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
255
            ],
256
            self.hook_calls)
257
258
    def test_post_pull_nonempty_history(self):
259
        target = self.make_branch_and_memory_tree('target')
260
        target.lock_write()
261
        target.add('')
262
        rev1 = target.commit('rev 1')
263
        target.unlock()
264
        sourcedir = target.bzrdir.clone(self.get_url('source'))
5010.2.17 by Vincent Ladeuil
Fix imports in per_branch/test_pull.py.
265
        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
266
        rev2 = source.commit('rev 2')
5010.2.17 by Vincent Ladeuil
Fix imports in per_branch/test_pull.py.
267
        branch.Branch.hooks.install_named_hook(
268
            'post_pull', self.capture_post_pull_hook, None)
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
269
        target.branch.pull(source.branch)
270
        # with nothing there we should still get a notification, and
271
        # have both branches locked at the notification time.
272
        self.assertEqual([
273
            ('post_pull', source.branch, None, target.branch.base, 1, rev1,
274
             2, rev2, True, None, True)
275
            ],
276
            self.hook_calls)