~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2011-08-17 18:13:57 UTC
  • mfrom: (5268.7.29 transport-segments)
  • Revision ID: pqm@pqm.ubuntu.com-20110817181357-y5q5eth1hk8bl3om
(jelmer) Allow specifying the colocated branch to use in the branch URL,
 and retrieving the branch name using ControlDir._get_selected_branch.
 (Jelmer Vernooij)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006 Canonical Ltd
2
 
# -*- coding: utf-8 -*-
 
1
# Copyright (C) 2006-2010 Canonical Ltd
3
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
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
"""Tests for the update command of bzr."""
20
19
 
21
20
import os
22
 
 
23
 
from bzrlib import branch, bzrdir
24
 
from bzrlib.tests import TestSkipped
25
 
from bzrlib.tests.blackbox import ExternalBase
26
 
from bzrlib.workingtree import WorkingTree
27
 
 
28
 
 
29
 
class TestUpdate(ExternalBase):
 
21
import re
 
22
 
 
23
from bzrlib import (
 
24
    branch,
 
25
    bzrdir,
 
26
    osutils,
 
27
    tests,
 
28
    urlutils,
 
29
    workingtree,
 
30
    )
 
31
from bzrlib.tests.script import ScriptRunner
 
32
 
 
33
 
 
34
class TestUpdate(tests.TestCaseWithTransport):
30
35
 
31
36
    def test_update_standalone_trivial(self):
32
 
        self.runbzr("init")
33
 
        out, err = self.runbzr('update')
34
 
        self.assertEqual('Tree is up to date at revision 0.\n', err)
 
37
        self.make_branch_and_tree('.')
 
38
        out, err = self.run_bzr('update')
 
39
        self.assertEqual(
 
40
            'Tree is up to date at revision 0 of branch %s\n' % self.test_dir,
 
41
            err)
 
42
        self.assertEqual('', out)
 
43
 
 
44
    def test_update_quiet(self):
 
45
        self.make_branch_and_tree('.')
 
46
        out, err = self.run_bzr('update --quiet')
 
47
        self.assertEqual('', err)
35
48
        self.assertEqual('', out)
36
49
 
37
50
    def test_update_standalone_trivial_with_alias_up(self):
38
 
        self.runbzr("init")
39
 
        out, err = self.runbzr('up')
40
 
        self.assertEqual('Tree is up to date at revision 0.\n', err)
 
51
        self.make_branch_and_tree('.')
 
52
        out, err = self.run_bzr('up')
 
53
        self.assertEqual('Tree is up to date at revision 0 of branch %s\n'
 
54
                         % self.test_dir,
 
55
                         err)
41
56
        self.assertEqual('', out)
42
57
 
43
58
    def test_update_up_to_date_light_checkout(self):
44
59
        self.make_branch_and_tree('branch')
45
 
        self.runbzr('checkout --lightweight branch checkout')
46
 
        out, err = self.runbzr('update checkout')
47
 
        self.assertEqual('Tree is up to date at revision 0.\n', err)
 
60
        self.run_bzr('checkout --lightweight branch checkout')
 
61
        out, err = self.run_bzr('update checkout')
 
62
        self.assertEqual('Tree is up to date at revision 0 of branch %s\n'
 
63
                         % osutils.pathjoin(self.test_dir, 'branch'),
 
64
                         err)
48
65
        self.assertEqual('', out)
49
66
 
50
67
    def test_update_up_to_date_checkout(self):
51
68
        self.make_branch_and_tree('branch')
52
 
        self.run_bzr('checkout', 'branch', 'checkout')
53
 
        out, err = self.run_bzr('update', 'checkout')
54
 
        self.assertEqual('Tree is up to date at revision 0.\n', err)
55
 
        self.assertEqual('', out)
 
69
        self.run_bzr('checkout branch checkout')
 
70
        sr = ScriptRunner()
 
71
        sr.run_script(self, '''
 
72
$ bzr update checkout
 
73
2>Tree is up to date at revision 0 of branch .../branch
 
74
''')
56
75
 
57
76
    def test_update_out_of_date_standalone_tree(self):
58
77
        # FIXME the default format has to change for this to pass
59
78
        # because it currently uses the branch last-revision marker.
60
79
        self.make_branch_and_tree('branch')
61
80
        # make a checkout
62
 
        self.runbzr('checkout --lightweight branch checkout')
 
81
        self.run_bzr('checkout --lightweight branch checkout')
63
82
        self.build_tree(['checkout/file'])
64
 
        self.runbzr('add checkout/file')
65
 
        self.runbzr('commit -m add-file checkout')
 
