~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_commit.py

(mbp) tolerate empty limbo and pending-deletion directories (bug 427773)
 (Martin Pool)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2008 Canonical Ltd
 
1
# Copyright (C) 2005-2011 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
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
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
 
18
18
import os
21
21
from bzrlib import (
22
22
    bzrdir,
23
23
    errors,
24
 
    lockdir,
25
 
    osutils,
26
 
    tests,
27
24
    )
28
25
from bzrlib.branch import Branch
29
 
from bzrlib.bzrdir import BzrDir, BzrDirMetaFormat1
 
26
from bzrlib.bzrdir import BzrDirMetaFormat1
30
27
from bzrlib.commit import Commit, NullCommitReporter
31
28
from bzrlib.config import BranchConfig
32
 
from bzrlib.errors import (PointlessCommit, BzrError, SigningFailed,
33
 
                           LockContention)
34
 
from bzrlib.tests import SymlinkFeature, TestCaseWithTransport
35
 
from bzrlib.workingtree import WorkingTree
 
29
from bzrlib.errors import (
 
30
    PointlessCommit,
 
31
    BzrError,
 
32
    SigningFailed,
 
33
    LockContention,
 
34
    )
 
35
from bzrlib.tests import (
 
36
    SymlinkFeature,
 
37
    TestCaseWithTransport,
 
38
    test_foreign,
 
39
    )
 
40
from bzrlib.tests.matchers import MatchesAncestry
36
41
 
37
42
 
38
43
# TODO: Test commit with some added, and added-but-missing files
107
112
        tree2.unlock()
108
113
        self.assertEqual('version 2', text)
109
114
 
110
 
    def test_delete_commit(self):
111
 
        """Test a commit with a deleted file"""
 
115
    def test_commit_lossy_native(self):
 
116
        """Attempt a lossy commit to a native branch."""
 
117
        wt = self.make_branch_and_tree('.')
 
118
        b = wt.branch
 
119
        file('hello', 'w').write('hello world')
 
120
        wt.add('hello')
 
121
        revid = wt.commit(message='add hello', rev_id='revid', lossy=True)
 
122
        self.assertEquals('revid', revid)
 
123
 
 
124
    def test_commit_lossy_foreign(self):
 
125
        """Attempt a lossy commit to a foreign branch."""
 
126
        test_foreign.register_dummy_foreign_for_test(self)
 
127
        wt = self.make_branch_and_tree('.',
 
128
            format=test_foreign.DummyForeignVcsDirFormat())
 
129
        b = wt.branch
 
130
        file('hello', 'w').write('hello world')
 
131
        wt.add('hello')
 
132
        revid = wt.commit(message='add hello', lossy=True,
 
133
            timestamp=1302659388, timezone=0)
 
134
        self.assertEquals('dummy-v1:1302659388.0-0-UNKNOWN', revid)
 
135
 
 
136
    def test_commit_bound_lossy_foreign(self):
 
137
        """Attempt a lossy commit to a bzr branch bound to a foreign branch."""
 
138
        test_foreign.register_dummy_foreign_for_test(self)
 
139
        foreign_branch = self.make_branch('foreign',
 
140
            format=test_foreign.DummyForeignVcsDirFormat())
 
141
        wt = foreign_branch.create_checkout("local")
 
142
        b = wt.branch
 
143
        file('local/hello', 'w').write('hello world')
 
144
        wt.add('hello')
 
145
        revid = wt.commit(message='add hello', lossy=True,
 
146
            timestamp=1302659388, timezone=0)
 
147
        self.assertEquals('dummy-v1:1302659388.0-0-0', revid)
 
148
        self.assertEquals('dummy-v1:1302659388.0-0-0',
 
149
            foreign_branch.last_revision())
 
150
        self.assertEquals('dummy-v1:1302659388.0-0-0',
 
151
            wt.branch.last_revision())
 
152
 
 
153
    def test_missing_commit(self):
 
154
        """Test a commit with a missing file"""
