~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

(vila) Fix test failures blocking package builds. (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'])
 
116
 
 
117
    def test_pull_revision(self):
 
118
        """Pull some changes from one branch to another."""
 
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')
103
156
 
104
157
    def test_overwrite_uptodate(self):
105
158
        # Make sure pull --overwrite overwrites
106
159
        # even if the target branch has merged
107
160
        # everything already.
108
 
        bzr = self.run_bzr
109
 
 
110
 
        def get_rh(expected_len):
111
 
            rh = self.capture('revision-history')
112
 
            # Make sure we don't have trailing empty revisions
113
 
            rh = rh.strip().split('\n')
114
 
            self.assertEqual(len(rh), expected_len)
115
 
            return rh
116
 
 
117
 
        os.mkdir('a')
118
 
        os.chdir('a')
119
 
        bzr('init')
120
 
        open('foo', 'wb').write('original\n')
121
 
        bzr('add', 'foo')
122
 
        bzr('commit', '-m', 'initial commit')
123
 
 
124
 
        os.chdir('..')
125
 
        bzr('branch', 'a', 'b')
126
 
 
127
 
        os.chdir('a')
128
 
        open('foo', 'wb').write('changed\n')
129
 
        bzr('commit', '-m', 'later change')
130
 
 
131
 
        open('foo', 'wb').write('another\n')
132
 
        bzr('commit', '-m', 'a third change')
133
 
 
134
 
        rev_history_a = get_rh(3)
135
 
 
136
 
        os.chdir('../b')
137
 
        bzr('merge', '../a')
138
 
        bzr('commit', '-m', 'merge')
139
 
 
140
 
        rev_history_b = get_rh(2)
141
 
 
142
 
        bzr('pull', '--overwrite', '../a')
143
 
        rev_history_b = get_rh(3)
144
 
 
145
 
        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())
146
185
 
147
186
    def test_overwrite_children(self):
148
187
        # Make sure pull --overwrite sets the revision-history
149
188
        # to be identical to the pull source, even if we have convergence
150
 
        bzr = self.run_bzr
151
 
 
152
 
        def get_rh(expected_len):
153
 
            rh = self.capture('revision-history')
154
 
            # Make sure we don't have trailing empty revisions
155
 
            rh = rh.strip().split('\n')
156
 
            self.assertEqual(len(rh), expected_len)
157
 
            return rh
158
 
 
159
 
        os.mkdir('a')
160
 
        os.chdir('a')
161
 
        bzr('init')
162
 
        open('foo', 'wb').write('original\n')
163
 
        bzr('add', 'foo')
164
 
        bzr('commit', '-m', 'initial commit')
165
 
 
166
 
        os.chdir('..')
167
 
        bzr('branch', 'a', 'b')
168
 
 
169
 
        os.chdir('a')
170
 
        open('foo', 'wb').write('changed\n')
171
 
        bzr('commit', '-m', 'later change')
172
 
 
173
 
        open('foo', 'wb').write('another\n')
174
 
        bzr('commit', '-m', 'a third change')
175
 
 
176
 
        rev_history_a = get_rh(3)
177
 
 
178
 
        os.chdir('../b')
179
 
        bzr('merge', '../a')
180
 
        bzr('commit', '-m', 'merge')
181
 
 
182
 
        rev_history_b = get_rh(2)
183
 
 
184
 
        os.chdir('../a')
185
 
        open('foo', 'wb').write('a fourth change\n')
186
 
        bzr('commit', '-m', 'a fourth change')
187
 
 
188
 
        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)
189
214
 
190
215
        # With convergence, we could just pull over the
191
216
        # new change, but with --overwrite, we want to switch our history
192
 
        os.chdir('../b')
193
 
        bzr('pull', '--overwrite', '../a')
194
 
        rev_history_b = get_rh(4)
195
 
 
196
 
        self.assertEqual(rev_history_b, rev_history_a)
197
 
 
198
 
 
 
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_warns_about_show_base_when_no_working_tree(self):
 
505
        """--show-base is useless if there's no working tree
 
506
 
 
507
        see https://bugs.launchpad.net/bzr/+bug/1022160"""
 
508
        self.make_branch('from')
 
509
        self.make_branch('to')
 
510
        out = self.run_bzr(['pull','-d','to','from','--show-base'])
 
