~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Robert Collins
  • Date: 2006-03-04 13:03:57 UTC
  • mfrom: (1505.1.30 bzr-bound-branch)
  • mto: This revision was merged to the branch mainline in revision 1590.
  • Revision ID: robertc@robertcollins.net-20060304130357-95990a95920f57bb
Update bound branch implementation to 0.8.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005 by Canonical Ltd
 
2
 
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
 
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
 
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
 
 
17
 
 
18
"""Tests of bound branches (binding, unbinding, commit, etc) command.
 
19
"""
 
20
 
 
21
import os
 
22
from cStringIO import StringIO
 
23
 
 
24
from bzrlib.tests import TestCaseWithTransport
 
25
from bzrlib.branch import Branch
 
26
from bzrlib.bzrdir import (BzrDir,
 
27
                           BzrDirFormat,
 
28
                           BzrDirFormat6,
 
29
                           BzrDirMetaFormat1,
 
30
                           )
 
31
from bzrlib.workingtree import WorkingTree
 
32
 
 
33
 
 
34
class TestLegacyFormats(TestCaseWithTransport):
 
35
    
 
36
    def setUp(self):
 
37
        super(TestLegacyFormats, self).setUp()
 
38
        self.build_tree(['master/', 'child/'])
 
39
        self.run_bzr('init', 'master')
 
40
        old_format = BzrDirFormat.get_default_format()
 
41
        BzrDirFormat.set_default_format(BzrDirFormat6())
 
42
        try:
 
43
            self.run_bzr('init', 'child')
 
44
        finally:
 
45
            BzrDirFormat.set_default_format(old_format)
 
46
        os.chdir('child')
 
47
    
 
48
    def test_bind_format_6_bzrdir(self):
 
49
        # bind on a format 6 bzrdir should error
 
50
        out,err = self.run_bzr('bind', '../master', retcode=3)
 
51
        self.assertEqual('', out)
 
52
        self.assertEqual('bzr: ERROR: To use this feature you must '
 
53
                         'upgrade your branch at %s/.\n' % os.getcwdu(), err)
 
54
    
 
55
    def test_unbind_format_6_bzrdir(self):
 
56
        # bind on a format 6 bzrdir should error
 
57
        out,err = self.run_bzr('unbind', retcode=3)
 
58
        self.assertEqual('', out)
 
59
        self.assertEqual('bzr: ERROR: To use this feature you must '
 
60
                         'upgrade your branch at %s/.\n' % os.getcwdu(), err)
 
61
 
 
62
 
 
63
class TestBoundBranches(TestCaseWithTransport):
 
64
 
 
65
    def create_branches(self):
 
66
        bzr = self.run_bzr
 
67
        self.build_tree(['base/', 'base/a', 'base/b'])
 
68
 
 
69
        self.init_meta_branch('base')
 
70
        os.chdir('base')
 
71
        bzr('add')
 
72
        bzr('commit', '-m', 'init')
 
73
 
 
74
        os.chdir('..')
 
75
 
 
76
        bzr('get', '--bound', 'base', 'child')
 
77
 
 
78
        self.failUnlessExists('child')
 
79
 
 
80
        self.check_revno(1, 'child')
 
81
        d = BzrDir.open('child')
 
82
        self.assertNotEqual(None, d.open_branch().get_master_branch())
 
83
 
 
84
    def check_revno(self, val, loc=None):
 
85
        if loc is not None:
 
86
            cwd = os.getcwd()
 
87
            os.chdir(loc)
 
88
        self.assertEquals(str(val), self.run_bzr('revno')[0].strip())
 
89
        if loc is not None:
 
90
            os.chdir(cwd)
 
91
 
 
92
    def test_simple_binding(self):
 
93
        self.build_tree(['base/', 'base/a', 'base/b'])
 
94
 
 
95
        self.init_meta_branch('base')
 
96
        self.run_bzr('add', 'base')
 