112
155
        wt = self.make_branch_and_tree('.')
113
156
        b = wt.branch
114
157
        file('hello', 'w').write('hello world')
224
267
        eq(tree1.id2path('hello-id'), 'hello')
225
268
        eq(tree1.get_file_text('hello-id'), 'contents of hello\n')
226
269
        self.assertFalse(tree1.has_filename('fruity'))
227
 
        self.check_inventory_shape(tree1.inventory, ['hello'])
228
 
        ie = tree1.inventory['hello-id']
229
 
        eq(ie.revision, 'test@rev-1')
 
270
        self.check_tree_shape(tree1, ['hello'])
 
271
        eq(tree1.get_file_revision('hello-id'), 'test@rev-1')
230
272
 
231
273
        tree2 = b.repository.revision_tree('test@rev-2')
232
274
        tree2.lock_read()
233
275
        self.addCleanup(tree2.unlock)
234
276
        eq(tree2.id2path('hello-id'), 'fruity')
235
277
        eq(tree2.get_file_text('hello-id'), 'contents of hello\n')
236
 
        self.check_inventory_shape(tree2.inventory, ['fruity'])
237
 
        ie = tree2.inventory['hello-id']
238
 
        eq(ie.revision, 'test@rev-2')
 
278
        self.check_tree_shape(tree2, ['fruity'])
 
279
        eq(tree2.get_file_revision('hello-id'), 'test@rev-2')
239
280
 
240
281
    def test_reused_rev_id(self):
241
282
        """Test that a revision id cannot be reused in a branch"""
262
303
        wt.commit('two', rev_id=r2, allow_pointless=False)
263
304
        wt.lock_read()
264
305
        try:
265
 
            self.check_inventory_shape(wt.read_working_inventory(),
266
 
                                       ['a/', 'a/hello', 'b/'])
 
306
            self.check_tree_shape(wt, ['a/', 'a/hello', 'b/'])
267
307
        finally:
268
308
            wt.unlock()
269
309
 
272
312
        wt.commit('three', rev_id=r3, allow_pointless=False)
273
313
        wt.lock_read()
274
314
        try:
