~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Patch Queue Manager
  • Date: 2013-05-23 10:35:23 UTC
  • mfrom: (6574.1.1 integration)
  • Revision ID: pqm@pqm.ubuntu.com-20130523103523-2wt6jmauja1n1vdt
(jameinel) Merge bzr/2.5 into trunk. (John A Meinel)

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
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
16
 
18
17
 
19
18
"""Black-box tests for bzr pull."""
21
20
import os
22
21
import sys
23
22
 
24
 
from bzrlib.branch import Branch
25
 
from bzrlib.tests.blackbox import ExternalBase
26
 
from bzrlib.uncommit import uncommit
27
 
 
28
 
 
29
 
class TestPull(ExternalBase):
30
 
 
31
 
    def example_branch(test):
32
 
        test.runbzr('init')
33
 
        file('hello', 'wt').write('foo')
34
 
        test.runbzr('add hello')
35
 
        test.runbzr('commit -m setup hello')
36
 
        file('goodbye', 'wt').write('baz')
37
 
        test.runbzr('add goodbye')
38
 
        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
39
53
 
40
54
    def test_pull(self):
41
55
        """Pull changes from one branch to another."""
42
 
        os.mkdir('a')
43
 
        os.chdir('a')
44
 
 
45
 
        self.example_branch()
46
 
        self.runbzr('pull', retcode=3)
47
 
        self.runbzr('missing', retcode=3)
48
 
        self.runbzr('missing .')
49
 
        self.runbzr('missing')
 
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')
50
62
        # this will work on windows because we check for the same branch
51
63
        # in pull - if it fails, it is a regression
52
 
        self.runbzr('pull')
53
 
        self.runbzr('pull /', retcode=3)
 
64
        self.run_bzr('pull', working_dir='a')
 
65
        self.run_bzr('pull /', retcode=3, working_dir='a')
54
66
        if sys.platform not in ('win32', 'cygwin'):
55
 
            self.runbzr('pull')
56
 
 
57
 
        os.chdir('..')
58
 
        self.runbzr('branch a b')
59
 
        os.chdir('b')
60
 
        self.runbzr('pull')
61
 
        os.mkdir('subdir')
62
 
        self.runbzr('add subdir')
63
 
        self.runbzr('commit -m blah --unchanged')
64
 
        os.chdir('../a')
65
 
        a = Branch.open('.')
66
 
        b = Branch.open('../b')
67
 
        self.assertEquals(a.revision_history(), b.revision_history()[:-1])
68
 
        self.runbzr('pull ../b')
69
 
        self.assertEquals(a.revision_history(), b.revision_history())
70
 
        self.runbzr('commit -m blah2 --unchanged')
71
 
        os.chdir('../b')
72
 
        self.runbzr('commit -m blah3 --unchanged')
 
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)
73
84
        # no overwrite
74
 
        self.runbzr('pull ../a', retcode=3)
75
 
        os.chdir('..')
76
 
        self.runbzr('branch b overwriteme')
77
 
        os.chdir('overwriteme')
78
 
        self.runbzr('pull --overwrite ../a')
79
 
        overwritten = Branch.open('.')
80
 
        self.assertEqual(overwritten.revision_history(),
81
 
                         a.revision_history())
82
 
        os.chdir('../a')
83
 
        self.runbzr('merge ../b')
84
 
        self.runbzr('commit -m blah4 --unchanged')
85
 
        os.chdir('../b/subdir')
86
 
        self.runbzr('pull ../../a')
87
 
        self.assertEquals(a.revision_history()[-1], b.revision_history()[-1])
88
 
        self.runbzr('commit -m blah5 --unchanged')
89
 
        self.runbzr('commit -m blah6 --unchanged')
90
 
        os.chdir('..')
91
 
        self.runbzr('pull ../a')
92
 
        os.chdir('../a')
93
 
        self.runbzr('commit -m blah7 --unchanged')
94
 
        self.runbzr('merge ../b')
95
 
        self.runbzr('commit -m blah8 --unchanged')
96
 
        self.runbzr('pull ../b')
97
 
        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'])
98
116
 
99
117
    def test_pull_revision(self):
100
118
        """Pull some changes from one branch to another."""
101
 
        os.mkdir('a')
102
 
        os.chdir('a')
103
 
 
104
 
        self.example_branch()
105
 
        file('hello2', 'wt').write('foo')
106
 
        self.runbzr('add hello2')
107
 
        self.runbzr('commit -m setup hello2')
108
 
        file('goodbye2', 'wt').write('baz')
