~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_commit.py

  • Committer: Vincent Ladeuil
  • Date: 2012-02-14 17:22:37 UTC
  • mfrom: (6466 +trunk)
  • mto: This revision was merged to the branch mainline in revision 6468.
  • Revision ID: v.ladeuil+lp@free.fr-20120214172237-7dv7er3n4uy8d5m4
Merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
import bzrlib
21
21
from bzrlib import (
22
22
    bzrdir,
 
23
    config,
23
24
    errors,
24
25
    )
25
26
from bzrlib.branch import Branch
26
27
from bzrlib.bzrdir import BzrDirMetaFormat1
27
28
from bzrlib.commit import Commit, NullCommitReporter
28
 
from bzrlib.config import BranchConfig
29
 
from bzrlib.errors import (PointlessCommit, BzrError, SigningFailed,
30
 
                           LockContention)
31
 
from bzrlib.tests import SymlinkFeature, TestCaseWithTransport
 
29
from bzrlib.errors import (
 
30
    PointlessCommit,
 
31
    BzrError,
 
32
    SigningFailed,
 
33
    LockContention,
 
34
    )
 
35
from bzrlib.tests import (
 
36
    TestCaseWithTransport,
 
37
    test_foreign,
 
38
    )
 
39
from bzrlib.tests.features import (
 
40
    SymlinkFeature,
 
41
    )
 
42
from bzrlib.tests.matchers import MatchesAncestry
32
43
 
33
44
 
34
45
# TODO: Test commit with some added, and added-but-missing files
35
46
 
36
 
class MustSignConfig(BranchConfig):
37
 
 
38
 
    def signature_needed(self):
39
 
        return True
40
 
 
41
 
    def gpg_signing_command(self):
42
 
        return ['cat', '-']
43
 
 
44
 
 
45
 
class BranchWithHooks(BranchConfig):
46
 
 
47
 
    def post_commit(self):
48
 
        return "bzrlib.ahook bzrlib.ahook"
 
47
class MustSignConfig(config.MemoryStack):
 
48
 
 
49
    def __init__(self):
 
50
        super(MustSignConfig, self).__init__('''
 
51
gpg_signing_command=cat -
 
52
create_signatures=always
 
53
''')
49
54
 
50
55
 
51
56
class CapturingReporter(NullCommitReporter):
77
82
        """Commit and check two versions of a single file."""
78
83
        wt = self.make_branch_and_tree('.')
79
84
        b = wt.branch
80
 
        file('hello', 'w').write('hello world')
 
85
        with file('hello', 'w') as f: f.write('hello world')
81
86
        wt.add('hello')
82
 
        wt.commit(message='add hello')
 
87
        rev1 = wt.commit(message='add hello')
83
88
        file_id = wt.path2id('hello')
84
89
 
85
 
        file('hello', 'w').write('version 2')
86
 
        wt.commit(message='commit 2')
 
90
        with file('hello', 'w') as f: f.write('version 2')
 
91
        rev2 = wt.commit(message='commit 2')
87
92
 
88
93
        eq = self.assertEquals
89
94
        eq(b.revno(), 2)
90
 
        rh = b.revision_history()
91
 
        rev = b.repository.get_revision(rh[0])
 
95
        rev = b.repository.get_revision(rev1)
92
96
        eq(rev.message, 'add hello')
93
97
 
94
 
        tree1 = b.repository.revision_tree(rh[0])
 
98
        tree1 = b.repository.revision_tree(rev1)
95
99
        tree1.lock_read()
96
100
        text = tree1.get_file_text(file_id)
97
101
        tree1.unlock()
98
102
        self.assertEqual('hello world', text)
99
103
 
100
 
        tree2 = b.repository.revision_tree(rh[1])
 
104
        tree2 = b.repository.revision_tree(rev2)
101
105
        tree2.lock_read()
102
106
        text = tree2.get_file_text(file_id)
103
107
        tree2.unlock()
104
108
        self.assertEqual('version 2', text)
105
109
 
 
110
    def test_commit_lossy_native(self):
 
111
        """Attempt a lossy commit to a native branch."""
 
112
        wt = self.make_branch_and_tree('.')
 
113
        b = wt.branch
 
114
        with file('hello', 'w') as f: f.write('hello world')
 
115
        wt.add('hello')
 
116
        revid = wt.commit(message='add hello', rev_id='revid', lossy=True)
 
117
        self.assertEquals('revid', revid)
 
118
 
 
119
    def test_commit_lossy_foreign(self):
 
120
        """Attempt a lossy commit to a foreign branch."""
 
121
        test_foreign.register_dummy_foreign_for_test(self)
 