83
        self.run_bzr('add checkout/file')
 
84
        self.run_bzr('commit -m add-file checkout')
66
85
        # now branch should be out of date
67
 
        out,err = self.runbzr('update branch')
 
86
        out,err = self.run_bzr('update branch')
68
87
        self.assertEqual('', out)
69
 
        self.assertEqual('All changes applied successfully.\n'
70
 
                         'Updated to revision 1.\n', err)
71
 
        self.failUnlessExists('branch/file')
 
88
        self.assertEqualDiff("""+N  file
 
89
All changes applied successfully.
 
90
Updated to revision 1 of branch %s
 
91
""" % osutils.pathjoin(self.test_dir, 'branch',),
 
92
                         err)
 
93
        self.assertPathExists('branch/file')
72
94
 
73
95
    def test_update_out_of_date_light_checkout(self):
74
96
        self.make_branch_and_tree('branch')
75
97
        # make two checkouts
76
 
        self.runbzr('checkout --lightweight branch checkout')
77
 
        self.runbzr('checkout --lightweight branch checkout2')
 
98
        self.run_bzr('checkout --lightweight branch checkout')
 
99
        self.run_bzr('checkout --lightweight branch checkout2')
78
100
        self.build_tree(['checkout/file'])
79
 
        self.runbzr('add checkout/file')
80
 
        self.runbzr('commit -m add-file checkout')
 
101
        self.run_bzr('add checkout/file')
 
102
        self.run_bzr('commit -m add-file checkout')
81
103
        # now checkout2 should be out of date
82
 
        out,err = self.runbzr('update checkout2')