109
 
        self.runbzr('add goodbye2')
110
 
        self.runbzr('commit -m setup goodbye2')
111
 
 
112
 
        os.chdir('..')
113
 
        self.runbzr('branch -r 1 a b')
114
 
        os.chdir('b')
115
 
        self.runbzr('pull -r 2')
116
 
        a = Branch.open('../a')
117
 
        b = Branch.open('.')
118
 
        self.assertEquals(a.revno(),4)
119
 
        self.assertEquals(b.revno(),2)
120
 
        self.runbzr('pull -r 3')
121
 
        self.assertEquals(b.revno(),3)
122
 
        self.runbzr('pull -r 4')
123
 
        self.assertEquals(a.revision_history(), b.revision_history())
124
 
 
 
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')
125
156
 
126
157
    def test_overwrite_uptodate(self):
127
158
        # Make sure pull --overwrite overwrites
128
159
        # even if the target branch has merged
129
160
        # everything already.
130
 
        bzr = self.run_bzr
131
 
 
132
 
        def get_rh(expected_len):
133
 
            rh = self.capture('revision-history')
134
 
            # Make sure we don't have trailing empty revisions
135
 
            rh = rh.strip().split('\n')
136
 
            self.assertEqual(len(rh), expected_len)
137
 
            return rh
138
 
 
139
 
        os.mkdir('a')
140
 
        os.chdir('a')
141
 
        bzr('init')
142
 
        open('foo', 'wb').write('original\n')
143
 
        bzr('add', 'foo')
144
 
        bzr('commit', '-m', 'initial commit')
145
 
 
146
 
        os.chdir('..')
147
 
        bzr('branch', 'a', 'b')
148
 
 
149
 
        os.chdir('a')
150
 
        open('foo', 'wb').write('changed\n')
151
 
        bzr('commit', '-m', 'later change')
152
 
 
153
 
        open('foo', 'wb').write('another\n')
154
 
        bzr('commit', '-m', 'a third change')
155
 
 
156
 
        rev_history_a = get_rh(3)
157
 
 
158
 
        os.chdir('../b')
159
 
        bzr('merge', '../a')
160
 
        bzr('commit', '-m', 'merge')
161
 
 
162
 
        rev_history_b = get_rh(2)
163
 
 
164
 
        bzr('pull', '--overwrite', '../a')
165
 
        rev_history_b = get_rh(3)
166
 
 
167
 
        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())
168
185
 
169
186
    def test_overwrite_children(self):
170
187
        # Make sure pull --overwrite sets the revision-history
171
188
        # to be identical to the pull source, even if we have convergence
172
 
        bzr = self.run_bzr
173
 
 
174
 
        def get_rh(expected_len):
175
 
            rh = self.capture('revision-history')
176
 
            # Make sure we don't have trailing empty revisions
177
 
            rh = rh.strip().split('\n')
178
 
            self.assertEqual(len(rh), expected_len)
179
 
            return rh
180
 
 
181
 
        os.mkdir('a')
182
 
        os.chdir('a')
183
 
        bzr('init')
184
 
        open('foo', 'wb').write('original\n')
185
 
        bzr('add', 'foo')
186
 
        bzr('commit', '-m', 'initial commit')
187
 
 
188
 
        os.chdir('..')
189
 
        bzr('branch', 'a', 'b')
190
 
 
191
 
        os.chdir('a')
192
 
        open('foo', 'wb').write('changed\n')
193
 
        bzr('commit', '-m', 'later change')
194
 
 
195
 
        open('foo', 'wb').write('another\n')
196
 
        bzr('commit', '-m', 'a third change')
197
 
 
198
 
        rev_history_a = get_rh(3)
199
 
 
200
 
        os.chdir('../b')
201
 
        bzr('merge', '../a')
202
 
        bzr('commit', '-m', 'merge')
203
 
 
204
 
        rev_history_b = get_rh(2)
205
 
 
206
 
        os.chdir('../a')
207
 
        open('foo', 'wb').write('a fourth change\n')
208
 
        bzr('commit', '-m', 'a fourth change')
209
 
 
210
 
        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)
211
214
 
212
215
        # With convergence, we could just pull over the
213
216
        # new change, but with --overwrite, we want to switch our history
214
 
        os.chdir('../b')
215
 
        bzr('pull', '--overwrite', '../a')
216
 
        rev_history_b = get_rh(4)
217
 
 
218
 
        self.assertEqual(rev_history_b, rev_history_a)
 
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)
219
221
 
220
222
    def test_pull_remember(self):