122
        wt = self.make_branch_and_tree('.',
 
123
            format=test_foreign.DummyForeignVcsDirFormat())
 
124
        b = wt.branch
 
125
        with file('hello', 'w') as f: f.write('hello world')
 
126
        wt.add('hello')
 
127
        revid = wt.commit(message='add hello', lossy=True,
 
128
            timestamp=1302659388, timezone=0)
 
129
        self.assertEquals('dummy-v1:1302659388.0-0-UNKNOWN', revid)
 
130
 
 
131
    def test_commit_bound_lossy_foreign(self):
 
132
        """Attempt a lossy commit to a bzr branch bound to a foreign branch."""
 
133
        test_foreign.register_dummy_foreign_for_test(self)
 
134
        foreign_branch = self.make_branch('foreign',
 
135
            format=test_foreign.DummyForeignVcsDirFormat())
 
136
        wt = foreign_branch.create_checkout("local")
 
137
        b = wt.branch
 
138
        with file('local/hello', 'w') as f: f.write('hello world')
 
139
        wt.add('hello')
 
140
        revid = wt.commit(message='add hello', lossy=True,
 
141
            timestamp=1302659388, timezone=0)
 
142
        self.assertEquals('dummy-v1:1302659388.0-0-0', revid)
 
143
        self.assertEquals('dummy-v1:1302659388.0-0-0',
 
144
            foreign_branch.last_revision())
 
145
        self.assertEquals('dummy-v1:1302659388.0-0-0',
 
146
            wt.branch.last_revision())
 
147
 
106
148
    def test_missing_commit(self):
107
149
        """Test a commit with a missing file"""
108
150
        wt = self.make_branch_and_tree('.')
109
151
        b = wt.branch
110
 
        file('hello', 'w').write('hello world')
 
152
        with file('hello', 'w') as f: f.write('hello world')
111
153
        wt.add(['hello'], ['hello-id'])
112
154
        wt.commit(message='add hello')
113
155
 
114
156
        os.remove('hello')
115
 
        wt.commit('removed hello', rev_id='rev2')
 
157
        reporter = CapturingReporter()
 
158
        wt.commit('removed hello', rev_id='rev2', reporter=reporter)
 
159
        self.assertEquals(
 
160
            [('missing', u'hello'), ('deleted', u'hello')],
 
161
            reporter.calls)
116
162
 
117
163
        tree = b.repository.revision_tree('rev2')
118
164
        self.assertFalse(tree.has_id('hello-id'))
141
187
        """Commit refuses unless there are changes or it's forced."""
142
188
        wt = self.make_branch_and_tree('.')
143
189
        b = wt.branch
144
 
        file('hello', 'w').write('hello')
 
190
        with file('hello', 'w') as f: f.write('hello')
145
191
        wt.add(['hello'])
146
192
        wt.commit(message='add hello')
147
193
        self.assertEquals(b.revno(), 1)
167
213
        """Selective commit in tree with deletions"""
168
214
        wt = self.make_branch_and_tree('.')
169
215
        b = wt.branch
170
 
        file('hello', 'w').write('hello')
171
 
        file('buongia', 'w').write('buongia')
 
216
        with file('hello', 'w') as f: f.write('hello')
 
217
        with file('buongia', 'w') as f: f.write('buongia')
172
218
        wt.add(['hello', 'buongia'],
173
219
              ['hello-id', 'buongia-id'])
174
220
        wt.commit(message='add files',
175
221
                 rev_id='test@rev-1')
176
222
 
177
223
        os.remove('hello')
178
 
        file('buongia', 'w').write('new text')
 
224
        with file('buongia', 'w') as f: f.write('new text')
