~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/blackbox/test_pull.py

(vila) Calling super() instead of mentioning the base class in setUp avoid
 mistakes. (Vincent Ladeuil)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 by Canonical Ltd
2
 
# -*- coding: utf-8 -*-
3
 
 
 
1
# Copyright (C) 2005-2012 Canonical Ltd
 
2
#
4
3
# This program is free software; you can redistribute it and/or modify
5
4
# it under the terms of the GNU General Public License as published by
6
5
# the Free Software Foundation; either version 2 of the License, or
7
6
# (at your option) any later version.
8
 
 
 
7
#
9
8
# This program is distributed in the hope that it will be useful,
10
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
11
# GNU General Public License for more details.
13
 
 
 
12
#
14
13
# You should have received a copy of the GNU General Public License
15
14
# along with this program; if not, write to the Free Software
16
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 
 
18
 
 
19
 
"""Black-box tests for bzr pull.
20
 
"""
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
 
 
18
"""Black-box tests for bzr pull."""
21
19
 
22
20
import os
23
21
import sys
24
22
 
25
 
from bzrlib.branch import Branch
26
 
from bzrlib.tests.blackbox import ExternalBase
27
 
 
28
 
class TestPull(ExternalBase):
29
 
 
30
 
    def example_branch(test):
31
 
        test.runbzr('init')
32
 
        file('hello', 'wt').write('foo')
33
 
        test.runbzr('add hello')
34
 
        test.runbzr('commit -m setup hello')
35
 
        file('goodbye', 'wt').write('baz')
36
 
        test.runbzr('add goodbye')
37
 
        test.runbzr('commit -m setup goodbye')
 
23
from bzrlib import (
 
24
    branch,
 
25
    debug,
 
26
    osutils,
 
27
    remote,
 
28
    tests,
 
29
    uncommit,
 
30
    urlutils,
 
31
    workingtree,
 
32
    )
 
33
 
 
34
from bzrlib.directory_service import directories
 
35
from bzrlib.tests import (
 
36
    fixtures,
 
37
    script,
 
38
    )
 
39
 
 
40
 
 
41
class TestPull(tests.TestCaseWithTransport):
 
42
 
 
43
    def example_branch(self, path='.'):
 
44
        tree = self.make_branch_and_tree(path)
 
45
        self.build_tree_contents([
 
46
            (osutils.pathjoin(path, 'hello'),   'foo'),
 
47
            (osutils.pathjoin(path, 'goodbye'), 'baz')])
 
48
        tree.add('hello')
 
49
        tree.commit(message='setup')
 
50
        tree.add('goodbye')
 
51
        tree.commit(message='setup')
 
52
        return tree
38
53
 
39
54
    def test_pull(self):
40
55
        """Pull changes from one branch to another."""
41
 
        os.mkdir('a')
42
 
        os.chdir('a')
43
 
 
44
 
        self.example_branch()
45
 
        self.runbzr('pull', retcode=3)
46
 
        self.runbzr('missing', retcode=3)
47
 
        self.runbzr('missing .')
48
 
        self.runbzr('missing')
49
 
        if sys.platform not in ('win32', 'cygwin'):
50
 
            # This is equivalent to doing "bzr pull ."
51
 
            # Which means that bzr creates 2 branches grabbing
52
 
            # the same location, and tries to pull.
53
 
            # However, 2 branches mean 2 locks on the same file
54
 
            # which ultimately implies a deadlock.
55
 
            # (non windows platforms allow multiple locks on the
56
 
            # same file by the same calling process)
57
 
            self.runbzr('pull')
58
 
        self.runbzr('pull /', retcode=3)
59
 
        if sys.platform not in ('win32', 'cygwin'):
60
 
            self.runbzr('pull')
61
 
 
62
 
        os.chdir('..')
63
 
        self.runbzr('branch a b')
64
 
        os.chdir('b')
65
 
        self.runbzr('pull')
66
 
        os.mkdir('subdir')
67
 
        self.runbzr('add subdir')
68
 
        self.runbzr('commit -m blah --unchanged')
69
 
        os.chdir('../a')
70
 
        a = Branch.open('.')
71
 
        b = Branch.open('../b')
72
 
        self.assertEquals(a.revision_history(), b.revision_history()[:-1])
73
 
        self.runbzr('pull ../b')
74
 
        self.assertEquals(a.revision_history(), b.revision_history())
75
 
        self.runbzr('commit -m blah2 --unchanged')
76
 
        os.chdir('../b')
77
 
        self.runbzr('commit -m blah3 --unchanged')
 
56
        a_tree = self.example_branch('a')
 
57
        base_rev = a_tree.branch.last_revision()
 
58
        self.run_bzr('pull', retcode=3, working_dir='a')
 
59
        self.run_bzr('missing', retcode=3, working_dir='a')
 
60
        self.run_bzr('missing .', working_dir='a')
 
61
        self.run_bzr('missing', working_dir='a')
 