221
223
        """Pull changes from one branch to another and test parent location."""
222
 
        transport = self.get_transport()
 
224
        t = self.get_transport()
223
225
        tree_a = self.make_branch_and_tree('branch_a')
224
226
        branch_a = tree_a.branch
225
227
        self.build_tree(['branch_a/a'])
234
236
        tree_a.commit('commit b')
235
237
        # reset parent
236
238
        parent = branch_b.get_parent()
 
239
        branch_b = branch.Branch.open('branch_b')
237
240
        branch_b.set_parent(None)
238
241
        self.assertEqual(None, branch_b.get_parent())
239
242
        # test pull for failure without parent set
240
 
        os.chdir('branch_b')
241
 
        out = self.runbzr('pull', retcode=3)
242
 
        self.assertEquals(out,
 
243
        out = self.run_bzr('pull', retcode=3, working_dir='branch_b')
 
244
        self.assertEqual(out,
243
245
                ('','bzr: ERROR: No pull location known or specified.\n'))
244
246
        # test implicit --remember when no parent set, this pull conflicts
245
 
        self.build_tree(['d'])
 
247
        self.build_tree(['branch_b/d'])
246
248
        tree_b.add('d')
247
249
        tree_b.commit('commit d')
248
 
        out = self.runbzr('pull ../branch_a', retcode=3)
249
 
        self.assertEquals(out,
250
 
                ('','bzr: ERROR: These branches have diverged.  Use the merge command to reconcile them.\n'))
251
 
        self.assertEquals(branch_b.get_parent(), parent)
 
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())
252
259
        # test implicit --remember after resolving previous failure
253
 
        uncommit(branch=branch_b, tree=tree_b)
254
 
        transport.delete('branch_b/d')
255
 
        self.runbzr('pull')
256
 
        self.assertEquals(branch_b.get_parent(), parent)
 
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)
257
266
        # test explicit --remember
258
 
        self.runbzr('pull ../branch_c --remember')
259
 
        self.assertEquals(branch_b.get_parent(),
260
 
                          branch_c.bzrdir.root_transport.base)
 
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())
261
272
 
262
273
    def test_pull_bundle(self):
263
274
        from bzrlib.testament import Testament
264
275
        # Build up 2 trees and prepare for a pull
265
276
        tree_a = self.make_branch_and_tree('branch_a')
266
 
        f = open('branch_a/a', 'wb')
267
 
        f.write('hello')
268
 
        f.close()
 
277
        with open('branch_a/a', 'wb') as f:
 
278
            f.write('hello')
269
279
        tree_a.add('a')
270
280
        tree_a.commit('message')
271
281
 
272
282
        tree_b = tree_a.bzrdir.sprout('branch_b').open_workingtree()
273
283
 
274
284
        # Make a change to 'a' that 'b' can pull
275
 
        f = open('branch_a/a', 'wb')
276
 
        f.write('hey there')
277
 
        f.close()
 
285
        with open('branch_a/a', 'wb') as f:
 
286
            f.write('hey there')
278
287
        tree_a.commit('message')
279
288
 
280
289
        # Create the bundle for 'b' to pull
281
 
        os.chdir('branch_a')
282
 
        bundle_file = open('../bundle', 'wb')
283
 
        bundle_file.write(self.run_bzr('bundle', '../branch_b')[0])
284
 
        bundle_file.close()
285
 
 
286
 
        os.chdir('../branch_b')
287
 
        output = self.run_bzr('pull', '../bundle')
288
 
        self.assertEqual('', output[0])
289
 
        self.assertEqual('All changes applied successfully.\n'
290
 
                         '1 revision(s) pulled.\n', output[1])
291
 
 
292
 
        self.assertEqualDiff(tree_a.branch.revision_history(),
293
 
                             tree_b.branch.revision_history())
294
 
 
295
 
        testament_a = Testament.from_revision(tree_a.branch.repository, 
296
 
                                              tree_a.last_revision())
 
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])
297
303
        testament_b = Testament.from_revision(tree_b.branch.repository,
298
 
                                              tree_b.last_revision())
 
304
                                              tree_b.get_parent_ids()[0])
299
305
        self.assertEqualDiff(testament_a.as_text(),
300
306
                             testament_b.as_text())
301
307
 
302
308
        # it is legal to attempt to pull an already-merged bundle
303
 
        output = self.run_bzr('pull', '../bundle')
304
 
        self.assertEqual('', output[0])
305
 
        self.assertEqual('0 revision(s) pulled.\n', output[1])
 
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
            """)