/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: 2018-12-10 01:46:35 UTC
  • mto: This revision was merged to the branch mainline in revision 7219.
  • Revision ID: jelmer@jelmer.uk-20181210014635-oxhnf8s46u0nvp5c
Fix import

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'), b'foo'),
 
49
            (osutils.pathjoin(path, 'goodbye'), b'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', b'foo'),
 
124
            ('a/goodbye2', b'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(
 
149
            builder)
 
150
        source.get_config_stack().set('branch.fetch_tags', True)
 
151
        target_bzrdir = source.controldir.sprout('target')
 
152
        source.tags.set_tag('tag-a', rev2)
 
153
        # Pull from source
 
154
        self.run_bzr('pull -d target source')
 
155
        target = target_bzrdir.open_branch()
 
156
        # The tag is present, and so is its revision.
 
157
        self.assertEqual(rev2, target.tags.lookup_tag('tag-a'))
 
158
        target.repository.get_revision(rev2)
133
159
 
134
160
    def test_overwrite_uptodate(self):
135
161
        # Make sure pull --overwrite overwrites
136
162
        # even if the target branch has merged
137
163
        # 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)
 
164
        a_tree = self.make_branch_and_tree('a')
 
165
        self.build_tree_contents([('a/foo', b'original\n')])
 
166
        a_tree.add('foo')
 
167
        a_tree.commit(message='initial commit')
 
168
 
 
169
        b_tree = a_tree.controldir.sprout('b').open_workingtree()
 
170
 
 
171
        self.build_tree_contents([('a/foo', b'changed\n')])
 
172
        a_tree.commit(message='later change')
 
173
 
 
174
        self.build_tree_contents([('a/foo', b'a third change')])
 
175
        a_tree.commit(message='a third change')
 
176
 
 
177
        self.assertEqual(a_tree.branch.last_revision_info()[0], 3)
 
178
 
 
179
        b_tree.merge_from_branch(a_tree.branch)
 
180
        b_tree.commit(message='merge')
 
181
 
 
182
        self.assertEqual(b_tree.branch.last_revision_info()[0], 2)
 
183
 
 
184
        self.run_bzr('pull --overwrite ../a', working_dir='b')
 
185
        (last_revinfo_b) = b_tree.branch.last_revision_info()
 
186
        self.assertEqual(last_revinfo_b[0], 3)
 
187
        self.assertEqual(last_revinfo_b[1], a_tree.branch.last_revision())
176
188
 
177
189
    def test_overwrite_children(self):
178
190
        # Make sure pull --overwrite sets the revision-history
179
191
        # 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)
 
192
        a_tree = self.make_branch_and_tree('a')
 
193
        self.build_tree_contents([('a/foo', b'original\n')])
 
194
        a_tree.add('foo')
 
195
        a_tree.commit(message='initial commit')
 
196
 
 
197
        b_tree = a_tree.controldir.sprout('b').open_workingtree()
 
198
 
 
199
        self.build_tree_contents([('a/foo', b'changed\n')])
 
200
        a_tree.commit(message='later change')
 
201
 
 
202
        self.build_tree_contents([('a/foo', b'a third change')])
 
203
        a_tree.commit(message='a third change')
 
204
 
 
205
        self.assertEqual(a_tree.branch.last_revision_info()[0], 3)
 
206
 
 
207
        b_tree.merge_from_branch(a_tree.branch)
 
208
        b_tree.commit(message='merge')
 
209
 
 
210
        self.assertEqual(b_tree.branch.last_revision_info()[0], 2)
 
211
 
 
212
        self.build_tree_contents([('a/foo', b'a fourth change\n')])
 
213
        a_tree.commit(message='a fourth change')
 
214
 
 
215
        rev_info_a = a_tree.branch.last_revision_info()
 
216
        self.assertEqual(rev_info_a[0], 4)
219
217
 
220
218
        # With convergence, we could just pull over the
221
219
        # 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)
 
220
        self.run_bzr('pull --overwrite ../a', working_dir='b')
 
221
        rev_info_b = b_tree.branch.last_revision_info()
 