179
225
        wt.commit(message='update text',
180
226
                 specific_files=['buongia'],
181
227
                 allow_pointless=False,
220
266
        eq(tree1.id2path('hello-id'), 'hello')
221
267
        eq(tree1.get_file_text('hello-id'), 'contents of hello\n')
222
268
        self.assertFalse(tree1.has_filename('fruity'))
223
 
        self.check_inventory_shape(tree1.inventory, ['hello'])
224
 
        ie = tree1.inventory['hello-id']
225
 
        eq(ie.revision, 'test@rev-1')
 
269
        self.check_tree_shape(tree1, ['hello'])
 
270
        eq(tree1.get_file_revision('hello-id'), 'test@rev-1')
226
271
 
227
272
        tree2 = b.repository.revision_tree('test@rev-2')
228
273
        tree2.lock_read()
229
274
        self.addCleanup(tree2.unlock)
230
275
        eq(tree2.id2path('hello-id'), 'fruity')
231
276
        eq(tree2.get_file_text('hello-id'), 'contents of hello\n')
232
 
        self.check_inventory_shape(tree2.inventory, ['fruity'])
233
 
        ie = tree2.inventory['hello-id']
234
 
        eq(ie.revision, 'test@rev-2')
 
277
        self.check_tree_shape(tree2, ['fruity'])
 
278
        eq(tree2.get_file_revision('hello-id'), 'test@rev-2')
235
279
 
236
280
    def test_reused_rev_id(self):
237
281
        """Test that a revision id cannot be reused in a branch"""
258
302
        wt.commit('two', rev_id=r2, allow_pointless=False)
259
303
        wt.lock_read()
260
304
        try:
261
 
            self.check_inventory_shape(wt.read_working_inventory(),
262
 
                                       ['a/', 'a/hello', 'b/'])
 
305
            self.check_tree_shape(wt, ['a/', 'a/hello', 'b/'])
263
306
        finally:
264
307
            wt.unlock()
265
308
 
268
311
        wt.commit('three', rev_id=r3, allow_pointless=False)
269
312
        wt.lock_read()
270
313
        try:
271
 
            self.check_inventory_shape(wt.read_working_inventory(),
 
314
            self.check_tree_shape(wt,
272
315
                                       ['a/', 'a/hello', 'a/b/'])
273
 
            self.check_inventory_shape(b.repository.get_inventory(r3),
 
316
            self.check_tree_shape(b.repository.revision_tree(r3),
274
317
                                       ['a/', 'a/hello', 'a/b/'])
275
318
        finally:
276
319
            wt.unlock()
280
323
        wt.commit('four', rev_id=r4, allow_pointless=False)
281
324
        wt.lock_read()
282
325
        try:
283
 
            self.check_inventory_shape(wt.read_working_inventory(),
284
 
                                       ['a/', 'a/b/hello', 'a/b/'])
 
326
            self.check_tree_shape(wt, ['a/', 'a/b/hello', 'a/b/'])
285
327
        finally:
286
328
            wt.unlock()
287
329
 
294
336
        """Commit with a removed file"""
295
337
        wt = self.make_branch_and_tree('.')
296
338
        b = wt.branch
297
 
        file('hello', 'w').write('hello world')
 
339
        with file('hello', 'w') as f: f.write('hello world')
298
340
        wt.add(['hello'], ['hello-id'])
299
341
        wt.commit(message='add hello')
300
342
        wt.remove('hello')
309
351
        b = wt.branch
310
352
        rev_ids = []
311
353
        for i in range(4):
312
 
            file('hello', 'w').write((str(i) * 4) + '\n')
 
354
            with file('hello', 'w') as f: f.write((str(i) * 4) + '\n')
313
355
            if i == 0:
314
356
                wt.add(['hello'], ['hello-id'])
315
357
            rev_id = 'test@rev-%d' % (i+1)
316
358
            rev_ids.append(rev_id)
317
359
            wt.commit(message='rev %d' % (i+1),
318
360
                     rev_id=rev_id)
319
 
        eq = self.assertEquals
320
 
        eq(b.revision_history(), rev_ids)
321
361
        for i in range(4):
322
 
            anc = b.repository.get_ancestry(rev_ids[i])
323
 
            eq(anc, [None] + rev_ids[:i+1])
 
362
            self.assertThat(rev_ids[:i+1],
 
363
                MatchesAncestry(b.repository, rev_ids[i]))
324
364
 
325
365
    def test_commit_new_subdir_child_selective(self):
326
366
        wt = self.make_branch_and_tree('.')
340
380
        from bzrlib.errors import StrictCommitFailed
341
381
        wt = self.make_branch_and_tree('.')
342
382
        b = wt.branch
343
 
        file('hello', 'w').write('hello world')
 
383
        with file('hello', 'w') as f: f.write('hello world')
344
384
        wt.add('hello')
345
 
        file('goodbye', 'w').write('goodbye cruel world!')
 
385
        with file('goodbye', 'w') as f: f.write('goodbye cruel world!')
346
386
        self.assertRaises(StrictCommitFailed, wt.commit,
347
387
            message='add hello but not goodbye', strict=True)
348
388
 
349
389
    def test_strict_commit_without_unknowns(self):
350
390
        """Try and commit with no unknown files and strict = True,
351
391
        should work."""
352
 
        from bzrlib.errors import StrictCommitFailed
353
392
        wt = self.make_branch_and_tree('.')
354
393
        b = wt.branch
355
 
        file('hello', 'w').write('hello world')
 
394
        with file('hello', 'w') as f: f.write('hello world')
356
395
        wt.add('hello')
357
396
        wt.commit(message='add hello', strict=True)
358
397
 
360
399
        """Try and commit with unknown files and strict = False, should work."""
361
400
        wt = self.make_branch_and_tree('.')
362
401
        b = wt.branch
363
 
        file('hello', 'w').write('hello world')
 
402
        with file('hello', 'w') as f: f.write('hello world')
364
403
        wt.add('hello')
365
 
        file('goodbye', 'w').write('goodbye cruel world!')
 
404
        with file('goodbye', 'w') as f: f.write('goodbye cruel world!')
366
405
        wt.commit(message='add hello but not goodbye', strict=False)
367
406
 
368
407
    def test_nonstrict_commit_without_unknowns(self):
370
409
        should work."""
371
410
        wt = self.make_branch_and_tree('.')
372
411
        b = wt.branch
373
 
        file('hello', 'w').write('hello world')
 
412
        with file('hello', 'w') as f: f.write('hello world')
374
413
        wt.add('hello')
375
414
        wt.commit(message='add hello', strict=False)
376
415
 
381
420
        wt = self.make_branch_and_tree('.')
382
421
        branch = wt.branch
383
422
        wt.commit("base", allow_pointless=True, rev_id='A')
384
 
        self.failIf(branch.repository.has_signature_for_revision_id('A'))
 
423
        self.assertFalse(branch.repository.has_signature_for_revision_id('A'))
385
424
        try:
386
425
            from bzrlib.testament import Testament
387
426
            # monkey patch gpg signing mechanism
388
427
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.LoopbackGPGStrategy
389
 
            commit.Commit(config=MustSignConfig(branch)).commit(message="base",
390
 
                                                      allow_pointless=True,
391
 
                                                      rev_id='B',
392
 
                                                      working_tree=wt)
 
428
            conf = config.MemoryStack('''
 
429
gpg_signing_command=cat -
 
430
create_signatures=always
 
431
''')
 
432
            commit.Commit(config_stack=conf).commit(
 
433
                message="base", allow_pointless=True, rev_id='B',
 
434
                working_tree=wt)
393
435
            def sign(text):
394
436
                return bzrlib.gpg.LoopbackGPGStrategy(None).sign(text)
395
437
            self.assertEqual(sign(Testament.from_revision(branch.repository,
396
 
                             'B').as_short_text()),
 
438
                                                          'B').as_short_text()),
397
439
                             branch.repository.get_signature_text('B'))
398
440
        finally:
399
441
            bzrlib.gpg.GPGStrategy = oldstrategy
405
447
        wt = self.make_branch_and_tree('.')
406
448
        branch = wt.branch
407
449
        wt.commit("base", allow_pointless=True, rev_id='A')
408
 
        self.failIf(branch.repository.has_signature_for_revision_id('A'))
 
450
        self.assertFalse(branch.repository.has_signature_for_revision_id('A'))
409
451
        try:
410
 
            from bzrlib.testament import Testament
411
452
            # monkey patch gpg signing mechanism
412
453
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.DisabledGPGStrategy
413
 
            config = MustSignConfig(branch)
 
454
            conf = config.MemoryStack('''
 
455
gpg_signing_command=cat -
 
456
create_signatures=always
 
457
''')
414
458
            self.assertRaises(SigningFailed,
415
 
                              commit.Commit(config=config).commit,
 
459
                              commit.Commit(config_stack=conf).commit,
416
460
                              message="base",
417
461
                              allow_pointless=True,
418
462
                              rev_id='B',
419
463
                              working_tree=wt)
420
464
            branch = Branch.open(self.get_url('.'))
421
 
            self.assertEqual(branch.revision_history(), ['A'])
422
 
            self.failIf(branch.repository.has_revision('B'))
 
465
            self.assertEqual(branch.last_revision(), 'A')
 
466
            self.assertFalse(branch.repository.has_revision('B'))
423
467
        finally:
424
468
            bzrlib.gpg.GPGStrategy = oldstrategy
425
469
 
432
476
            calls.append('called')
433
477
        bzrlib.ahook = called
434
478
        try:
435
 
            config = BranchWithHooks(branch)
436
 
            commit.Commit(config=config).commit(
437
 
                            message = "base",
438
 
                            allow_pointless=True,
439
 
                            rev_id='A', working_tree = wt)
 
479
            conf = config.MemoryStack('post_commit=bzrlib.ahook bzrlib.ahook')
 
480
            commit.Commit(config_stack=conf).commit(
 
481
                message = "base", allow_pointless=True, rev_id='A',
 
482
                working_tree = wt)
440
483
            self.assertEqual(['called', 'called'], calls)
441
484
        finally:
442
485
            del bzrlib.ahook