/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

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

  • Committer: Jelmer Vernooij
  • Date: 2017-12-03 15:14:22 UTC
  • mfrom: (6829.1.1 no-branch-nick)
  • Revision ID: jelmer@jelmer.uk-20171203151422-54pwtld2ae5cx11l
Merge lp:~jelmer/brz/no-branch-nick.

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