275
 
            self.check_inventory_shape(wt.read_working_inventory(),
 
315
            self.check_tree_shape(wt,
276
316
                                       ['a/', 'a/hello', 'a/b/'])
277
 
            self.check_inventory_shape(b.repository.get_revision_inventory(r3),
 
317
            self.check_tree_shape(b.repository.revision_tree(r3),
278
318
                                       ['a/', 'a/hello', 'a/b/'])
279
319
        finally:
280
320
            wt.unlock()
284
324
        wt.commit('four', rev_id=r4, allow_pointless=False)
285
325
        wt.lock_read()
286
326
        try:
287
 
            self.check_inventory_shape(wt.read_working_inventory(),
288
 
                                       ['a/', 'a/b/hello', 'a/b/'])
 
327
            self.check_tree_shape(wt, ['a/', 'a/b/hello', 'a/b/'])
289
328
        finally:
290
329
            wt.unlock()
291
330
 
292
 
        inv = b.repository.get_revision_inventory(r4)
 
331
        inv = b.repository.get_inventory(r4)
293
332
        eq(inv['hello-id'].revision, r4)
294
333
        eq(inv['a-id'].revision, r1)
295
334
        eq(inv['b-id'].revision, r3)
323
362
        eq = self.assertEquals
324
363
        eq(b.revision_history(), rev_ids)
325
364
        for i in range(4):
326
 
            anc = b.repository.get_ancestry(rev_ids[i])
327
 
            eq(anc, [None] + rev_ids[:i+1])
 
365
            self.assertThat(rev_ids[:i+1],
 
366
                MatchesAncestry(b.repository, rev_ids[i]))
328
367
 
329
368
    def test_commit_new_subdir_child_selective(self):
330
369
        wt = self.make_branch_and_tree('.')
353
392
    def test_strict_commit_without_unknowns(self):
354
393
        """Try and commit with no unknown files and strict = True,
355
394
        should work."""
356
 
        from bzrlib.errors import StrictCommitFailed
357
395
        wt = self.make_branch_and_tree('.')
358
396
        b = wt.branch
359
397
        file('hello', 'w').write('hello world')
385
423
        wt = self.make_branch_and_tree('.')
386
424
        branch = wt.branch
387
425
        wt.commit("base", allow_pointless=True, rev_id='A')
388
 
        self.failIf(branch.repository.has_signature_for_revision_id('A'))
 
426
        self.assertFalse(branch.repository.has_signature_for_revision_id('A'))
389
427
        try:
390
428
            from bzrlib.testament import Testament
391
429
            # monkey patch gpg signing mechanism
409
447
        wt = self.make_branch_and_tree('.')
410
448
        branch = wt.branch
411
449
        wt.commit("base", allow_pointless=True, rev_id='A')
412
 
        self.failIf(branch.repository.has_signature_for_revision_id('A'))
 
450
        self.assertFalse(branch.repository.has_signature_for_revision_id('A'))
413
451
        try:
414
 
            from bzrlib.testament import Testament
415
452
            # monkey patch gpg signing mechanism
416
453
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.DisabledGPGStrategy
417
454
            config = MustSignConfig(branch)
423
460
                              working_tree=wt)
424
461
            branch = Branch.open(self.get_url('.'))
425
462
            self.assertEqual(branch.revision_history(), ['A'])
426
 
            self.failIf(branch.repository.has_revision('B'))
 
463
            self.assertFalse(branch.repository.has_revision('B'))
427
464
        finally:
428
465
            bzrlib.gpg.GPGStrategy = oldstrategy
429
466
 
484
521
        other_bzrdir = master_branch.bzrdir.sprout('other')
485
522
        other_tree = other_bzrdir.open_workingtree()
486
523
 
487
 
        # do a commit to the the other branch changing the content file so
 
524
        # do a commit to the other branch changing the content file so
488
525
        # that our commit after merging will have a merged revision in the
489
526
        # content file history.
490
527
        self.build_tree_contents([('other/content_file', 'change in other\n')])
550
587
        this_tree.merge_from_branch(other_tree.branch)
551
588
        reporter = CapturingReporter()
552
589
        this_tree.commit('do the commit', reporter=reporter)
553
 
        self.assertEqual([
554
 
            ('change', 'unchanged', ''),
555
 
            ('change', 'unchanged', 'dirtoleave'),
556
 
            ('change', 'unchanged', 'filetoleave'),
 
590
        expected = set([
557
591
            ('change', 'modified', 'filetomodify'),
558
592
            ('change', 'added', 'newdir'),
559
593
            ('change', 'added', 'newfile'),
563
597
            ('renamed', 'renamed', 'filetoreparent', 'renameddir/reparentedfile'),
564
598
            ('deleted', 'dirtoremove'),
565
599
            ('deleted', 'filetoremove'),
566
 
            ],
567
 
            reporter.calls)
 
600
            ])
 
601
        result = set(reporter.calls)
 
602
        missing = expected - result
 
603
        new = result - expected
 
604
        self.assertEqual((set(), set()), (missing, new))
568
605
 
569
606
    def test_commit_removals_respects_filespec(self):
570
607
        """Commit respects the specified_files for removals."""
708
745
        cb = self.Callback(u'commit 2', self)
709
746
        repository = tree.branch.repository
710
747
        # simulate network failure
711
 
        def raise_(self, arg, arg2):
 
748
        def raise_(self, arg, arg2, arg3=None, arg4=None):
712
749
            raise errors.NoSuchFile('foo')
713
750
        repository.add_inventory = raise_
 
751
        repository.add_inventory_by_delta = raise_
714
752
        self.assertRaises(errors.NoSuchFile, tree.commit, message_callback=cb)
715
753
        self.assertFalse(cb.called)
716
754