83
 
        self.assertEqual('All changes applied successfully.\n'
84
 
                         'Updated to revision 1.\n',
 
104
        out,err = self.run_bzr('update checkout2')
 
105
        self.assertEqualDiff('''+N  file
 
106
All changes applied successfully.
 
107
Updated to revision 1 of branch %s
 
108
''' % osutils.pathjoin(self.test_dir, 'branch',),
85
109
                         err)
86
110
        self.assertEqual('', out)
87
111
 
88
112
    def test_update_conflicts_returns_2(self):
89
113
        self.make_branch_and_tree('branch')
90
114
        # make two checkouts
91
 
        self.runbzr('checkout --lightweight branch checkout')
 
115
        self.run_bzr('checkout --lightweight branch checkout')
92
116
        self.build_tree(['checkout/file'])
93
 
        self.runbzr('add checkout/file')
94
 
        self.runbzr('commit -m add-file checkout')
95
 
        self.runbzr('checkout --lightweight branch checkout2')
 
117
        self.run_bzr('add checkout/file')
 
118
        self.run_bzr('commit -m add-file checkout')
 
119
        self.run_bzr('checkout --lightweight branch checkout2')
96
120
        # now alter file in checkout
97
121
        a_file = file('checkout/file', 'wt')
98
122
        a_file.write('Foo')
99
123
        a_file.close()
100
 
        self.runbzr('commit -m checnge-file checkout')
 
124
        self.run_bzr('commit -m checnge-file checkout')
101
125
        # now checkout2 should be out of date
102
126
        # make a local change to file
103
127
        a_file = file('checkout2/file', 'wt')
104
128
        a_file.write('Bar')
105
129
        a_file.close()
106
 
        out,err = self.runbzr('update checkout2', retcode=1)
107
 
        self.assertEqual(['1 conflicts encountered.',
108
 
                          'Updated to revision 2.'],
109
 
                         err.split('\n')[1:3])
110
 
        self.assertContainsRe(err, 'Text conflict in file\n')
 
130
        out,err = self.run_bzr('update checkout2', retcode=1)
 
131
        self.assertEqualDiff(''' M  file
 
132
Text conflict in file
 
133
1 conflicts encountered.
 
134
Updated to revision 2 of branch %s
 
135
''' % osutils.pathjoin(self.test_dir, 'branch',),
 
136
                         err)
111
137
        self.assertEqual('', out)
112
138
 
113
139
    def test_smoke_update_checkout_bound_branch_local_commits(self):
114
140
        # smoke test for doing an update of a checkout of a bound
115
141
        # branch with local commits.
116
142
        master = self.make_branch_and_tree('master')
 
143
        master.commit('first commit')
117
144
        # make a bound branch
118
 
        self.run_bzr('checkout', 'master', 'child')
119
 
        # get an object form of child
120
 
        child = WorkingTree.open('child')
 
145
        self.run_bzr('checkout master child')
121
146
        # check that out
122
 
        self.run_bzr('checkout', '--lightweight', 'child', 'checkout')
 
147
        self.run_bzr('checkout --lightweight child checkout')
123
148
        # get an object form of the checkout to manipulate
124
 
        wt = WorkingTree.open('checkout')
 
149
        wt = workingtree.WorkingTree.open('checkout')
125
150
        # change master
126
151
        a_file = file('master/file', 'wt')
127
152
        a_file.write('Foo')
132
157
        a_file = file('child/file_b', 'wt')
133
158
        a_file.write('Foo')
134
159
        a_file.close()
 
160
        # get an object form of child
 
161
        child = workingtree.WorkingTree.open('child')
135
162
        child.add(['file_b'])
136
163
        child_tip = child.commit('add file_b', local=True)
137
164
        # check checkout
142
169
 
143
170
        # now, update checkout ->
144
171
        # get all three files and a pending merge.
145
 
        out, err = self.run_bzr('update', 'checkout')
 
172
        out, err = self.run_bzr('update checkout')
146
173
        self.assertEqual('', out)
147
 
        self.assertContainsRe(err, 'Updated to revision 1.\n'
148
 
                                   'Your local commits will now show as'
149
 
                                   ' pending merges')
 
174
        self.assertEqualDiff("""+N  file_b
 
175
All changes applied successfully.
 
176
+N  file
 
177
All changes applied successfully.
 
178
Updated to revision 2 of branch %s
 
179
Your local commits will now show as pending merges with 'bzr status', and can be committed with 'bzr commit'.
 
180
""" % osutils.pathjoin(self.test_dir, 'master',),
 
181
                         err)
150
182
        self.assertEqual([master_tip, child_tip], wt.get_parent_ids())
151
 
        self.failUnlessExists('checkout/file')
152
 
        self.failUnlessExists('checkout/file_b')
153
 
        self.failUnlessExists('checkout/file_c')
 
183
        self.assertPathExists('checkout/file')
 
184
        self.assertPathExists('checkout/file_b')
 
185
        self.assertPathExists('checkout/file_c')
154
186
        self.assertTrue(wt.has_filename('file_c'))
155
187
 
156
188
    def test_update_with_merges(self):
164
196
 
165
197
        self.build_tree(['checkout1/'])
166
198
        checkout_dir = bzrdir.BzrDirMetaFormat1().initialize('checkout1')
167
 
        branch.BranchReferenceFormat().initialize(checkout_dir, master.branch)
 
199
        branch.BranchReferenceFormat().initialize(checkout_dir,
 
200
            target_branch=master.branch)
168
201
        checkout1 = checkout_dir.create_workingtree('m1')
169
202
 
170
203
        # Create a second branch, with an extra commit
180
213
 
181
214
        # Merge the other branch into checkout
182
215
        os.chdir('checkout1')
183
 
        self.run_bzr('merge', '../other')
 
216
        self.run_bzr('merge ../other')
184
217
 
185
218
        self.assertEqual(['o2'], checkout1.get_parent_ids()[1:])
186
219
 
187
220
        # At this point, 'commit' should fail, because we are out of date
188
221
        self.run_bzr_error(["please run 'bzr update'"],
189
 
                           'commit', '-m', 'merged')
 
222
                           'commit -m merged')
190
223
 
191
224
        # This should not report about local commits being pending
192
225
        # merges, because they were real merges
193
226
        out, err = self.run_bzr('update')
194
227
        self.assertEqual('', out)
195
 
        self.assertEqual('All changes applied successfully.\n'
196
 
                         'Updated to revision 2.\n', err)
197
 
 
 
228
        self.assertEqualDiff('''+N  file3
 
229
All changes applied successfully.
 
230
Updated to revision 2 of branch %s
 
231
''' % osutils.pathjoin(self.test_dir, 'master',),
 
232
                         err)
198
233
        # The pending merges should still be there
199
234
        self.assertEqual(['o2'], checkout1.get_parent_ids()[1:])
200
235
 
205
240
        checkout = readonly_branch.create_checkout('checkout',
206
241
                                                   lightweight=True)
207
242
        tree.commit('empty commit')
208
 
        self.runbzr(['update', 'checkout'])
 
243
        self.run_bzr('update checkout')
 
244
 
 
245
    def test_update_with_merge_merged_to_master(self):
 
246
        # Test that 'bzr update' works correctly when you have
 
247
        # an update in the master tree, and a [lightweight or otherwise]
 
248
        # checkout which has merge a revision merged to master already.
 
249
        master = self.make_branch_and_tree('master')
 
250
        self.build_tree(['master/file'])
 
251
        master.add(['file'])
 
252
        master.commit('one', rev_id='m1')
 