62
        # this will work on windows because we check for the same branch
 
63
        # in pull - if it fails, it is a regression
 
64
        self.run_bzr('pull', working_dir='a')
 
65
        self.run_bzr('pull /', retcode=3, working_dir='a')
 
66
        if sys.platform not in ('win32', 'cygwin'):
 
67
            self.run_bzr('pull', working_dir='a')
 
68
 
 
69
        b_tree = a_tree.bzrdir.sprout('b').open_workingtree()
 
70
        self.run_bzr('pull', working_dir='b')
 
71
        os.mkdir('b/subdir')
 
72
        b_tree.add('subdir')
 
73
        new_rev = b_tree.commit(message='blah', allow_pointless=True)
 
74
 
 
75
        a = branch.Branch.open('a')
 
76
        b = branch.Branch.open('b')
 
77
        self.assertEqual(a.last_revision(), base_rev)
 
78
        self.assertEqual(b.last_revision(), new_rev)
 
79
 
 
80
        self.run_bzr('pull ../b', working_dir='a')
 
81
        self.assertEqual(a.last_revision(), b.last_revision())
 
82
        a_tree.commit(message='blah2', allow_pointless=True)
 
83
        b_tree.commit(message='blah3', allow_pointless=True)
78
84
        # no overwrite
79
 
        self.runbzr('pull ../a', retcode=3)
80
 
        os.chdir('..')
81
 
        self.runbzr('branch b overwriteme')
82
 
        os.chdir('overwriteme')
83
 
        self.runbzr('pull --overwrite ../a')
84
 
        overwritten = Branch.open('.')
85
 
        self.assertEqual(overwritten.revision_history(),
86
 
                         a.revision_history())
87
 
        os.chdir('../a')
88
 
        self.runbzr('merge ../b')
89
 
        self.runbzr('commit -m blah4 --unchanged')
90
 
        os.chdir('../b/subdir')
91
 
        self.runbzr('pull ../../a')
92
 
        self.assertEquals(a.revision_history()[-1], b.revision_history()[-1])
93
 
        self.runbzr('commit -m blah5 --unchanged')
94
 
        self.runbzr('commit -m blah6 --unchanged')
95
 
        os.chdir('..')
96
 
        self.runbzr('pull ../a')
97
 
        os.chdir('../a')
98
 
        self.runbzr('commit -m blah7 --unchanged')
99
 
        self.runbzr('merge ../b')
100
 
        self.runbzr('commit -m blah8 --unchanged')
101
 
        self.runbzr('pull ../b')
102
 
        self.runbzr('pull ../b')
 
85
        self.run_bzr('pull ../a', retcode=3, working_dir='b')
 
86
        b_tree.bzrdir.sprout('overwriteme')
 
87
        self.run_bzr('pull --overwrite ../a', working_dir='overwriteme')
 
88
        overwritten = branch.Branch.open('overwriteme')
 
89
        self.assertEqual(overwritten.last_revision(),
 
90
                         a.last_revision())
 
91
        a_tree.merge_from_branch(b_tree.branch)
 
92
        a_tree.commit(message="blah4", allow_pointless=True)
 
93
 
 
94
        self.run_bzr('pull ../../a', working_dir='b/subdir')
 
95
        self.assertEqual(a.last_revision(), b.last_revision())
 
96
        sub_tree = workingtree.WorkingTree.open_containing('b/subdir')[0]
 
97
        sub_tree.commit(message="blah5", allow_pointless=True)
 
98
        sub_tree.commit(message="blah6", allow_pointless=True)
 
99
        self.run_bzr('pull ../a', working_dir='b')
 
100
        a_tree.commit(message="blah7", allow_pointless=True)
 
101
        a_tree.merge_from_branch(b_tree.branch)
 
102
        a_tree.commit(message="blah8", allow_pointless=True)
 
103
        self.run_bzr('pull ../b', working_dir='a')
 
104
        self.run_bzr('pull ../b', working_dir='a')
 
105
 
 
106
    def test_pull_dash_d(self):
 
107
        self.example_branch('a')
 
108
        self.make_branch_and_tree('b')
 
109
        self.make_branch_and_tree('c')
 
110
        # pull into that branch
 
111
        self.run_bzr('pull -d b a')
 
112
        # pull into a branch specified by a url
 
113
        c_url = urlutils.local_path_to_url('c')
 
114
        self.assertStartsWith(c_url, 'file://')
 
115
        self.run_bzr(['pull', '-d', c_url, 'a'])
103
116
 
104
117
    def test_pull_revision(self):
105
118
        """Pull some changes from one branch to another."""
106
 
        os.mkdir('a')
107
 
        os.chdir('a')
108
 
 
109
 
        self.example_branch()
110
 
        file('hello2', 'wt').write('foo')
111
 
        self.runbzr('add hello2')
112
 
        self.runbzr('commit -m setup hello2')