222
        self.assertEqual(rev_info_b[0], 4)
 
223
        self.assertEqual(rev_info_b, rev_info_a)
227
224
 
228
225
    def test_pull_remember(self):
229
226
        """Pull changes from one branch to another and test parent location."""
230
 
        transport = self.get_transport()
 
227
        t = self.get_transport()
231
228
        tree_a = self.make_branch_and_tree('branch_a')
232
229
        branch_a = tree_a.branch
233
230
        self.build_tree(['branch_a/a'])
234
231
        tree_a.add('a')
235
232
        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()
 
233
        tree_b = branch_a.controldir.sprout('branch_b').open_workingtree()
 
234
        branch_b = tree_b.branch
 
235
        tree_c = branch_a.controldir.sprout('branch_c').open_workingtree()
 
236
        branch_c = tree_c.branch
240
237
        self.build_tree(['branch_a/b'])
241
238
        tree_a.add('b')
242
239
        tree_a.commit('commit b')
243
240
        # reset parent
244
241
        parent = branch_b.get_parent()
 
242
        branch_b = branch.Branch.open('branch_b')
245
243
        branch_b.set_parent(None)
246
244
        self.assertEqual(None, branch_b.get_parent())
247
245
        # 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'))
 
246
        out = self.run_bzr('pull', retcode=3, working_dir='branch_b')
 
247
        self.assertEqual(out,
 
248
                         ('', 'brz: ERROR: No pull location known or specified.\n'))
252
249
        # test implicit --remember when no parent set, this pull conflicts
253
 
        self.build_tree(['d'])
 
250
        self.build_tree(['branch_b/d'])
254
251
        tree_b.add('d')
255
252
        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))
 
253
        out = self.run_bzr('pull ../branch_a', retcode=3,
 
254
                           working_dir='branch_b')
 
255
        self.assertEqual(out,
 
256
                         ('', 'brz: ERROR: These branches have diverged.'
 
257
                          ' Use the missing command to see how.\n'
 
258
                          'Use the merge command to reconcile them.\n'))
 
259
        tree_b = tree_b.controldir.open_workingtree()
 
260
        branch_b = tree_b.branch
 
261
        self.assertEqual(parent, branch_b.get_parent())
260
262
        # 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))
 
263
        uncommit.uncommit(branch=branch_b, tree=tree_b)
 
264
        t.delete('branch_b/d')
 
265
        self.run_bzr('pull', working_dir='branch_b')
 
266
        # Refresh the branch object as 'pull' modified it
 
267
        branch_b = branch_b.controldir.open_branch()
 
268
        self.assertEqual(branch_b.get_parent(), parent)
265
269
        # 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))
 
270
        self.run_bzr('pull ../branch_c --remember', working_dir='branch_b')
 
271
        # Refresh the branch object as 'pull' modified it
 
272
        branch_b = branch_b.controldir.open_branch()
 
273
        self.assertEqual(branch_c.controldir.root_transport.base,
 
274
                         branch_b.get_parent())
 
275
 
 
276
    def test_pull_bundle(self):
 
277
        from breezy.testament import Testament
 
278
        # Build up 2 trees and prepare for a pull
 
279
        tree_a = self.make_branch_and_tree('branch_a')
 
280
        with open('branch_a/a', 'wb') as f:
 
281
            f.write(b'hello')
 
282
        tree_a.add('a')
 
283
        tree_a.commit('message')
 
284
 
 
285
        tree_b = tree_a.controldir.sprout('branch_b').open_workingtree()
 
286
 
 
287
        # Make a change to 'a' that 'b' can pull
 
288
        with open('branch_a/a', 'wb') as f:
 
289
            f.write(b'hey there')
 
290
        tree_a.commit('message')
 
291
 
 
292
        # Create the bundle for 'b' to pull
 
293
        self.run_bzr('bundle ../branch_b -o ../bundle', working_dir='branch_a')
 
294
 
 
295
        out, err = self.run_bzr('pull ../bundle', working_dir='branch_b')
 
