~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2006-03-06 00:49:26 UTC
  • mfrom: (1587.1.14 bound-branches)
  • Revision ID: pqm@pqm.ubuntu.com-20060306004926-6d7a10c990bc17d1
Merge in bound branches core support.

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('checkout', '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
        self.check_revno(2)
 
142
 
 
143
        os.chdir('../child')
 
144
        self.check_revno(1)
 
145
        open('b', 'wb').write('new b child contents\n')
 
146
        bzr('commit', '-m', 'child', retcode=3)
 
147
        self.check_revno(1)
 
148
 
 
149
        bzr('update')
 
150
        self.check_revno(2)
 
151
 
 
152
        bzr('commit', '-m', 'child')
 
153
        self.check_revno(3)
 
154
        self.check_revno(3, '../base')
 
155
 
 
156
    def test_double_binding(self):
 
157
        bzr = self.run_bzr
 
158
        self.create_branches()
 
159
 
 
160
        bzr('branch', 'child', 'child2')
 
161
        os.chdir('child2')
 
162
 
 
163
        # Double binding succeeds, but committing to child2 should fail
 
164
        bzr('bind', '../child')
 
165
 
 
166
        bzr('commit', '-m', 'child2', '--unchanged', retcode=3)
 
167
 
 
168
    def test_unbinding(self):
 
169
        bzr = self.run_bzr
 
170
        self.create_branches()
 
171
 
 
172
        os.chdir('base')
 
173
        open('a', 'wb').write('new base contents\n')
 
174
        bzr('commit', '-m', 'base')
 
175
        self.check_revno(2)
 
176
 
 
177
        os.chdir('../child')
 
178
        open('b', 'wb').write('new b child contents\n')
 
179
        self.check_revno(1)
 
180
        bzr('commit', '-m', 'child', retcode=3)
 
181
        self.check_revno(1)
 
182
        bzr('unbind')
 
183
        bzr('commit', '-m', 'child')
 
184
        self.check_revno(2)
 
185
 
 
186
        bzr('bind', retcode=3)
 
187
 
 
188
    def test_commit_remote_bound(self):
 
189
        # It is not possible to commit to a branch
 
190
        # which is bound to a branch which is bound
 
191
        bzr = self.run_bzr
 
192
        self.create_branches()
 
193
        bzr('branch', 'base', 'newbase')
 
194
        os.chdir('base')
 
195
        
 
196
        # There is no way to know that B has already
 
197
        # been bound by someone else, otherwise it
 
198
        # might be nice if this would fail
 
199
        bzr('bind', '../newbase')
 
200
 
 
201
        os.chdir('../child')
 
202
        bzr('commit', '-m', 'failure', '--unchanged', retcode=3)
 
203
 
 
204
    def test_pull_updates_both(self):
 
205
        bzr = self.run_bzr
 
206
        self.create_branches()
 
207
        bzr('branch', 'base', 'newchild')
 
208
        os.chdir('newchild')
 
209
        open('b', 'wb').write('newchild b contents\n')
 
210
        bzr('commit', '-m', 'newchild')
 
211
        self.check_revno(2)
 
212
 
 
213
        os.chdir('../child')
 
214
        # The pull should succeed, and update
 
215
        # the bound parent branch
 
216
        bzr('pull', '../newchild')
 
217
        self.check_revno(2)
 
218
 
 
219
        self.check_revno(2, '../base')
 
220
 
 
221
    def test_bind_diverged(self):
 
222
        bzr = self.run_bzr
 
223
        self.create_branches()
 
224
 
 
225
        os.chdir('child')
 
226
        bzr('unbind')
 
227
 
 
228
        bzr('commit', '-m', 'child', '--unchanged')
 
229
        self.check_revno(2)
 
230
 
 
231
        os.chdir('../base')
 
232
        self.check_revno(1)
 
233
        bzr('commit', '-m', 'base', '--unchanged')
 
234
        self.check_revno(2)
 
235
 
 
236
        os.chdir('../child')
 
237
        # These branches have diverged
 
238
        bzr('bind', '../base', retcode=3)
 
239
 
 
240
        # TODO: In the future, this might require actual changes
 
241
        # to have occurred, rather than just a new revision entry
 
242
        bzr('merge', '../base')
 
243
        bzr('commit', '-m', 'merged')
 
244
        self.check_revno(3)
 
245
 
 
246
        # After a merge, trying to bind again should succeed
 
247
        # by pushing the new change to base
 
248
        bzr('bind', '../base')
 
249
        self.check_revno(3)
 
250
        self.check_revno(3, '../base')
 
251
 
 
252
        # After binding, the revision history should be identical
 
253
        child_rh = bzr('revision-history')[0]
 
254
        os.chdir('../base')
 
255
        base_rh = bzr('revision-history')[0]
 
256
        self.assertEquals(child_rh, base_rh)
 
257
 
 
258
    def test_bind_parent_ahead(self):
 
259
        bzr = self.run_bzr
 
260
        self.create_branches()
 
261
 
 
262
        os.chdir('child')
 
263
        bzr('unbind')
 
264
 
 
265
        os.chdir('../base')
 
266
        bzr('commit', '-m', 'base', '--unchanged')
 
267
 
 
268
        os.chdir('../child')
 
269
        self.check_revno(1)
 
270
        bzr('bind', '../base')
 
271
 
 
272
        self.check_revno(2)
 
273
        bzr('unbind')
 
274
 
 
275
        # Check and make sure it also works if parent is ahead multiple
 
276
        os.chdir('../base')
 
277
        bzr('commit', '-m', 'base 3', '--unchanged')
 
278
        bzr('commit', '-m', 'base 4', '--unchanged')
 
279
        bzr('commit', '-m', 'base 5', '--unchanged')
 
280
        self.check_revno(5)
 
281
 
 
282
        os.chdir('../child')
 
283
        self.check_revno(2)
 
284
        bzr('bind', '../base')
 
285
        self.check_revno(5)
 
286
 
 
287
    def test_bind_child_ahead(self):
 
288
        bzr = self.run_bzr
 
289
        self.create_branches()
 
290
 
 
291
        os.chdir('child')
 
292
        bzr('unbind')
 
293
        bzr('commit', '-m', 'child', '--unchanged')
 
294
        self.check_revno(2)
 
295
        self.check_revno(1, '../base')
 
296
 
 
297
        bzr('bind', '../base')
 
298
        self.check_revno(2, '../base')
 
299
 
 
300
        # Check and make sure it also works if child is ahead multiple
 
301
        bzr('unbind')
 
302
        bzr('commit', '-m', 'child 3', '--unchanged')
 
303
        bzr('commit', '-m', 'child 4', '--unchanged')
 
304
        bzr('commit', '-m', 'child 5', '--unchanged')
 
305
        self.check_revno(5)
 
306
 
 
307
        self.check_revno(2, '../base')
 
308
        bzr('bind', '../base')
 
309
        self.check_revno(5, '../base')
 
310
 
 
311
    def test_commit_after_merge(self):
 
312
        bzr = self.run_bzr
 
313
        self.create_branches()
 
314
 
 
315
        # We want merge to be able to be a local only
 
316
        # operation, because it can be without violating
 
317
        # the binding invariants.
 
318
        # But we can't fail afterwards
 
319
 
 
320
        bzr('branch', 'child', 'other')
 
321
 
 
322
        os.chdir('other')
 
323
        open('c', 'wb').write('file c\n')
 
324
        bzr('add', 'c')
 
325
        bzr('commit', '-m', 'adding c')
 
326
        new_rev_id = bzr('revision-history')[0].strip().split('\n')[-1]
 
327
 
 
328
        os.chdir('../child')
 
329
        bzr('merge', '../other')
 
330
 
 
331
        self.failUnlessExists('c')
 
332
        tree = WorkingTree.open('.')
 
333
        self.assertEqual([new_rev_id], tree.pending_merges())
 
334
 
 
335
        # Make sure the local branch has the installed revision
 
336
        bzr('cat-revision', new_rev_id)
 
337
        
 
338
        # And make sure that the base tree does not
 
339
        os.chdir('../base')
 
340
        bzr('cat-revision', new_rev_id, retcode=3)
 
341
 
 
342
        # Commit should succeed, and cause merged revisions to
 
343
        # be pulled into base
 
344
        os.chdir('../child')
 
345
        bzr('commit', '-m', 'merge other')
 
346
 
 
347
        self.check_revno(2)
 
348
 
 
349
        os.chdir('../base')
 
350
        self.check_revno(2)
 
351
 
 
352
        bzr('cat-revision', new_rev_id)
 
353
 
 
354
    def test_pull_overwrite_fails(self):
 
355
        bzr = self.run_bzr
 
356
        self.create_branches()
 
357
 
 
358
        bzr('branch', 'child', 'other')
 
359
        
 
360
        os.chdir('other')
 
361
        open('a', 'wb').write('new contents\n')
 
362
        bzr('commit', '-m', 'changed a')
 
363
        self.check_revno(2)
 
364
        open('a', 'ab').write('and then some\n')
 
365
        bzr('commit', '-m', 'another a')
 
366
        self.check_revno(3)
 
367
        open('a', 'ab').write('and some more\n')
 
368
        bzr('commit', '-m', 'yet another a')
 
369
        self.check_revno(4)
 
370
 
 
371
        os.chdir('../child')
 
372
        open('a', 'wb').write('also changed a\n')
 
373
        bzr('commit', '-m', 'child modified a')
 
374
 
 
375
        self.check_revno(2)
 
376
        self.check_revno(2, '../base')
 
377
 
 
378
        # It might be possible that we want pull --overwrite to
 
379
        # actually succeed.
 
380
        # If we want it, just change this test to make sure that 
 
381
        # both base and child are updated properly
 
382
        bzr('pull', '--overwrite', '../other', retcode=3)
 
383
 
 
384
        # It should fail without changing the local revision
 
385
        self.check_revno(2)
 
386
        self.check_revno(2, '../base')
 
387
 
 
388
    # TODO: jam 20051230 Test that commit & pull fail when the branch we 
 
389
    #       are bound to is not available
 
390
 
 
391