113
 
        file('goodbye2', 'wt').write('baz')
114
 
        self.runbzr('add goodbye2')
115
 
        self.runbzr('commit -m setup goodbye2')
116
 
 
117
 
        os.chdir('..')
118
 
        self.runbzr('branch -r 1 a b')
119
 
        os.chdir('b')
120
 
        self.runbzr('pull -r 2')
121
 
        a = Branch.open('../a')
122
 
        b = Branch.open('.')
123
 
        self.assertEquals(a.revno(),4)
124
 
        self.assertEquals(b.revno(),2)
125
 
        self.runbzr('pull -r 3')
126
 
        self.assertEquals(b.revno(),3)
127
 
        self.runbzr('pull -r 4')
128
 
        self.assertEquals(a.revision_history(), b.revision_history())
129
 
 
 
119
        a_tree = self.example_branch('a')
 
120
        self.build_tree_contents([
 
121
            ('a/hello2',   'foo'),
 
122
            ('a/goodbye2', 'baz')])
 
123
        a_tree.add('hello2')
 
124
        a_tree.commit(message="setup")
 
125
        a_tree.add('goodbye2')
 
126
        a_tree.commit(message="setup")
 
127
 
 
128
        b_tree = a_tree.bzrdir.sprout('b',
 
129
                   revision_id=a_tree.branch.get_rev_id(1)).open_workingtree()
 
130
        self.run_bzr('pull -r 2', working_dir='b')
 
131
        a = branch.Branch.open('a')
 
132
        b = branch.Branch.open('b')
 
133
        self.assertEqual(a.revno(),4)
 
134
        self.assertEqual(b.revno(),2)
 
135
        self.run_bzr('pull -r 3', working_dir='b')
 
136
        self.assertEqual(b.revno(),3)
 
137
        self.run_bzr('pull -r 4', working_dir='b')
 
138
        self.assertEqual(a.last_revision(), b.last_revision())
 
139
 
 
140
    def test_pull_tags(self):
 
141
        """Tags are updated by pull, and revisions named in those tags are
 
142
        fetched.
 
143
        """
 
144
        # Make a source, sprout a target off it
 
145
        builder = self.make_branch_builder('source')
 
146
        source = fixtures.build_branch_with_non_ancestral_rev(builder)
 
147
        source.get_config_stack().set('branch.fetch_tags', True)
 
148
        target_bzrdir = source.bzrdir.sprout('target')
 
149
        source.tags.set_tag('tag-a', 'rev-2')
 
150
        # Pull from source
 
151
        self.run_bzr('pull -d target source')
 
152
        target = target_bzrdir.open_branch()
 
153
        # The tag is present, and so is its revision.
 
154
        self.assertEqual('rev-2', target.tags.lookup_tag('tag-a'))
 
155
        target.repository.get_revision('rev-2')
130
156
 
131
157
    def test_overwrite_uptodate(self):
132
158
        # Make sure pull --overwrite overwrites
133
159
        # even if the target branch has merged
134
160
        # everything already.
135
 
        bzr = self.run_bzr
136
 
 
137
 
        def get_rh(expected_len):
138
 
            rh = self.capture('revision-history')
139
 
            # Make sure we don't have trailing empty revisions
140
 
            rh = rh.strip().split('\n')
141
 
            self.assertEqual(len(rh), expected_len)
142
 
            return rh
143
 
 
144
 
        os.mkdir('a')
145
 
        os.chdir('a')
146
 
        bzr('init')
147
 
        open('foo', 'wb').write('original\n')
148
 
        bzr('add', 'foo')
149
 
        bzr('commit', '-m', 'initial commit')
150
 
 
151
 
        os.chdir('..')
152
 
        bzr('branch', 'a', 'b')
153
 
 
154
 
        os.chdir('a')
155
 
        open('foo', 'wb').write('changed\n')
156
 
        bzr('commit', '-m', 'later change')
157
 
 
158
 
        open('foo', 'wb').write('another\n')
159
 
        bzr('commit', '-m', 'a third change')
160
 
 
161
 
        rev_history_a = get_rh(3)
162
 
 
163
 
        os.chdir('../b')
164
 
        bzr('merge', '../a')
165
 
        bzr('commit', '-m', 'merge')
166
 
 
167
 
        rev_history_b = get_rh(2)
168
 
 
169
 
        bzr('pull', '--overwrite', '../a')
170
 
        rev_history_b = get_rh(3)
171
 
 
172
 
        self.assertEqual(rev_history_b, rev_history_a)
 
161
        a_tree = self.make_branch_and_tree('a')
 
162
        self.build_tree_contents([('a/foo', 'original\n')])
 
163
        a_tree.add('foo')
 
164
        a_tree.commit(message='initial commit')
 
165
 
 
166
        b_tree = a_tree.bzrdir.sprout('b').open_workingtree()
 
167
 
 
168
        self.build_tree_contents([('a/foo', 'changed\n')])
 