296
        self.assertEqual(out,
 
297
                         'Now on revision 2.\n')
 
298
        self.assertEqual(err,
 
299
                         ' M  a\nAll changes applied successfully.\n')
 
300
 
 
301
        self.assertEqualDiff(tree_a.branch.last_revision(),
 
302
                             tree_b.branch.last_revision())
 
303
 
 
304
        testament_a = Testament.from_revision(tree_a.branch.repository,
 
305
                                              tree_a.get_parent_ids()[0])
 
306
        testament_b = Testament.from_revision(tree_b.branch.repository,
 
307
                                              tree_b.get_parent_ids()[0])
 
308
        self.assertEqualDiff(testament_a.as_text(),
 
309
                             testament_b.as_text())
 
310
 
 
311
        # it is legal to attempt to pull an already-merged bundle
 
312
        out, err = self.run_bzr('pull ../bundle', working_dir='branch_b')
 
313
        self.assertEqual(err, '')
 
314
        self.assertEqual(out, 'No revisions or tags to pull.\n')
 
315
 
 
316
    def test_pull_verbose_no_files(self):
 
317
        """Pull --verbose should not list modified files"""
 
318
        tree_a = self.make_branch_and_tree('tree_a')
 
319
        self.build_tree(['tree_a/foo'])
 
320
        tree_a.add('foo')
 
321
        tree_a.commit('bar')
 
322
        tree_b = self.make_branch_and_tree('tree_b')
 
323
        out = self.run_bzr('pull --verbose -d tree_b tree_a')[0]
 
324
        self.assertContainsRe(out, 'bar')
 
325
        self.assertNotContainsRe(out, 'added:')
 
326
        self.assertNotContainsRe(out, 'foo')
 
327
 
 
328
    def test_pull_quiet(self):
 
329
        """Check that brz pull --quiet does not print anything"""
 
330
        tree_a = self.make_branch_and_tree('tree_a')
 
331
        self.build_tree(['tree_a/foo'])
 
332
        tree_a.add('foo')
 
333
        revision_id = tree_a.commit('bar')
 
334
        tree_b = tree_a.controldir.sprout('tree_b').open_workingtree()
 
335
        out, err = self.run_bzr('pull --quiet -d tree_b')
 
336
        self.assertEqual(out, '')
 
337
        self.assertEqual(err, '')
 
338
        self.assertEqual(tree_b.last_revision(), revision_id)
 
339
        self.build_tree(['tree_a/moo'])
 
340
        tree_a.add('moo')
 
341
        revision_id = tree_a.commit('quack')
 
342
        out, err = self.run_bzr('pull --quiet -d tree_b')
 
343
        self.assertEqual(out, '')
 
344
        self.assertEqual(err, '')
 
345
        self.assertEqual(tree_b.last_revision(), revision_id)
 
346
 
 
347
    def test_pull_from_directory_service(self):
 
348
        source = self.make_branch_and_tree('source')
 
349
        source.commit('commit 1')
 
350
        target = source.controldir.sprout('target').open_workingtree()
 
351
        source_last = source.commit('commit 2')
 
352
 
 
353
        class FooService(object):
 
354
            """A directory service that always returns source"""
 
355
 
 
356
            def look_up(self, name, url):
 
357
                return 'source'
 
358
        directories.register('foo:', FooService, 'Testing directory service')
 
359
        self.addCleanup(directories.remove, 'foo:')
 
360
        self.run_bzr('pull foo:bar -d target')
 
361
        self.assertEqual(source_last, target.last_revision())
 
362
 
 
363
    def test_pull_verbose_defaults_to_long(self):
 
364
        tree = self.example_branch('source')
 
365
        target = self.make_branch_and_tree('target')
 
366
        out = self.run_bzr('pull -v source -d target')[0]
 
367
        self.assertContainsRe(out,
 
368
                              r'revno: 1\ncommitter: .*\nbranch nick: source')
 
369
        self.assertNotContainsRe(out, r'\n {4}1 .*\n {6}setup\n')
 
370
 
 
371
    def test_pull_verbose_uses_default_log(self):
 