253
 
 
254
        self.build_tree(['checkout1/'])
 
255
        checkout_dir = bzrdir.BzrDirMetaFormat1().initialize('checkout1')
 
256
        branch.BranchReferenceFormat().initialize(checkout_dir,
 
257
            target_branch=master.branch)
 
258
        checkout1 = checkout_dir.create_workingtree('m1')
 
259
 
 
260
        # Create a second branch, with an extra commit
 
261
        other = master.bzrdir.sprout('other').open_workingtree()
 
262
        self.build_tree(['other/file2'])
 
263
        other.add(['file2'])
 
264
        other.commit('other2', rev_id='o2')
 
265
 
 
266
        # Merge the other branch into checkout -  'start reviewing a patch'
 
267
        checkout1.merge_from_branch(other.branch)
 
268
        self.assertEqual(['o2'], checkout1.get_parent_ids()[1:])
 
269
 
 
270
        # Create a new commit in the master branch - 'someone else lands its'
 
271
        master.merge_from_branch(other.branch)
 
272
        master.commit('f3', rev_id='m2')
 
273
 
 
274
        # This should not report about local commits being pending
 
275
        # merges, because they were real merges (but are now gone).
 
276
        # It should perhaps report on them.
 
277
        out, err = self.run_bzr('update', working_dir='checkout1')
 
278
        self.assertEqual('', out)
 
279
        self.assertEqualDiff('''All changes applied successfully.
 
280
Updated to revision 2 of branch %s
 
281
''' % osutils.pathjoin(self.test_dir, 'master',),
 
282
                         err)
 
283
        # The pending merges should still be there
 
284
        self.assertEqual([], checkout1.get_parent_ids()[1:])
 
285
 
 
286
    def test_update_dash_r(self):
 
287
        master = self.make_branch_and_tree('master')
 
288
        os.chdir('master')
 
289
        self.build_tree(['./file1'])
 
290
        master.add(['file1'])
 
291
        master.commit('one', rev_id='m1')
 
292
        self.build_tree(['./file2'])
 
293
        master.add(['file2'])
 
294
        master.commit('two', rev_id='m2')
 
295
 
 
296
        sr = ScriptRunner()
 
297
        sr.run_script(self, '''
 
298
$ bzr update -r 1
 
299
2>-D  file2
 
300
2>All changes applied successfully.
 
301
2>Updated to revision 1 of .../master
 
302
''')
 
303
        self.assertPathExists('./file1')
 
304
        self.assertPathDoesNotExist('./file2')
 
305
        self.assertEquals(['m1'], master.get_parent_ids())
 
306
 
 
307
    def test_update_dash_r_outside_history(self):
 
308
        """Ensure that we can update -r to dotted revisions.
 
309
        """
 
310
        master = self.make_branch_and_tree('master')
 
311
        self.build_tree(['master/file1'])
 
312
        master.add(['file1'])
 
313
        master.commit('one', rev_id='m1')
 
314
 
 
315
        # Create a second branch, with extra commits
 
316
        other = master.bzrdir.sprout('other').open_workingtree()
 
317
        self.build_tree(['other/file2', 'other/file3'])
 
318
        other.add(['file2'])
 
319
        other.commit('other2', rev_id='o2')
 
320
        other.add(['file3'])
 
321
        other.commit('other3', rev_id='o3')
 
322
 
 
323
        os.chdir('master')
 
324
        self.run_bzr('merge ../other')
 
325
        master.commit('merge', rev_id='merge')
 
326
 
 
327
        # Switch to o2. file3 was added only in o3 and should be deleted.
 
328
        out, err = self.run_bzr('update -r revid:o2')
 
329
        self.assertContainsRe(err, '-D\s+file3')
 
330
        self.assertContainsRe(err, 'All changes applied successfully\.')
 
331
        self.assertContainsRe(err, 'Updated to revision 1.1.1 of branch .*')
 
332
 
 
333
        # Switch back to latest
 
334
        out, err = self.run_bzr('update')
 
335
        self.assertContainsRe(err, '\+N\s+file3')
 
336
        self.assertContainsRe(err, 'All changes applied successfully\.')
 
337
        self.assertContainsRe(err, 'Updated to revision 2 of branch .*')
 
338
 
 
339
    def test_update_dash_r_in_master(self):
 
340
        # Test that 'bzr update' works correctly when you have
 
341
        # an update in the master tree,
 
342
        master = self.make_branch_and_tree('master')
 
343
        self.build_tree(['master/file1'])
 
344
        master.add(['file1'])
 
345
        master.commit('one', rev_id='m1')
 
