~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Aaron Bentley
  • Date: 2007-08-20 13:07:12 UTC
  • mfrom: (2732 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2733.
  • Revision ID: abentley@panoramicfeedback.com-20070820130712-buopmg528zcgwyxc
Merge bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
 
23
23
from bzrlib import (
24
24
    bzrdir,
 
25
    errors
25
26
    )
26
27
from bzrlib.branch import Branch
27
28
from bzrlib.bzrdir import (BzrDir, BzrDirFormat, BzrDirMetaFormat1)
36
37
    def setUp(self):
37
38
        super(TestLegacyFormats, self).setUp()
38
39
        self.build_tree(['master/', 'child/'])
39
 
        self.run_bzr('init master')
40
 
        self.run_bzr('init --format=weave child')
 
40
        self.make_branch_and_tree('master')
 
41
        self.make_branch_and_tree('child',
 
42
                        format=bzrdir.format_registry.make_bzrdir('weave'))
41
43
        os.chdir('child')
42
44
    
43
45
    def test_bind_format_6_bzrdir(self):
62
64
class TestBoundBranches(TestCaseWithTransport):
63
65
 
64
66
    def create_branches(self):
65
 
        bzr = self.run_bzr
66
67
        self.build_tree(['base/', 'base/a', 'base/b'])
67
68
 
68
69
        branch = self.init_meta_branch('base')
69
 
        tree = branch.bzrdir.open_workingtree()
70
 
        tree.lock_write()
71
 
        tree.add(['a', 'b'])
72
 
        tree.commit('init')
73
 
        tree.unlock()
 
70
        base_tree = branch.bzrdir.open_workingtree()
 
71
        base_tree.lock_write()
 
72
        base_tree.add(['a', 'b'])
 
73
        base_tree.commit('init')
 
74
        base_tree.unlock()
74
75
 
75
 
        self.run_bzr('checkout base child')
 
76
        child_tree = branch.create_checkout('child')
76
77
 
77
78
        self.check_revno(1, 'child')
78
79
        d = BzrDir.open('child')
79
80
        self.assertNotEqual(None, d.open_branch().get_master_branch())
80
81
 
 
82
        return base_tree, child_tree
 
83
 
81
84
    def check_revno(self, val, loc='.'):
82
85
        self.assertEqual(
83
86
            val, len(BzrDir.open(loc).open_branch().revision_history()))
85
88
    def test_simple_binding(self):
86
89
        self.build_tree(['base/', 'base/a', 'base/b'])
87
90
 
88
 
        self.init_meta_branch('base')
89
 
        self.run_bzr('add base')
90
 
        self.run_bzr('commit -m init base')
 
91
        branch = self.init_meta_branch('base')
 
92
        tree = branch.bzrdir.open_workingtree()
 
93
        tree.add('a', 'b')
 
94
        tree.commit(message='init')
91
95
 
92
 
        self.run_bzr('branch base child')
 
96
        tree.bzrdir.sprout('child')
93
97
 
94
98
        os.chdir('child')
95
99
        self.run_bzr('bind ../base')
132
136
        return BzrDir.create_branch_convenience(path, format=format)
133
137
 
134
138
    def test_bound_commit(self):
135
 
        bzr = self.run_bzr
136
 
        self.create_branches()
137
 
 
138
 
        os.chdir('child')
139
 
        open('a', 'wb').write('new contents\n')
140
 
        bzr('commit -m child')
141
 
 
142
 
        self.check_revno(2)
 
139
        child_tree = self.create_branches()[1]
 
140
 
 
141
        self.build_tree_contents([('child/a', 'new contents')])
 
142
        child_tree.commit(message='child')
 
143
 
 
144
        self.check_revno(2, 'child')
143
145
 
144
146
        # Make sure it committed on the parent
145
 
        self.check_revno(2, '../base')
 
147
        self.check_revno(2, 'base')
146
148
 
147
149
    def test_bound_fail(self):
148
150
        # Make sure commit fails if out of date.
149
 
        bzr = self.run_bzr
150
 
        self.create_branches()
151
 
 
152
 
        os.chdir('base')
153
 
        open('a', 'wb').write('new base contents\n')
154
 
        bzr('commit -m base')
155
 
        self.check_revno(2)
156
 
 
157
 
        os.chdir('../child')
158
 
        self.check_revno(1)
159
 
        open('b', 'wb').write('new b child contents\n')
160
 
        bzr('commit -m child', retcode=3)
161
 
        self.check_revno(1)
162
 
 
163
 
        bzr('update')
164
 
        self.check_revno(2)
165
 
 
166
 
        bzr('commit -m child')
167
 
        self.check_revno(3)
168
 
        self.check_revno(3, '../base')
 
151
        base_tree, child_tree = self.create_branches()
 
152
 
 
153
        self.build_tree_contents([
 
154
            ('base/a',  'new base contents\n'   ),
 
155
            ('child/b', 'new b child contents\n')])
 
156
        base_tree.commit(message='base')
 
157
        self.check_revno(2, 'base')
 
158
 
 
159
        self.check_revno(1, 'child')
 
160
        self.assertRaises(errors.BoundBranchOutOfDate, child_tree.commit,
 
161
                                                            message='child')
 
162
        self.check_revno(1, 'child')
 
163
 
 
164
        child_tree.update()
 
165
        self.check_revno(2, 'child')
 
166
 
 
167
        child_tree.commit(message='child')
 
168
        self.check_revno(3, 'child')
 
169
        self.check_revno(3, 'base')
169
170
 
170
171
    def test_double_binding(self):
171
 
        bzr = self.run_bzr
172
 
        self.create_branches()
173
 
 
174
 
        bzr('branch child child2')
 
172
        child_tree = self.create_branches()[1]
 
173
 
 
174
        child2_tree = child_tree.bzrdir.sprout('child2').open_workingtree()
 
175
 
175
176
        os.chdir('child2')
176
 
 
177
177
        # Double binding succeeds, but committing to child2 should fail
178
 
        bzr('bind ../child')
 
178
        self.run_bzr('bind ../child')
179
179
 
180
 
        bzr('commit -m child2 --unchanged', retcode=3)
 
180
        self.assertRaises(errors.CommitToDoubleBoundBranch,
 
181
                child2_tree.commit, message='child2', allow_pointless=True)
181
182
 
182
183
    def test_unbinding(self):
183
 
        bzr = self.run_bzr
184
 
        self.create_branches()
185
 
 
186
 
        os.chdir('base')
187
 
        open('a', 'wb').write('new base contents\n')
188
 
        bzr('commit -m base')
189
 
        self.check_revno(2)
190
 
 
191
 
        os.chdir('../child')
192
 
        open('b', 'wb').write('new b child contents\n')
193
 
        self.check_revno(1)
194
 
        bzr('commit -m child', retcode=3)
195
 
        self.check_revno(1)
196
 
        bzr('unbind')
197
 
        bzr('commit -m child')
198
 
        self.check_revno(2)
199
 
 
200
 
        bzr('bind', retcode=3)
 
184
        base_tree, child_tree = self.create_branches()
 
185
 
 
186
        self.build_tree_contents([
 
187
            ('base/a',  'new base contents\n'   ),
 
188
            ('child/b', 'new b child contents\n')])
 
189
 
 
190
        base_tree.commit(message='base')
 
191
        self.check_revno(2, 'base')
 
192
 
 
193
        self.check_revno(1, 'child')
 
194
        os.chdir('child')
 
195
        self.run_bzr("commit -m child", retcode=3)
 
196
        self.check_revno(1)
 
197
        self.run_bzr('unbind')
 
198
        child_tree.commit(message='child')
 
199
        self.check_revno(2)
 
200
 
 
201
        self.run_bzr('bind', retcode=3)
201
202
 
202
203
    def test_commit_remote_bound(self):
203
204
        # It is not possible to commit to a branch
204
205
        # which is bound to a branch which is bound
205
 
        bzr = self.run_bzr
206
 
        self.create_branches()
207
 
        bzr('branch base newbase')
 
206
        base_tree, child_tree = self.create_branches()
 
207
        base_tree.bzrdir.sprout('newbase')
 
208
 
208
209
        os.chdir('base')
209
 
        
210
210
        # There is no way to know that B has already
211
211
        # been bound by someone else, otherwise it
212
212
        # might be nice if this would fail
213
 
        bzr('bind ../newbase')
 
213
        self.run_bzr('bind ../newbase')
214
214
 
215
215
        os.chdir('../child')
216
 
        bzr('commit -m failure --unchanged', retcode=3)
 
216
        self.run_bzr('commit -m failure --unchanged', retcode=3)
217
217
 
218
218
    def test_pull_updates_both(self):
219
 
        bzr = self.run_bzr
220
 
        self.create_branches()
221
 
        bzr('branch base newchild')
222
 
        os.chdir('newchild')
223
 
        open('b', 'wb').write('newchild b contents\n')
224
 
        bzr('commit -m newchild')
225
 
        self.check_revno(2)
 
219
        base_tree = self.create_branches()[0]
 
220
        newchild_tree = base_tree.bzrdir.sprout('newchild').open_workingtree()
 
221
        self.build_tree_contents([('newchild/b', 'newchild b contents\n')])
 
222
        newchild_tree.commit(message='newchild')
 
223
        self.check_revno(2, 'newchild')
226
224
 
227
 
        os.chdir('../child')
 
225
        os.chdir('child')
228
226
        # The pull should succeed, and update
229
227
        # the bound parent branch
230
 
        bzr('pull ../newchild')
 
228
        self.run_bzr('pull ../newchild')
231
229
        self.check_revno(2)
232
230
 
233
231
        self.check_revno(2, '../base')
234
232
 
235
233
    def test_bind_diverged(self):
236
 
        bzr = self.run_bzr
237
 
        self.create_branches()
238
 
 
239
 
        os.chdir('child')
240
 
        bzr('unbind')
241
 
 
242
 
        bzr('commit -m child --unchanged')
243
 
        self.check_revno(2)
244
 
 
245
 
        os.chdir('../base')
246
 
        self.check_revno(1)
247
 
        bzr('commit -m base --unchanged')
248
 
        self.check_revno(2)
249
 
 
250
 
        os.chdir('../child')
 
234
        base_tree, child_tree = self.create_branches()
 
235
        base_branch = base_tree.branch
 
236
        child_branch = child_tree.branch
 
237
 
 
238
        os.chdir('child')
 
239
        self.run_bzr('unbind')
 
240
 
 
241
        child_tree.commit(message='child', allow_pointless=True)
 
242
        self.check_revno(2)
 
243
 
 
244
        os.chdir('..')
 
245
        self.check_revno(1, 'base')
 
246
        base_tree.commit(message='base', allow_pointless=True)
 
247
        self.check_revno(2, 'base')
 
248
 
 
249
        os.chdir('child')
251
250
        # These branches have diverged
252
 
        bzr('bind ../base', retcode=3)
 
251
        self.run_bzr('bind ../base', retcode=3)
253
252
 
254
253
        # TODO: In the future, this might require actual changes
255
254
        # to have occurred, rather than just a new revision entry
256
 
        bzr('merge ../base')
257
 
        bzr('commit -m merged')
 
255
        child_tree.merge_from_branch(base_branch)
 
256
        child_tree.commit(message='merged')
258
257
        self.check_revno(3)
259
258
 
260
259
        # After binding, the revision history should be unaltered
261
 
        base_branch = Branch.open('../base')
262
 
        child_branch = Branch.open('.')
263
260
        # take a copy before
264
261
        base_history = base_branch.revision_history()
265
262
        child_history = child_branch.revision_history()
266
263
 
267
264
        # After a merge, trying to bind again should succeed
268
265
        # keeping the new change as a local commit.
269
 
        bzr('bind ../base')
 
266
        self.run_bzr('bind ../base')
270
267
        self.check_revno(3)
271
268
        self.check_revno(2, '../base')
272
269
 
275
272
        self.assertEqual(child_history, child_branch.revision_history())
276
273
 
277
274
    def test_bind_parent_ahead(self):
278
 
        bzr = self.run_bzr
279
 
        self.create_branches()
 
275
        base_tree = self.create_branches()[0]
280
276
 
281
277
        os.chdir('child')
282
 
        bzr('unbind')
283
 
 
284
 
        os.chdir('../base')
285
 
        bzr('commit -m base --unchanged')
286
 
 
287
 
        os.chdir('../child')
 
278
        self.run_bzr('unbind')
 
279
 
 
280
        base_tree.commit(message='base', allow_pointless=True)
 
281
 
288
282
        self.check_revno(1)
289
 
        bzr('bind ../base')
 
283
        self.run_bzr('bind ../base')
290
284
 
291
285
        # binding does not pull data:
292
286
        self.check_revno(1)
293
 
        bzr('unbind')
 
287
        self.run_bzr('unbind')
294
288
 
295
289
        # Check and make sure it also works if parent is ahead multiple
296
 
        os.chdir('../base')
297
 
        bzr(['commit', '-m', 'base 3', '--unchanged'])
298
 
        bzr(['commit', '-m', 'base 4', '--unchanged'])
299
 
        bzr(['commit', '-m', 'base 5', '--unchanged'])
300
 
        self.check_revno(5)
 
290
        base_tree.commit(message='base 3', allow_pointless=True)
 
291
        base_tree.commit(message='base 4', allow_pointless=True)
 
292
        base_tree.commit(message='base 5', allow_pointless=True)
 
293
        self.check_revno(5, '../base')
301
294
 
302
 
        os.chdir('../child')
303
295
        self.check_revno(1)
304
 
        bzr('bind ../base')
 
296
        self.run_bzr('bind ../base')
305
297
        self.check_revno(1)
306
298
 
307
299
    def test_bind_child_ahead(self):
308
300
        # test binding when the master branches history is a prefix of the 
309
301
        # childs - it should bind ok but the revision histories should not
310
302
        # be altered
311
 
        bzr = self.run_bzr
312
 
        self.create_branches()
 
303
        child_tree = self.create_branches()[1]
313
304
 
314
305
        os.chdir('child')
315
 
        bzr('unbind')
316
 
        bzr('commit -m child --unchanged')
 
306
        self.run_bzr('unbind')
 
307
        child_tree.commit(message='child', allow_pointless=True)
317
308
        self.check_revno(2)
318
309
        self.check_revno(1, '../base')
319
310
 
320
 
        bzr('bind ../base')
 
311
        self.run_bzr('bind ../base')
321
312
        self.check_revno(1, '../base')
322
313
 
323
314
        # Check and make sure it also works if child is ahead multiple
324
 
        bzr('unbind')
325
 
        bzr(['commit', '-m', 'child 3', '--unchanged'])
326
 
        bzr(['commit', '-m', 'child 4', '--unchanged'])
327
 
        bzr(['commit', '-m', 'child 5', '--unchanged'])
 
315
        self.run_bzr('unbind')
 
316
        child_tree.commit(message='child 3', allow_pointless=True)
 
317
        child_tree.commit(message='child 4', allow_pointless=True)
 
318
        child_tree.commit(message='child 5', allow_pointless=True)
328
319
        self.check_revno(5)
329
320
 
330
321
        self.check_revno(1, '../base')
331
 
        bzr('bind ../base')
 
322
        self.run_bzr('bind ../base')
332
323
        self.check_revno(1, '../base')
333
324
 
334
325
    def test_commit_after_merge(self):
335
 
        bzr = self.run_bzr
336
 
        self.create_branches()
 
326
        base_tree, child_tree = self.create_branches()
337
327
 
338
328
        # We want merge to be able to be a local only
339
329
        # operation, because it can be without violating
340
330
        # the binding invariants.
341
331
        # But we can't fail afterwards
342
 
 
343
 
        bzr('branch child other')
344
 
 
345
 
        os.chdir('other')
346
 
        open('c', 'wb').write('file c\n')
347
 
        bzr('add c')
348
 
        bzr(['commit', '-m', 'adding c'])
349
 
        new_rev_id = bzr('revision-history')[0].strip().split('\n')[-1]
350
 
 
351
 
        os.chdir('../child')
352
 
        bzr('merge ../other')
353
 
 
354
 
        self.failUnlessExists('c')
355
 
        tree = WorkingTree.open('.') # opens child
356
 
        self.assertEqual([new_rev_id], tree.get_parent_ids()[1:])
 
332
        other_tree = child_tree.bzrdir.sprout('other').open_workingtree()
 
333
        other_branch = other_tree.branch
 
334
 
 
335
        self.build_tree_contents([('other/c', 'file c\n')])
 
336
        other_tree.add('c')
 
337
        other_tree.commit(message='adding c')
 
338
        new_rev_id = other_branch.revision_history()[-1]
 
339
 
 
340
        child_tree.merge_from_branch(other_branch)
 
341
 
 
342
        self.failUnlessExists('child/c')
 
343
        self.assertEqual([new_rev_id], child_tree.get_parent_ids()[1:])
357
344
 
358
345
        # Make sure the local branch has the installed revision
359
 
        bzr(['cat-revision', new_rev_id])
360
 
        
 
346
        self.assertTrue(child_tree.branch.repository.has_revision(new_rev_id))
 
347
 
361
348
        # And make sure that the base tree does not
362
 
        os.chdir('../base')
363
 
        bzr(['cat-revision', new_rev_id], retcode=3)
 
349
        self.assertFalse(base_tree.branch.repository.has_revision(new_rev_id))
364
350
 
365
351
        # Commit should succeed, and cause merged revisions to
366
352
        # be pulled into base
367
 
        os.chdir('../child')
368
 
        bzr(['commit', '-m', 'merge other'])
369
 
 
370
 
        self.check_revno(2)
371
 
 
372
 
        os.chdir('../base')
373
 
        self.check_revno(2)
374
 
 
375
 
        bzr(['cat-revision', new_rev_id])
 
353
        os.chdir('child')
 
354
        self.run_bzr(['commit', '-m', 'merge other'])
 
355
 
 
356
        self.check_revno(2)
 
357
 
 
358
        self.check_revno(2, '../base')
 
359
 
 
360
        self.assertTrue(base_tree.branch.repository.has_revision(new_rev_id))
376
361
 
377
362
    def test_pull_overwrite(self):
378
363
        # XXX: This test should be moved to branch-implemenations/test_pull
379
 
        bzr = self.run_bzr
380
 
        self.create_branches()
381
 
 
382
 
        bzr('branch child other')
383
 
        
384
 
        os.chdir('other')
385
 
        open('a', 'wb').write('new contents\n')
386
 
        bzr(['commit', '-m', 'changed a'])
387
 
        self.check_revno(2)
388
 
        open('a', 'ab').write('and then some\n')
389
 
        bzr(['commit', '-m', 'another a'])
390
 
        self.check_revno(3)
391
 
        open('a', 'ab').write('and some more\n')
392
 
        bzr(['commit', '-m', 'yet another a'])
393
 
        self.check_revno(4)
394
 
 
395
 
        os.chdir('../child')
396
 
        open('a', 'wb').write('also changed a\n')
397
 
        bzr(['commit', '-m', 'child modified a'])
398
 
 
399
 
        self.check_revno(2)
400
 
        self.check_revno(2, '../base')
401
 
 
402
 
        bzr('pull --overwrite ../other')
 
364
        child_tree = self.create_branches()[1]
 
365
 
 
366
        other_tree = child_tree.bzrdir.sprout('other').open_workingtree()
 
367
 
 
368
        self.build_tree_contents([('other/a', 'new contents\n')])
 
369
        other_tree.commit(message='changed a')
 
370
        self.check_revno(2, 'other')
 
371
        self.build_tree_contents([
 
372
            ('other/a', 'new contents\nand then some\n')])
 
373
        other_tree.commit(message='another a')
 
374
        self.check_revno(3, 'other')
 
375
        self.build_tree_contents([
 
376
            ('other/a', 'new contents\nand then some\nand some more\n')])
 
377
        other_tree.commit('yet another a')
 
378
        self.check_revno(4, 'other')
 
379
 
 
380
        self.build_tree_contents([('child/a', 'also changed a\n')])
 
381
        child_tree.commit(message='child modified a')
 
382
 
 
383
        self.check_revno(2, 'child')
 
384
        self.check_revno(2, 'base')
 
385
 
 
386
        os.chdir('child')
 
387
        self.run_bzr('pull --overwrite ../other')
403
388
 
404
389
        # both the local and master should have been updated.
405
390
        self.check_revno(4)