372
        tree = self.example_branch('source')
 
373
        target = self.make_branch_and_tree('target')
 
374
        target.branch.get_config_stack().set('log_format', 'short')
 
375
        out = self.run_bzr('pull -v source -d target')[0]
 
376
        self.assertContainsRe(out, r'\n {4}1 .*\n {6}setup\n')
 
377
        self.assertNotContainsRe(
 
378
            out, r'revno: 1\ncommitter: .*\nbranch nick: source')
 
379
 
 
380
    def test_pull_smart_bound_branch(self):
 
381
        self.setup_smart_server_with_call_log()
 
382
        parent = self.make_branch_and_tree('parent')
 
383
        parent.commit(message='first commit')
 
384
        child = parent.controldir.sprout('child').open_workingtree()
 
385
        child.commit(message='second commit')
 
386
        checkout = parent.branch.create_checkout('checkout')
 
387
        self.run_bzr(['pull', self.get_url('child')], working_dir='checkout')
 
388
 
 
389
    def test_pull_smart_stacked_streaming_acceptance(self):
 
390
        """'brz pull -r 123' works on stacked, smart branches, even when the
 
391
        revision specified by the revno is only present in the fallback
 
392
        repository.
 
393
 
 
394
        See <https://launchpad.net/bugs/380314>
 
395
        """
 
396
        self.setup_smart_server_with_call_log()
 
397
        # Make a stacked-on branch with two commits so that the
 
398
        # revision-history can't be determined just by looking at the parent
 
399
        # field in the revision in the stacked repo.
 
400
        parent = self.make_branch_and_tree('parent', format='1.9')
 
401
        parent.commit(message='first commit')
 
402
        parent.commit(message='second commit')
 
403
        local = parent.controldir.sprout('local').open_workingtree()
 
404
        local.commit(message='local commit')
 
405
        local.branch.create_clone_on_transport(
 
406
            self.get_transport('stacked'), stacked_on=self.get_url('parent'))
 
407
        empty = self.make_branch_and_tree('empty', format='1.9')
 
408
        self.reset_smart_call_log()
 
409
        self.run_bzr(['pull', '-r', '1', self.get_url('stacked')],
 
410
                     working_dir='empty')
 
411
        # This figure represent the amount of work to perform this use case. It
 
412
        # is entirely ok to reduce this number if a test fails due to rpc_count
 
413
        # being too low. If rpc_count increases, more network roundtrips have
 
414
        # become necessary for this use case. Please do not adjust this number
 
415
        # upwards without agreement from bzr's network support maintainers.
 
416
        self.assertLength(19, self.hpss_calls)
 
417
        self.assertLength(1, self.hpss_connections)
 
418
        remote = branch.Branch.open('stacked')
 
419
        self.assertEndsWith(remote.get_stacked_on_url(), '/parent')
 
420
 
 
421
    def test_pull_cross_format_warning(self):
 
422
        """You get a warning for probably slow cross-format pulls.
 
423
        """
 
424
        # this is assumed to be going through InterDifferingSerializer
 
425
        from_tree = self.make_branch_and_tree('from', format='2a')
 
426
        to_tree = self.make_branch_and_tree('to', format='1.14-rich-root')
 
427
        from_tree.commit(message='first commit')
 
428
        out, err = self.run_bzr(['pull', '-d', 'to', 'from'])
 
429
        self.assertContainsRe(err,
 
430
                              "(?m)Doing on-the-fly conversion")
 
431
 
 
432
    def test_pull_cross_format_warning_no_IDS(self):
 
433
        """You get a warning for probably slow cross-format pulls.
 
434
        """
 
435
        # this simulates what would happen across the network, where
 
436
        # interdifferingserializer is not active
 
437
 
 
438
        debug.debug_flags.add('IDS_never')
 
439
        # TestCase take care of restoring them
 
440
 
 
441
        from_tree = self.make_branch_and_tree('from', format='2a')
 
442
        to_tree = self.make_branch_and_tree('to', format='1.14-rich-root')
 
443
        from_tree.commit(message='first commit')
 