169
        a_tree.commit(message='later change')
 
170
 
 
171
        self.build_tree_contents([('a/foo', 'a third change')])
 
172
        a_tree.commit(message='a third change')
 
173
 
 
174
        self.assertEqual(a_tree.branch.last_revision_info()[0], 3)
 
175
 
 
176
        b_tree.merge_from_branch(a_tree.branch)
 
177
        b_tree.commit(message='merge')
 
178
 
 
179
        self.assertEqual(b_tree.branch.last_revision_info()[0], 2)
 
180
 
 
181
        self.run_bzr('pull --overwrite ../a', working_dir='b')
 
182
        (last_revinfo_b) = b_tree.branch.last_revision_info()
 
183
        self.assertEqual(last_revinfo_b[0], 3)
 
184
        self.assertEqual(last_revinfo_b[1], a_tree.branch.last_revision())
173
185
 
174
186
    def test_overwrite_children(self):
175
187
        # Make sure pull --overwrite sets the revision-history
176
188
        # to be identical to the pull source, even if we have convergence
177
 
        bzr = self.run_bzr
178
 
 
179
 
        def get_rh(expected_len):
180
 
            rh = self.capture('revision-history')
181
 
            # Make sure we don't have trailing empty revisions
182
 
            rh = rh.strip().split('\n')
183
 
            self.assertEqual(len(rh), expected_len)
184
 
            return rh
185
 
 
186
 
        os.mkdir('a')
187
 
        os.chdir('a')
188
 
        bzr('init')
189
 
        open('foo', 'wb').write('original\n')
190
 
        bzr('add', 'foo')
191
 
        bzr('commit', '-m', 'initial commit')
192
 
 
193
 
        os.chdir('..')
194
 
        bzr('branch', 'a', 'b')
195
 
 
196
 
        os.chdir('a')
197
 
        open('foo', 'wb').write('changed\n')
198
 
        bzr('commit', '-m', 'later change')
199
 
 
200
 
        open('foo', 'wb').write('another\n')
201
 
        bzr('commit', '-m', 'a third change')
202
 
 
203
 
        rev_history_a = get_rh(3)
204
 
 
205
 
        os.chdir('../b')
206
 
        bzr('merge', '../a')
207
 
        bzr('commit', '-m', 'merge')
208
 
 
209
 
        rev_history_b = get_rh(2)
210
 
 
211
 
        os.chdir('../a')
212
 
        open('foo', 'wb').write('a fourth change\n')
213
 
        bzr('commit', '-m', 'a fourth change')
214
 
 
215
 
        rev_history_a = get_rh(4)
 
189
        a_tree = self.make_branch_and_tree('a')
 
190
        self.build_tree_contents([('a/foo', 'original\n')])
 
191
        a_tree.add('foo')
 
192
        a_tree.commit(message='initial commit')
 
193
 
 
194
        b_tree = a_tree.bzrdir.sprout('b').open_workingtree()
 
195
 
 
196
        self.build_tree_contents([('a/foo', 'changed\n')])
 
197
        a_tree.commit(message='later change')
 
198
 
 
199
        self.build_tree_contents([('a/foo', 'a third change')])
 
200
        a_tree.commit(message='a third change')
 
201
 
 
202
        self.assertEqual(a_tree.branch.last_revision_info()[0], 3)
 
203
 
 
204
        b_tree.merge_from_branch(a_tree.branch)
 
205
        b_tree.commit(message='merge')
 
206
 
 
207
        self.assertEqual(b_tree.branch.last_revision_info()[0], 2)
 
208
 
 
209
        self.build_tree_contents([('a/foo', 'a fourth change\n')])
 
210
        a_tree.commit(message='a fourth change')
 
211
 
 
212
        rev_info_a = a_tree.branch.last_revision_info()
 
213
        self.assertEqual(rev_info_a[0], 4)
216
214
 
217
215
        # With convergence, we could just pull over the
218
216
        # new change, but with --overwrite, we want to switch our history
219
 
        os.chdir('../b')
220
 
        bzr('pull', '--overwrite', '../a')
221
 
        rev_history_b = get_rh(4)
222
 
 
223
 
        self.assertEqual(rev_history_b, rev_history_a)
224
 
 
225
 
 
 
217
        self.run_bzr('pull --overwrite ../a', working_dir='b')
 
218
        rev_info_b = b_tree.branch.last_revision_info()
 
219
        self.assertEqual(rev_info_b[0], 4)
 
220
        self.assertEqual(rev_info_b, rev_info_a)
 
221
 
 
222
    def test_pull_remember(self):
 
223
        """Pull changes from one branch to another and test parent location."""
 
224
        t = self.get_transport()
 
225
        tree_a = self.make_branch_and_tree('branch_a')
 
226
        branch_a = tree_a.branch
 
227
        self.build_tree(['branch_a/a'])
 
228
        tree_a.add('a')
 
229
        tree_a.commit('commit a')
 