97
        self.run_bzr('commit', '-m', 'init', 'base')
 
98
 
 
99
        self.run_bzr('branch', 'base', 'child')
 
100
 
 
101
        os.chdir('child')
 
102
        self.run_bzr('bind', '../base')
 
103
 
 
104
        d = BzrDir.open('')
 
105
        self.assertNotEqual(None, d.open_branch().get_master_branch())
 
106
 
 
107
        self.run_bzr('unbind')
 
108
        self.assertEqual(None, d.open_branch().get_master_branch())
 
109
 
 
110
        self.run_bzr('unbind', retcode=3)
 
111
 
 
112
    def init_meta_branch(self, path):
 
113
        old_format = BzrDirFormat.get_default_format()
 
114
        BzrDirFormat.set_default_format(BzrDirMetaFormat1())
 
115
        try:
 
116
            self.run_bzr('init', path)
 
117
        finally:
 
118
            BzrDirFormat.set_default_format(old_format)
 
119
 
 
120
    def test_bound_commit(self):
 
121
        bzr = self.run_bzr
 
122
        self.create_branches()
 
123
 
 
124
        os.chdir('child')
 
125
        open('a', 'wb').write('new contents\n')
 
126
        bzr('commit', '-m', 'child')
 
127
 
 
128
        self.check_revno(2)
 
129
 
 
130
        # Make sure it committed on the parent
 
131
        self.check_revno(2, '../base')
 
132
 
 
133
    def test_bound_fail(self):
 
134
        # Make sure commit fails if out of date.
 
135
        bzr = self.run_bzr
 
136
        self.create_branches()
 
137
 
 
138
        os.chdir('base')
 
139
        open('a', 'wb').write('new base contents\n')
 
140
        bzr('commit', '-m', 'base')
 
141
 
 
142
        os.chdir('../child')
 
143
        open('b', 'wb').write('new b child contents\n')
 
144
        bzr('commit', '-m', 'child', retcode=3)
 
145
 
 
146
        bzr('update')
 
147
        self.check_revno(2)
 
148
 
 
149
        bzr('commit', '-m', 'child')
 
150
        self.check_revno(3)
 
151
        self.check_revno(3, '../base')
 
152
 
 
153
    def test_double_binding(self):
 
154
        bzr = self.run_bzr
 
155
        self.create_branches()
 
156
 
 
157
        bzr('branch', 'child', 'child2')
 
158
        os.chdir('child2')
 
159
 
 
160
        # Double binding succeeds, but committing to child2 should fail
 
161
        bzr('bind', '../child')
 
162
 
 
163
        bzr('commit', '-m', 'child2', '--unchanged', retcode=3)
 
164
 
 
165
    def test_unbinding(self):
 
166
        bzr = self.run_bzr
 
167
        self.create_branches()
 
168
 
 
169
        os.chdir('base')
 
170
        open('a', 'wb').write('new base contents\n')
 
171
        bzr('commit', '-m', 'base')
 
172
        self.check_revno(2)
 
173
 
 
174
        os.chdir('../child')
 
175
        open('b', 'wb').write('new b child contents\n')
 
176
        self.check_revno(1)
 
177
        bzr('commit', '-m', 'child', retcode=3)
 
178
        self.check_revno(1)
 
179
        bzr('unbind')
 
180
        bzr('commit', '-m', 'child')
 
181
        self.check_revno(2)
 
182
 
 
183
        bzr('bind', retcode=3)
 
184
 
 
185
    def test_commit_remote_bound(self):
 
186
        # It is not possible to commit to a branch
 
187
        # which is bound to a branch which is bound
 
188
        bzr = self.run_bzr
 
189
        self.create_branches()
 
190
        bzr('branch', 'base', 'newbase')
 
191
        os.chdir('base')
 
192
        
 
193
        # There is no way to know that B has already
 
194
        # been bound by someone else, otherwise it
 