444
        out, err = self.run_bzr(['pull', '-d', 'to', 'from'])
 
445
        self.assertContainsRe(err,
 
446
                              "(?m)Doing on-the-fly conversion")
 
447
 
 
448
    def test_pull_cross_format_from_network(self):
 
449
        self.setup_smart_server_with_call_log()
 
450
        from_tree = self.make_branch_and_tree('from', format='2a')
 
451
        to_tree = self.make_branch_and_tree('to', format='1.14-rich-root')
 
452
        self.assertIsInstance(from_tree.branch, remote.RemoteBranch)
 
453
        from_tree.commit(message='first commit')
 
454
        out, err = self.run_bzr(['pull', '-d', 'to',
 
455
                                 from_tree.branch.controldir.root_transport.base])
 
456
        self.assertContainsRe(err,
 
457
                              "(?m)Doing on-the-fly conversion")
 
458
 
 
459
    def test_pull_to_experimental_format_warning(self):
 
460
        """You get a warning for pulling into experimental formats.
 
461
        """
 
462
        from_tree = self.make_branch_and_tree(
 
463
            'from', format='development-subtree')
 
464
        to_tree = self.make_branch_and_tree('to', format='development-subtree')
 
465
        from_tree.commit(message='first commit')
 
466
        out, err = self.run_bzr(['pull', '-d', 'to', 'from'])
 
467
        self.assertContainsRe(err,
 
468
                              "(?m)Fetching into experimental format")
 
469
 
 
470
    def test_pull_cross_to_experimental_format_warning(self):
 
471
        """You get a warning for pulling into experimental formats.
 
472
        """
 
473
        from_tree = self.make_branch_and_tree('from', format='2a')
 
474
        to_tree = self.make_branch_and_tree('to', format='development-subtree')
 
475
        from_tree.commit(message='first commit')
 
476
        out, err = self.run_bzr(['pull', '-d', 'to', 'from'])
 
477
        self.assertContainsRe(err,
 
478
                              "(?m)Fetching into experimental format")
 
479
 
 
480
    def test_pull_show_base(self):
 
481
        """brz pull supports --show-base
 
482
 
 
483
        see https://bugs.launchpad.net/bzr/+bug/202374"""
 
484
        # create two trees with conflicts, setup conflict, check that
 
485
        # conflicted file looks correct
 
486
        a_tree = self.example_branch('a')
 
487
        b_tree = a_tree.controldir.sprout('b').open_workingtree()
 
488
 
 
489
        with open(osutils.pathjoin('a', 'hello'), 'wt') as f:
 
490
            f.write('fee')
 
491
        a_tree.commit('fee')
 
492
 
 
493
        with open(osutils.pathjoin('b', 'hello'), 'wt') as f:
 
494
            f.write('fie')
 
495
 
 
496
        out, err = self.run_bzr(['pull', '-d', 'b', 'a', '--show-base'])
 
497
 
 
498
        # check for message here
 
499
        self.assertEqual(
 
500
            err,
 
501
            ' M  hello\nText conflict in hello\n1 conflicts encountered.\n')
 
502
 
 
503
        self.assertEqualDiff('<<<<<<< TREE\n'
 
504
                             'fie||||||| BASE-REVISION\n'
 
505
                             'foo=======\n'
 
506
                             'fee>>>>>>> MERGE-SOURCE\n',
 
507
                             open(osutils.pathjoin('b', 'hello')).read())
 
508
 
 
509
    def test_pull_warns_about_show_base_when_no_working_tree(self):
 
510
        """--show-base is useless if there's no working tree
 
511
 
 
512
        see https://bugs.launchpad.net/bzr/+bug/1022160"""
 
513
        self.make_branch('from')
 
514
        self.make_branch('to')
 
515
        out = self.run_bzr(['pull', '-d', 'to', 'from', '--show-base'])
 
516
        self.assertEqual(out, ('No revisions or tags to pull.\n',
 
517
                               'No working tree, ignoring --show-base\n'))
 
518
 
 
519
    def test_pull_tag_conflicts(self):
 