346
 
 
347
        self.run_bzr('checkout master checkout')
 
348
 
 
349
        # add a revision in the master.
 
350
        self.build_tree(['master/file2'])
 
351
        master.add(['file2'])
 
352
        master.commit('two', rev_id='m2')
 
353
 
 
354
        os.chdir('checkout')
 
355
        sr = ScriptRunner()
 
356
        sr.run_script(self, '''
 
357
$ bzr update -r revid:m2
 
358
2>+N  file2
 
359
2>All changes applied successfully.
 
360
2>Updated to revision 2 of branch .../master
 
361
''')
 
362
 
 
363
    def test_update_show_base(self):
 
364
        """bzr update support --show-base
 
365
 
 
366
        see https://bugs.launchpad.net/bzr/+bug/202374"""
 
367
 
 
368
        tree=self.make_branch_and_tree('.')
 
369
 
 
370
        f = open('hello','wt')
 
371
        f.write('foo')
 
372
        f.close()
 
373
        tree.add('hello')
 
374
        tree.commit('fie')
 
375
 
 
376
        f = open('hello','wt')
 
377
        f.write('fee')
 
378
        f.close()
 
379
        tree.commit('fee')
 
380
 
 
381
        #tree.update() gives no such revision, so ...
 
382
        self.run_bzr(['update','-r1'])
 
383
 
 
384
        #create conflict
 
385
        f = open('hello','wt')
 
386
        f.write('fie')
 
387
        f.close()
 
388
 
 
389
        out, err = self.run_bzr(['update','--show-base'],retcode=1)
 
390
 
 
391
        # check for conflict notification
 
392
        self.assertContainsString(err,
 
393
                                  ' M  hello\nText conflict in hello\n1 conflicts encountered.\n')
 
394
        
 
395
        self.assertEqualDiff('<<<<<<< TREE\n'
 
396
                             'fie||||||| BASE-REVISION\n'
 
397
                             'foo=======\n'
 
398
                             'fee>>>>>>> MERGE-SOURCE\n',
 
399
                             open('hello').read())
 
400
 
 
401
    def test_update_checkout_prevent_double_merge(self):
 
402
        """"Launchpad bug 113809 in bzr "update performs two merges"
 
403
        https://launchpad.net/bugs/113809"""
 
404
        master = self.make_branch_and_tree('master')
 
405
        self.build_tree_contents([('master/file', 'initial contents\n')])
 
406
        master.add(['file'])
 
407
        master.commit('one', rev_id='m1')
 
408
 
 
409
        checkout = master.branch.create_checkout('checkout')
 
410
        lightweight = checkout.branch.create_checkout('lightweight',
 
411
                                                      lightweight=True)
 
412
 
 
413
        # time to create a mess
 
414
        # add a commit to the master
 
415
        self.build_tree_contents([('master/file', 'master\n')])
 
416
        master.commit('two', rev_id='m2')
 
417
        self.build_tree_contents([('master/file', 'master local changes\n')])
 
418
 
 
419
        # local commit on the checkout
 
420
        self.build_tree_contents([('checkout/file', 'checkout\n')])
 
421
        checkout.commit('tree', rev_id='c2', local=True)
 
422
        self.build_tree_contents([('checkout/file',
 
423
                                   'checkout local changes\n')])
 
424
 
 
425
        # lightweight 
 
426
        self.build_tree_contents([('lightweight/file',
 
427
                                   'lightweight local changes\n')])
 
428
 
 
429
        # now update (and get conflicts)
 
430
        out, err = self.run_bzr('update lightweight', retcode=1)
 
431
        self.assertEqual('', out)
 
432
        # NB: these conflicts are actually in the source code
 
433
        self.assertFileEqual('''\
 
434
<<<<<<< TREE
 
435
lightweight local changes
 
436
=======
 
437
checkout
 
438
>>>>>>> MERGE-SOURCE
 
439
''',
 
440
                             'lightweight/file')
 
441
 
 
442
        # resolve it
 
443
        self.build_tree_contents([('lightweight/file',
 
444
                                   'lightweight+checkout\n')])
 
445
        self.run_bzr('resolve lightweight/file')
 
446
 
 
447
        # check we get the second conflict
 
448
        out, err = self.run_bzr('update lightweight', retcode=1)
 
449
        self.assertEqual('', out)
 
450
        # NB: these conflicts are actually in the source code
 
451
        self.assertFileEqual('''\
 
452
<<<<<<< TREE
 
453
lightweight+checkout
 
454
=======
 
455
master
 
456
>>>>>>> MERGE-SOURCE
 
457
''',
 
458
                             'lightweight/file')