511
        self.assertEqual(out, ('No revisions or tags to pull.\n',
 
512
                               'No working tree, ignoring --show-base\n'))
 
513
 
 
514
    def test_pull_tag_conflicts(self):
 
515
        """pulling tags with conflicts will change the exit code"""
 
516
        # create a branch, see that --show-base fails
 
517
        from_tree = self.make_branch_and_tree('from')
 
518
        from_tree.branch.tags.set_tag("mytag", "somerevid")
 
519
        to_tree = self.make_branch_and_tree('to')
 
520
        to_tree.branch.tags.set_tag("mytag", "anotherrevid")
 
521
        out = self.run_bzr(['pull','-d','to','from'],retcode=1)
 
522
        self.assertEqual(out,
 
523
            ('No revisions to pull.\nConflicting tags:\n    mytag\n', ''))
 
524
 
 
525
    def test_pull_tag_notification(self):
 
526
        """pulling tags with conflicts will change the exit code"""
 
527
        # create a branch, see that --show-base fails
 
528
        from_tree = self.make_branch_and_tree('from')
 
529
        from_tree.branch.tags.set_tag("mytag", "somerevid")
 
530
        to_tree = self.make_branch_and_tree('to')
 
531
        out = self.run_bzr(['pull', '-d', 'to', 'from'])
 
532
        self.assertEqual(out,
 
533
            ('1 tag(s) updated.\n', ''))
 
534
 
 
535
    def test_overwrite_tags(self):
 
536
        """--overwrite-tags only overwrites tags, not revisions."""
 
537
        from_tree = self.make_branch_and_tree('from')
 
538
        from_tree.branch.tags.set_tag("mytag", "somerevid")
 
539
        to_tree = self.make_branch_and_tree('to')
 
540
        to_tree.branch.tags.set_tag("mytag", "anotherrevid")
 
541
        revid1 = to_tree.commit('my commit')
 
542
        out = self.run_bzr(['pull', '-d', 'to', 'from'], retcode=1)
 
543
        self.assertEquals(out,
 
544
            ('No revisions to pull.\nConflicting tags:\n    mytag\n', ''))
 
545
        out = self.run_bzr(['pull', '-d', 'to', '--overwrite-tags', 'from'])
 
546
        self.assertEquals(out, ('1 tag(s) updated.\n', ''))
 
547
 
 
548
        self.assertEquals(to_tree.branch.tags.lookup_tag('mytag'),
 
549
                          'somerevid')
 
550
        self.assertEquals(to_tree.branch.last_revision(), revid1)
 
551
 
 
552
    def test_pull_tag_overwrite(self):
 
553
        """pulling tags with --overwrite only reports changed tags."""
 
554
        # create a branch, see that --show-base fails
 
555
        from_tree = self.make_branch_and_tree('from')
 
556
        from_tree.branch.tags.set_tag("mytag", "somerevid")
 
557
        to_tree = self.make_branch_and_tree('to')
 
558
        to_tree.branch.tags.set_tag("mytag", "somerevid")
 
559
        out = self.run_bzr(['pull', '--overwrite', '-d', 'to', 'from'])
 
560
        self.assertEqual(out,
 
561
            ('No revisions or tags to pull.\n', ''))
 
562
 
 
563
 
 
564
class TestPullOutput(script.TestCaseWithTransportAndScript):
 
565
 
 
566
    def test_pull_log_format(self):
 
567
        self.run_script("""
 
568
            $ bzr init trunk
 
569
            Created a standalone tree (format: 2a)
 
570
            $ cd trunk
 
571
            $ echo foo > file
 
572
            $ bzr add
 
573
            adding file
 
574
            $ bzr commit -m 'we need some foo'
 
575
            2>Committing to:...trunk/
 
576
            2>added file
 
577
            2>Committed revision 1.
 
578
            $ cd ..
 
579
            $ bzr init feature
 
580
            Created a standalone tree (format: 2a)
 
581
            $ cd feature
 
582
            $ bzr pull -v ../trunk -Olog_format=line
 
583
            Now on revision 1.
 
584
            Added Revisions:
 
585
            1: jrandom@example.com ...we need some foo
 
586
            2>+N  file
 
587
            2>All changes applied successfully.
 
588
            """)