520
        """pulling tags with conflicts will change the exit code"""
 
521
        # create a branch, see that --show-base fails
 
522
        from_tree = self.make_branch_and_tree('from')
 
523
        from_tree.branch.tags.set_tag("mytag", b"somerevid")
 
524
        to_tree = self.make_branch_and_tree('to')
 
525
        to_tree.branch.tags.set_tag("mytag", b"anotherrevid")
 
526
        out = self.run_bzr(['pull', '-d', 'to', 'from'], retcode=1)
 
527
        self.assertEqual(out,
 
528
                         ('No revisions to pull.\nConflicting tags:\n    mytag\n', ''))
 
529
 
 
530
    def test_pull_tag_notification(self):
 
531
        """pulling tags with conflicts will change the exit code"""
 
532
        # create a branch, see that --show-base fails
 
533
        from_tree = self.make_branch_and_tree('from')
 
534
        from_tree.branch.tags.set_tag("mytag", b"somerevid")
 
535
        to_tree = self.make_branch_and_tree('to')
 
536
        out = self.run_bzr(['pull', '-d', 'to', 'from'])
 
537
        self.assertEqual(out,
 
538
                         ('1 tag(s) updated.\n', ''))
 
539
 
 
540
    def test_overwrite_tags(self):
 
541
        """--overwrite-tags only overwrites tags, not revisions."""
 
542
        from_tree = self.make_branch_and_tree('from')
 
543
        from_tree.branch.tags.set_tag("mytag", b"somerevid")
 
544
        to_tree = self.make_branch_and_tree('to')
 
545
        to_tree.branch.tags.set_tag("mytag", b"anotherrevid")
 
546
        revid1 = to_tree.commit('my commit')
 
547
        out = self.run_bzr(['pull', '-d', 'to', 'from'], retcode=1)
 
548
        self.assertEqual(out,
 
549
                         ('No revisions to pull.\nConflicting tags:\n    mytag\n', ''))
 
550
        out = self.run_bzr(['pull', '-d', 'to', '--overwrite-tags', 'from'])
 
551
        self.assertEqual(out, ('1 tag(s) updated.\n', ''))
 
552
 
 
553
        self.assertEqual(to_tree.branch.tags.lookup_tag('mytag'),
 
554
                         b'somerevid')
 
555
        self.assertEqual(to_tree.branch.last_revision(), revid1)
 
556
 
 
557
    def test_pull_tag_overwrite(self):
 
558
        """pulling tags with --overwrite only reports changed tags."""
 
559
        # create a branch, see that --show-base fails
 
560
        from_tree = self.make_branch_and_tree('from')
 
561
        from_tree.branch.tags.set_tag("mytag", b"somerevid")
 
562
        to_tree = self.make_branch_and_tree('to')
 
563
        to_tree.branch.tags.set_tag("mytag", b"somerevid")
 
564
        out = self.run_bzr(['pull', '--overwrite', '-d', 'to', 'from'])
 
565
        self.assertEqual(out,
 
566
                         ('No revisions or tags to pull.\n', ''))
 
567
 
 
568
 
 
569
class TestPullOutput(script.TestCaseWithTransportAndScript):
 
570
 
 
571
    def test_pull_log_format(self):
 
572
        self.run_script("""
 
573
            $ brz init trunk
 
574
            Created a standalone tree (format: 2a)
 
575
            $ cd trunk
 
576
            $ echo foo > file
 
577
            $ brz add
 
578
            adding file
 
579
            $ brz commit -m 'we need some foo'
 
580
            2>Committing to:...trunk/
 
581
            2>added file
 
582
            2>Committed revision 1.
 
583
            $ cd ..
 
584
            $ brz init feature
 
585
            Created a standalone tree (format: 2a)
 
586
            $ cd feature
 
587
            $ brz pull -v ../trunk -Olog_format=line
 
588
            Now on revision 1.
 
589
            Added Revisions:
 
590
            1: jrandom@example.com ...we need some foo
 
591
            2>+N  file
 
592
            2>All changes applied successfully.
 
593
            """)