230
        tree_b = branch_a.bzrdir.sprout('branch_b').open_workingtree()
 
231
        branch_b = tree_b.branch
 
232
        tree_c = branch_a.bzrdir.sprout('branch_c').open_workingtree()
 
233
        branch_c = tree_c.branch
 
234
        self.build_tree(['branch_a/b'])
 
235
        tree_a.add('b')
 
236
        tree_a.commit('commit b')
 
237
        # reset parent
 
238
        parent = branch_b.get_parent()
 
239
        branch_b = branch.Branch.open('branch_b')
 
240
        branch_b.set_parent(None)
 
241
        self.assertEqual(None, branch_b.get_parent())
 
242
        # test pull for failure without parent set
 
243
        out = self.run_bzr('pull', retcode=3, working_dir='branch_b')
 
244
        self.assertEqual(out,
 
245
                ('','bzr: ERROR: No pull location known or specified.\n'))
 
246
        # test implicit --remember when no parent set, this pull conflicts
 
247
        self.build_tree(['branch_b/d'])
 
248
        tree_b.add('d')
 
249
        tree_b.commit('commit d')
 
250
        out = self.run_bzr('pull ../branch_a', retcode=3,
 
251
                           working_dir='branch_b')
 
252
        self.assertEqual(out,
 
253
                ('','bzr: ERROR: These branches have diverged.'
 
254
                    ' Use the missing command to see how.\n'
 
255
                    'Use the merge command to reconcile them.\n'))
 
256
        tree_b = tree_b.bzrdir.open_workingtree()
 
257
        branch_b = tree_b.branch
 
258
        self.assertEqual(parent, branch_b.get_parent())
 
259
        # test implicit --remember after resolving previous failure
 
260
        uncommit.uncommit(branch=branch_b, tree=tree_b)
 
261
        t.delete('branch_b/d')
 
262
        self.run_bzr('pull', working_dir='branch_b')
 
263
        # Refresh the branch object as 'pull' modified it
 
264
        branch_b = branch_b.bzrdir.open_branch()
 
265
        self.assertEqual(branch_b.get_parent(), parent)
 
266
        # test explicit --remember
 
267
        self.run_bzr('pull ../branch_c --remember', working_dir='branch_b')
 
268
        # Refresh the branch object as 'pull' modified it
 
269
        branch_b = branch_b.bzrdir.open_branch()
 
270
        self.assertEqual(branch_c.bzrdir.root_transport.base,
 
271
                         branch_b.get_parent())
 
272
 
 
273
    def test_pull_bundle(self):
 
274
        from bzrlib.testament import Testament
 
275
        # Build up 2 trees and prepare for a pull
 
276
        tree_a = self.make_branch_and_tree('branch_a')
 
277
        with open('branch_a/a', 'wb') as f:
 
278
            f.write('hello')
 
279
        tree_a.add('a')
 
280
        tree_a.commit('message')
 
281
 
 
282
        tree_b = tree_a.bzrdir.sprout('branch_b').open_workingtree()
 
283
 
 
284
        # Make a change to 'a' that 'b' can pull
 
285
        with open('branch_a/a', 'wb') as f:
 
286
            f.write('hey there')
 
287
        tree_a.commit('message')
 
288
 
 
289
        # Create the bundle for 'b' to pull
 
290
        self.run_bzr('bundle ../branch_b -o ../bundle', working_dir='branch_a')
 
291
 
 
292
        out, err = self.run_bzr('pull ../bundle', working_dir='branch_b')
 
293
        self.assertEqual(out,
 
294
                         'Now on revision 2.\n')
 
295
        self.assertEqual(err,
 
296
                ' M  a\nAll changes applied successfully.\n')
 
297
 
 
298
        self.assertEqualDiff(tree_a.branch.last_revision(),
 
299
                             tree_b.branch.last_revision())
 
300
 
 
301
        testament_a = Testament.from_revision(tree_a.branch.repository,
 
302
                                              tree_a.get_parent_ids()[0])
 
303
        testament_b = Testament.from_revision(tree_b.branch.repository,
 
304
                                              tree_b.get_parent_ids()[0])
 
305
        self.assertEqualDiff(testament_a.as_text(),
 
306
                             testament_b.as_text())
 
307
 
 
308
        # it is legal to attempt to pull an already-merged bundle
 
309
        out, err = self.run_bzr('pull ../bundle', working_dir='branch_b')
 
310
        self.assertEqual(err, '')
 
311
        self.assertEqual(out, 'No revisions or tags to pull.\n')
 
312
 
 
313
    def test_pull_verbose_no_files(self):
 
314
        """Pull --verbose should not list modified files"""
 
315
        tree_a = self.make_branch_and_tree('tree_a')
 
316
        self.build_tree(['tree_a/foo'])
 
317
        tree_a.add('foo')
 
318
        tree_a.commit('bar')
 
319
        tree_b = self.make_branch_and_tree('tree_b')
 