195
        # might be nice if this would fail
 
196
        bzr('bind', '../newbase')
 
197
 
 
198
        os.chdir('../child')
 
199
        bzr('commit', '-m', 'failure', '--unchanged', retcode=3)
 
200
 
 
201
    def test_pull_updates_both(self):
 
202
        bzr = self.run_bzr
 
203
        self.create_branches()
 
204
        bzr('branch', 'base', 'newchild')
 
205
        os.chdir('newchild')
 
206
        open('b', 'wb').write('newchild b contents\n')
 
207
        bzr('commit', '-m', 'newchild')
 
208
        self.check_revno(2)
 
209
 
 
210
        os.chdir('../child')
 
211
        # The pull should succeed, and update
 
212
        # the bound parent branch
 
213
        bzr('pull', '../newchild')
 
214
        self.check_revno(2)
 
215
 
 
216
        self.check_revno(2, '../base')
 
217
 
 
218
    def test_bind_diverged(self):
 
219
        bzr = self.run_bzr
 
220
        self.create_branches()
 
221
 
 
222
        os.chdir('child')
 
223
        bzr('unbind')
 
224
 
 
225
        bzr('commit', '-m', 'child', '--unchanged')
 
226
        self.check_revno(2)
 
227
 
 
228
        os.chdir('../base')
 
229
        self.check_revno(1)
 
230
        bzr('commit', '-m', 'base', '--unchanged')
 
231
        self.check_revno(2)
 
232
 
 
233
        os.chdir('../child')
 
234
        # These branches have diverged
 
235
        bzr('bind', '../base', retcode=3)
 
236
 
 
237
        # TODO: In the future, this might require actual changes
 
238
        # to have occurred, rather than just a new revision entry
 
239
        bzr('merge', '../base')
 
240
        bzr('commit', '-m', 'merged')
 
241
        self.check_revno(3)
 
242
 
 
243
        # After a merge, trying to bind again should succeed
 
244
        # by pushing the new change to base
 
245
        bzr('bind', '../base')
 
246
        self.check_revno(3)
 
247
        self.check_revno(3, '../base')
 
248
 
 
249
        # After binding, the revision history should be identical
 
250
        child_rh = bzr('revision-history')[0]
 
251
        os.chdir('../base')
 
252
        base_rh = bzr('revision-history')[0]
 
253
        self.assertEquals(child_rh, base_rh)
 
254
 
 
255
    def test_bind_parent_ahead(self):
 
256
        bzr = self.run_bzr
 
257
        self.create_branches()
 
258
 
 
259
        os.chdir('child')
 
260
        bzr('unbind')
 
261
 
 
262
        os.chdir('../base')
 
263
        bzr('commit', '-m', 'base', '--unchanged')
 
264
 
 
265
        os.chdir('../child')
 
266
        self.check_revno(1)
 
267
        bzr('bind', '../base')
 
268
 
 
269
        self.check_revno(2)
 
270
        bzr('unbind')
 
271
 
 
272
        # Check and make sure it also works if parent is ahead multiple
 
273
        os.chdir('../base')
 
274
        bzr('commit', '-m', 'base 3', '--unchanged')
 
275
        bzr('commit', '-m', 'base 4', '--unchanged')
 
276
        bzr('commit', '-m', 'base 5', '--unchanged')
 
277
        self.check_revno(5)
 
278
 
 
279
        os.chdir('../child')
 
280
        self.check_revno(2)
 
281
        bzr('bind')
 
282
        self.check_revno(5)
 
283
 
 
284
    def test_bind_child_ahead(self):
 
285
        bzr = self.run_bzr
 
286
        self.create_branches()
 
287
 
 
288
        os.chdir('child')
 
289
        bzr('unbind')
 
290
        bzr('commit', '-m', 'child', '--unchanged')
 
291
        self.check_revno(2)
 
292
        self.check_revno(1, '../base')
 