320
        out = self.run_bzr('pull --verbose -d tree_b tree_a')[0]
 
321
        self.assertContainsRe(out, 'bar')
 
322
        self.assertNotContainsRe(out, 'added:')
 
323
        self.assertNotContainsRe(out, 'foo')
 
324
 
 
325
    def test_pull_quiet(self):
 
326
        """Check that bzr pull --quiet does not print anything"""
 
327
        tree_a = self.make_branch_and_tree('tree_a')
 
328
        self.build_tree(['tree_a/foo'])
 
329
        tree_a.add('foo')
 
330
        revision_id = tree_a.commit('bar')
 
331
        tree_b = tree_a.bzrdir.sprout('tree_b').open_workingtree()
 
332
        out, err = self.run_bzr('pull --quiet -d tree_b')
 
333
        self.assertEqual(out, '')
 
334
        self.assertEqual(err, '')
 
335
        self.assertEqual(tree_b.last_revision(), revision_id)
 
336
        self.build_tree(['tree_a/moo'])
 
337
        tree_a.add('moo')
 
338
        revision_id = tree_a.commit('quack')
 
339
        out, err = self.run_bzr('pull --quiet -d tree_b')
 
340
        self.assertEqual(out, '')
 
341
        self.assertEqual(err, '')
 
342
        self.assertEqual(tree_b.last_revision(), revision_id)
 
343
 
 
344
    def test_pull_from_directory_service(self):
 
345
        source = self.make_branch_and_tree('source')
 
346
        source.commit('commit 1')
 
347
        target = source.bzrdir.sprout('target').open_workingtree()
 
348
        source_last = source.commit('commit 2')
 
349
        class FooService(object):
 
350
            """A directory service that always returns source"""
 
351
 
 
352
            def look_up(self, name, url):
 
353
                return 'source'
 
354
        directories.register('foo:', FooService, 'Testing directory service')
 
355
        self.addCleanup(directories.remove, 'foo:')
 
356
        self.run_bzr('pull foo:bar -d target')
 
357
        self.assertEqual(source_last, target.last_revision())
 
358
 
 
359
    def test_pull_verbose_defaults_to_long(self):
 
360
        tree = self.example_branch('source')
 
361
        target = self.make_branch_and_tree('target')
 
362
        out = self.run_bzr('pull -v source -d target')[0]
 
363
        self.assertContainsRe(out,
 
364
                              r'revno: 1\ncommitter: .*\nbranch nick: source')
 
365
        self.assertNotContainsRe(out, r'\n {4}1 .*\n {6}setup\n')
 
366
 
 
367
    def test_pull_verbose_uses_default_log(self):
 
368
        tree = self.example_branch('source')
 
369
        target = self.make_branch_and_tree('target')
 
370
        target.branch.get_config_stack().set('log_format', 'short')
 
371
        out = self.run_bzr('pull -v source -d target')[0]
 
372
        self.assertContainsRe(out, r'\n {4}1 .*\n {6}setup\n')
 
373
        self.assertNotContainsRe(
 
374
            out, r'revno: 1\ncommitter: .*\nbranch nick: source')
 
375
 
 
376
    def test_pull_smart_bound_branch(self):
 
377
        self.setup_smart_server_with_call_log()
 
378
        parent = self.make_branch_and_tree('parent')
 
379
        parent.commit(message='first commit')
 
380
        child = parent.bzrdir.sprout('child').open_workingtree()
 
381
        child.commit(message='second commit')
 
382
        checkout = parent.branch.create_checkout('checkout')
 
383
        self.run_bzr(['pull', self.get_url('child')], working_dir='checkout')
 
384
 
 
385
    def test_pull_smart_stacked_streaming_acceptance(self):
 
386
        """'bzr pull -r 123' works on stacked, smart branches, even when the
 
387
        revision specified by the revno is only present in the fallback
 
388
        repository.
 
389
 
 
390
        See <https://launchpad.net/bugs/380314>
 
391
        """
 
392
        self.setup_smart_server_with_call_log()
 
393
        # Make a stacked-on branch with two commits so that the
 
394
        # revision-history can't be determined just by looking at the parent
 
395
        # field in the revision in the stacked repo.
 
396
        parent = self.make_branch_and_tree('parent', format='1.9')
 
397
        parent.commit(message='first commit')
 
398
        parent.commit(message='second commit')
 
399
        local = parent.bzrdir.sprout('local').open_workingtree()
 
400
        local.commit(message='local commit')
 
401
        local.branch.create_clone_on_transport(
 
402
            self.get_transport('stacked'), stacked_on=self.get_url('parent'))
 
403
        empty = self.make_branch_and_tree('empty', format='1.9')
 
404
        self.reset_smart_call_log()
 
405
        self.run_bzr(['pull', '-r', '1', self.get_url('stacked')],
 
406
            working_dir='empty')
 
407
        # This figure represent the amount of work to perform this use case. It
 
408
        # is entirely ok to reduce this number if a test fails due to rpc_count
 
409
        # being too low. If rpc_count increases, more network roundtrips have
 
410
        # become necessary for this use case. Please do not adjust this number
 
411
        # upwards without agreement from bzr's network support maintainers.
 
412
        self.assertLength(19, self.hpss_calls)
 
413
        self.assertLength(1, self.hpss_connections)
 
414
        remote = branch.Branch.open('stacked')
 
415
        self.assertEndsWith(remote.get_stacked_on_url(), '/parent')
 
416
 
 
417
    def test_pull_cross_format_warning(self):
 
418
        """You get a warning for probably slow cross-format pulls.
 
419
        """
 
420
        # this is assumed to be going through InterDifferingSerializer
 
421
        from_tree = self.make_branch_and_tree('from', format='2a')
 
422
        to_tree = self.make_branch_and_tree('to', format='1.14-rich-root')
 
423
        from_tree.commit(message='first commit')
 
424
        out, err = self.run_bzr(['pull', '-d', 'to', 'from'])
 
425
        self.assertContainsRe(err,
 
426
            "(?m)Doing on-the-fly conversion")
 
427
 
 
428
    def test_pull_cross_format_warning_no_IDS(self):
 
429
        """You get a warning for probably slow cross-format pulls.
 
430
        """
 
431
        # this simulates what would happen across the network, where
 
432
        # interdifferingserializer is not active
 
433
 
 
434
        debug.debug_flags.add('IDS_never')
 
435
        # TestCase take care of restoring them
 
436
 
 
437
        from_tree = self.make_branch_and_tree('from', format='2a')
 
438
        to_tree = self.make_branch_and_tree('to', format='1.14-rich-root')
 
439
        from_tree.commit(message='first commit')
 
440
        out, err = self.run_bzr(['pull', '-d', 'to', 'from'])
 
441
        self.assertContainsRe(err,
 
442
            "(?m)Doing on-the-fly conversion")
 
443
 
 
444
    def test_pull_cross_format_from_network(self):
 
445
        self.setup_smart_server_with_call_log()
 
446
        from_tree = self.make_branch_and_tree('from', format='2a')
 
447
        to_tree = self.make_branch_and_tree('to', format='1.14-rich-root')
 
448
        self.assertIsInstance(from_tree.branch, remote.RemoteBranch)
 
449
        from_tree.commit(message='first commit')
 
450
        out, err = self.run_bzr(['pull', '-d', 'to',
 
451
            from_tree.branch.bzrdir.root_transport.base])
 
452
        self.assertContainsRe(err,
 
453
            "(?m)Doing on-the-fly conversion")
 
454
 
 
455
    def test_pull_to_experimental_format_warning(self):
 
456
        """You get a warning for pulling into experimental formats.
 
457
        """
 
458
        from_tree = self.make_branch_and_tree('from', format='development-subtree')
 
459
        to_tree = self.make_branch_and_tree('to', format='development-subtree')
 
460
        from_tree.commit(message='first commit')
 
461
        out, err = self.run_bzr(['pull', '-d', 'to', 'from'])
 
462
        self.assertContainsRe(err,
 
463
            "(?m)Fetching into experimental format")
 
464
 
 
465
    def test_pull_cross_to_experimental_format_warning(self):
 
466
        """You get a warning for pulling into experimental formats.
 
467
        """
 
468
        from_tree = self.make_branch_and_tree('from', format='2a')
 
469
        to_tree = self.make_branch_and_tree('to', format='development-subtree')
 
470
        from_tree.commit(message='first commit')
 
471
        out, err = self.run_bzr(['pull', '-d', 'to', 'from'])
 
472
        self.assertContainsRe(err,
 
473
            "(?m)Fetching into experimental format")
 
474
 
 
475
    def test_pull_show_base(self):
 
476
        """bzr pull supports --show-base
 
477
 
 
478
        see https://bugs.launchpad.net/bzr/+bug/202374"""
 
479
        # create two trees with conflicts, setup conflict, check that
 
480
        # conflicted file looks correct
 
481
        a_tree = self.example_branch('a')
 
482
        b_tree = a_tree.bzrdir.sprout('b').open_workingtree()
 
483
 
 
484
        with open(osutils.pathjoin('a', 'hello'),'wt') as f:
 
485
            f.write('fee')
 
486
        a_tree.commit('fee')
 
487
 
 
488
        with open(osutils.pathjoin('b', 'hello'),'wt') as f:
 
489
            f.write('fie')
 
490
 
 
491
        out,err=self.run_bzr(['pull','-d','b','a','--show-base'])
 
492
 
 
493
        # check for message here
 
494
        self.assertEqual(
 
495
            err,
 
496
            ' M  hello\nText conflict in hello\n1 conflicts encountered.\n')
 