293
 
 
294
        bzr('bind', '../base')
 
295
        self.check_revno(2, '../base')
 
296
 
 
297
        # Check and make sure it also works if child is ahead multiple
 
298
        bzr('unbind')
 
299
        bzr('commit', '-m', 'child 3', '--unchanged')
 
300
        bzr('commit', '-m', 'child 4', '--unchanged')
 
301
        bzr('commit', '-m', 'child 5', '--unchanged')
 
302
        self.check_revno(5)
 
303
 
 
304
        self.check_revno(2, '../base')
 
305
        bzr('bind')
 
306
        self.check_revno(5, '../base')
 
307
 
 
308
    def test_commit_after_merge(self):
 
309
        bzr = self.run_bzr
 
310
        self.create_branches()
 
311
 
 
312
        # We want merge to be able to be a local only
 
313
        # operation, because it can be without violating
 
314
        # the binding invariants.
 
315
        # But we can't fail afterwards
 
316
 
 
317
        bzr('branch', 'child', 'other')
 
318
 
 
319
        os.chdir('other')
 
320
        open('c', 'wb').write('file c\n')
 
321
        bzr('add', 'c')
 
322
        bzr('commit', '-m', 'adding c')
 
323
        new_rev_id = bzr('revision-history')[0].strip().split('\n')[-1]
 
324
 
 
325
        os.chdir('../child')
 
326
        bzr('merge', '../other')
 
327
 
 
328
        self.failUnlessExists('c')
 
329
        tree = WorkingTree.open('.')
 
330
        self.assertEqual([new_rev_id], tree.pending_merges())
 
331
 
 
332
        # Make sure the local branch has the installed revision
 
333
        bzr('cat-revision', new_rev_id)
 
334
        
 
335
        # And make sure that the base tree does not
 
336
        os.chdir('../base')
 
337
        bzr('cat-revision', new_rev_id, retcode=3)
 
338
 
 
339
        # Commit should succeed, and cause merged revisions to
 
340
        # be pulled into base
 
341
        os.chdir('../child')
 
342
        bzr('commit', '-m', 'merge other')
 
343
 
 
344
        self.check_revno(2)
 
345
 
 
346
        os.chdir('../base')
 
347
        self.check_revno(2)
 
348
 
 
349
        bzr('cat-revision', new_rev_id)
 
350
 
 
351
    def test_pull_overwrite_fails(self):
 
352
        bzr = self.run_bzr
 
353
        self.create_branches()
 
354
 
 
355
        bzr('branch', 'child', 'other')
 
356
        
 
357
        os.chdir('other')
 
358
        open('a', 'wb').write('new contents\n')
 
359
        bzr('commit', '-m', 'changed a')
 
360
        self.check_revno(2)
 
361
        open('a', 'ab').write('and then some\n')
 
362
        bzr('commit', '-m', 'another a')
 
363
        self.check_revno(3)
 
364
        open('a', 'ab').write('and some more\n')
 
365
        bzr('commit', '-m', 'yet another a')
 
366
        self.check_revno(4)
 
367
 
 
368
        os.chdir('../child')
 
369
        open('a', 'wb').write('also changed a\n')
 
370
        bzr('commit', '-m', 'child modified a')
 
371
 
 
372
        self.check_revno(2)
 
373
        self.check_revno(2, '../base')
 
374
 
 
375
        # It might be possible that we want pull --overwrite to
 
376
        # actually succeed.
 
377
        # If we want it, just change this test to make sure that 
 
378
        # both base and child are updated properly
 
379
        bzr('pull', '--overwrite', '../other', retcode=3)
 
380
 
 
381
        # It should fail without changing the local revision
 
382
        self.check_revno(2)
 
383
        self.check_revno(2, '../base')
 
384
 
 
385
    # TODO: jam 20051230 Test that commit & pull fail when the branch we 
 
386
    #       are bound to is not available
 
387
 
 
388