497
 
 
498
        self.assertEqualDiff('<<<<<<< TREE\n'
 
499
                             'fie||||||| BASE-REVISION\n'
 
500
                             'foo=======\n'
 
501
                             'fee>>>>>>> MERGE-SOURCE\n',
 
502
                             open(osutils.pathjoin('b', 'hello')).read())
 
503
 
 
504
    def test_pull_show_base_working_tree_only(self):
 
505
        """--show-base only allowed if there's a working tree
 
506
 
 
507
        see https://bugs.launchpad.net/bzr/+bug/202374"""
 
508
        # create a branch, see that --show-base fails
 
509
        self.make_branch('from')
 
510
        self.make_branch('to')
 
511
        out=self.run_bzr(['pull','-d','to','from','--show-base'],retcode=3)
 
512
        self.assertEqual(
 
513
            out, ('','bzr: ERROR: Need working tree for --show-base.\n'))
 
514
 
 
515
    def test_pull_tag_conflicts(self):
 
516
        """pulling tags with conflicts will change the exit code"""
 
517
        # create a branch, see that --show-base fails
 
518
        from_tree = self.make_branch_and_tree('from')
 
519
        from_tree.branch.tags.set_tag("mytag", "somerevid")
 
520
        to_tree = self.make_branch_and_tree('to')
 
521
        to_tree.branch.tags.set_tag("mytag", "anotherrevid")
 
522
        out = self.run_bzr(['pull','-d','to','from'],retcode=1)
 
523
        self.assertEqual(out,
 
524
            ('No revisions to pull.\nConflicting tags:\n    mytag\n', ''))
 
525
 
 
526
    def test_pull_tag_notification(self):
 
527
        """pulling tags with conflicts will change the exit code"""
 
528
        # create a branch, see that --show-base fails
 
529
        from_tree = self.make_branch_and_tree('from')
 
530
        from_tree.branch.tags.set_tag("mytag", "somerevid")
 
531
        to_tree = self.make_branch_and_tree('to')
 
532
        out = self.run_bzr(['pull', '-d', 'to', 'from'])
 
533
        self.assertEqual(out,
 
534
            ('1 tag(s) updated.\n', ''))
 
535
 
 
536
    def test_overwrite_tags(self):
 
537
        """--overwrite-tags only overwrites tags, not revisions."""
 
538
        from_tree = self.make_branch_and_tree('from')
 
539
        from_tree.branch.tags.set_tag("mytag", "somerevid")
 
540
        to_tree = self.make_branch_and_tree('to')
 
541
        to_tree.branch.tags.set_tag("mytag", "anotherrevid")
 
542
        revid1 = to_tree.commit('my commit')
 
543
        out = self.run_bzr(['pull', '-d', 'to', 'from'], retcode=1)
 
544
        self.assertEquals(out,
 
545
            ('No revisions to pull.\nConflicting tags:\n    mytag\n', ''))
 
546
        out = self.run_bzr(['pull', '-d', 'to', '--overwrite-tags', 'from'])
 
547
        self.assertEquals(out, ('1 tag(s) updated.\n', ''))
 
548
 
 
549
        self.assertEquals(to_tree.branch.tags.lookup_tag('mytag'),
 
550
                          'somerevid')
 
551
        self.assertEquals(to_tree.branch.last_revision(), revid1)
 
552
 
 
553
    def test_pull_tag_overwrite(self):
 
554
        """pulling tags with --overwrite only reports changed tags."""
 
555
        # create a branch, see that --show-base fails
 
556
        from_tree = self.make_branch_and_tree('from')
 
557
        from_tree.branch.tags.set_tag("mytag", "somerevid")
 
558
        to_tree = self.make_branch_and_tree('to')
 
559
        to_tree.branch.tags.set_tag("mytag", "somerevid")
 
560
        out = self.run_bzr(['pull', '--overwrite', '-d', 'to', 'from'])
 
561
        self.assertEqual(out,
 
562
            ('No revisions or tags to pull.\n', ''))
 
563
 
 
564
 
 
565
class TestPullOutput(script.TestCaseWithTransportAndScript):
 
566
 
 
567
    def test_pull_log_format(self):
 
568
        self.run_script("""
 
569
            $ bzr init trunk
 
570
            Created a standalone tree (format: 2a)
 
571
            $ cd trunk
 
572
            $ echo foo > file
 
573
            $ bzr add
 
574
            adding file
 
575
            $ bzr commit -m 'we need some foo'
 
576
            2>Committing to:...trunk/
 
577
            2>added file
 
578
            2>Committed revision 1.
 
579
            $ cd ..
 
580
            $ bzr init feature
 
581
            Created a standalone tree (format: 2a)
 
582
            $ cd feature
 
583
            $ bzr pull -v ../trunk -Olog_format=line
 
584
            Now on revision 1.
 
585
            Added Revisions:
 
586
            1: jrandom@example.com ...we need some foo
 
587
            2>+N  file
 
588
            2>All changes applied successfully.
 
589
            """)