~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_commit.py

  • Committer: Vincent Ladeuil
  • Date: 2008-09-11 19:36:38 UTC
  • mfrom: (3703 +trunk)
  • mto: (3705.1.1 trunk2)
  • mto: This revision was merged to the branch mainline in revision 3708.
  • Revision ID: v.ladeuil+lp@free.fr-20080911193638-wtjyc1kcmacc6t1f
merge bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2008 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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,
24
27
    )
25
28
from bzrlib.branch import Branch
26
 
from bzrlib.bzrdir import BzrDirMetaFormat1
 
29
from bzrlib.bzrdir import BzrDir, BzrDirMetaFormat1
27
30
from bzrlib.commit import Commit, NullCommitReporter
28
31
from bzrlib.config import BranchConfig
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
from bzrlib.errors import (PointlessCommit, BzrError, SigningFailed, 
 
33
                           LockContention)
 
34
from bzrlib.tests import SymlinkFeature, TestCaseWithTransport
 
35
from bzrlib.workingtree import WorkingTree
43
36
 
44
37
 
45
38
# TODO: Test commit with some added, and added-but-missing files
114
107
        tree2.unlock()
115
108
        self.assertEqual('version 2', text)
116
109
 
117
 
    def test_commit_lossy_native(self):
118
 
        """Attempt a lossy commit to a native branch."""
119
 
        wt = self.make_branch_and_tree('.')
120
 
        b = wt.branch
121
 
        file('hello', 'w').write('hello world')
122
 
        wt.add('hello')
123
 
        revid = wt.commit(message='add hello', rev_id='revid', lossy=True)
124
 
        self.assertEquals('revid', revid)
125
 
 
126
 
    def test_commit_lossy_foreign(self):
127
 
        """Attempt a lossy commit to a foreign branch."""
128
 
        test_foreign.register_dummy_foreign_for_test(self)
129
 
        wt = self.make_branch_and_tree('.',
130
 
            format=test_foreign.DummyForeignVcsDirFormat())
131
 
        b = wt.branch
132
 
        file('hello', 'w').write('hello world')
133
 
        wt.add('hello')
134
 
        revid = wt.commit(message='add hello', lossy=True,
135
 
            timestamp=1302659388, timezone=0)
136
 
        self.assertEquals('dummy-v1:1302659388.0-0-UNKNOWN', revid)
137
 
 
138
 
    def test_commit_bound_lossy_foreign(self):
139
 
        """Attempt a lossy commit to a bzr branch bound to a foreign branch."""
140
 
        test_foreign.register_dummy_foreign_for_test(self)
141
 
        foreign_branch = self.make_branch('foreign',
142
 
            format=test_foreign.DummyForeignVcsDirFormat())
143
 
        wt = foreign_branch.create_checkout("local")
144
 
        b = wt.branch
145
 
        file('local/hello', 'w').write('hello world')
146
 
        wt.add('hello')
147
 
        revid = wt.commit(message='add hello', lossy=True,
148
 
            timestamp=1302659388, timezone=0)
149
 
        self.assertEquals('dummy-v1:1302659388.0-0-0', revid)
150
 
        self.assertEquals('dummy-v1:1302659388.0-0-0',
151
 
            foreign_branch.last_revision())
152
 
        self.assertEquals('dummy-v1:1302659388.0-0-0',
153
 
            wt.branch.last_revision())
154
 
 
155
 
    def test_missing_commit(self):
156
 
        """Test a commit with a missing file"""
 
110
    def test_delete_commit(self):
 
111
        """Test a commit with a deleted file"""
157
112
        wt = self.make_branch_and_tree('.')
158
113
        b = wt.branch
159
114
        file('hello', 'w').write('hello world')
170
125
        """Test a partial commit where a file was renamed but not committed.
171
126
 
172
127
        https://bugs.launchpad.net/bzr/+bug/83039
173
 
 
 
128
        
174
129
        If not handled properly, commit will try to snapshot
175
 
        dialog.py with olive/ as a parent, while
 
130
        dialog.py with olive/ as a parent, while 
176
131
        olive/ has not been snapshotted yet.
177
132
        """
178
133
        wt = self.make_branch_and_tree('.')
199
154
                          message='fails',
200
155
                          allow_pointless=False)
201
156
        self.assertEquals(b.revno(), 1)
202
 
 
 
157
        
203
158
    def test_commit_empty(self):
204
159
        """Commiting an empty tree works."""
205
160
        wt = self.make_branch_and_tree('.')
222
177
              ['hello-id', 'buongia-id'])
223
178
        wt.commit(message='add files',
224
179
                 rev_id='test@rev-1')
225
 
 
 
180
        
226
181
        os.remove('hello')
227
182
        file('buongia', 'w').write('new text')
228
183
        wt.commit(message='update text',
244
199
        self.assertTrue(tree2.has_filename('hello'))
245
200
        self.assertEquals(tree2.get_file_text('hello-id'), 'hello')
246
201
        self.assertEquals(tree2.get_file_text('buongia-id'), 'new text')
247
 
 
 
202
        
248
203
        tree3 = b.repository.revision_tree('test@rev-3')
249
204
        tree3.lock_read()
250
205
        self.addCleanup(tree3.unlock)
269
224
        eq(tree1.id2path('hello-id'), 'hello')
270
225
        eq(tree1.get_file_text('hello-id'), 'contents of hello\n')
271
226
        self.assertFalse(tree1.has_filename('fruity'))
272
 
        self.check_tree_shape(tree1, ['hello'])
273
 
        eq(tree1.get_file_revision('hello-id'), 'test@rev-1')
 
227
        self.check_inventory_shape(tree1.inventory, ['hello'])
 
228
        ie = tree1.inventory['hello-id']
 
229
        eq(ie.revision, 'test@rev-1')
274
230
 
275
231
        tree2 = b.repository.revision_tree('test@rev-2')
276
232
        tree2.lock_read()
277
233
        self.addCleanup(tree2.unlock)
278
234
        eq(tree2.id2path('hello-id'), 'fruity')
279
235
        eq(tree2.get_file_text('hello-id'), 'contents of hello\n')
280
 
        self.check_tree_shape(tree2, ['fruity'])
281
 
        eq(tree2.get_file_revision('hello-id'), 'test@rev-2')
 
236
        self.check_inventory_shape(tree2.inventory, ['fruity'])
 
237
        ie = tree2.inventory['hello-id']
 
238
        eq(ie.revision, 'test@rev-2')
282
239
 
283
240
    def test_reused_rev_id(self):
284
241
        """Test that a revision id cannot be reused in a branch"""
305
262
        wt.commit('two', rev_id=r2, allow_pointless=False)
306
263
        wt.lock_read()
307
264
        try:
308
 
            self.check_tree_shape(wt, ['a/', 'a/hello', 'b/'])
 
265
            self.check_inventory_shape(wt.read_working_inventory(),
 
266
                                       ['a/', 'a/hello', 'b/'])
309
267
        finally:
310
268
            wt.unlock()
311
269
 
314
272
        wt.commit('three', rev_id=r3, allow_pointless=False)
315
273
        wt.lock_read()
316
274
        try:
317
 
            self.check_tree_shape(wt,
 
275
            self.check_inventory_shape(wt.read_working_inventory(),
318
276
                                       ['a/', 'a/hello', 'a/b/'])
319
 
            self.check_tree_shape(b.repository.revision_tree(r3),
 
277
            self.check_inventory_shape(b.repository.get_revision_inventory(r3),
320
278
                                       ['a/', 'a/hello', 'a/b/'])
321
279
        finally:
322
280
            wt.unlock()
326
284
        wt.commit('four', rev_id=r4, allow_pointless=False)
327
285
        wt.lock_read()
328
286
        try:
329
 
            self.check_tree_shape(wt, ['a/', 'a/b/hello', 'a/b/'])
 
287
            self.check_inventory_shape(wt.read_working_inventory(),
 
288
                                       ['a/', 'a/b/hello', 'a/b/'])
330
289
        finally:
331
290
            wt.unlock()
332
291
 
333
 
        inv = b.repository.get_inventory(r4)
 
292
        inv = b.repository.get_revision_inventory(r4)
334
293
        eq(inv['hello-id'].revision, r4)
335
294
        eq(inv['a-id'].revision, r1)
336
295
        eq(inv['b-id'].revision, r3)
364
323
        eq = self.assertEquals
365
324
        eq(b.revision_history(), rev_ids)
366
325
        for i in range(4):
367
 
            self.assertThat(rev_ids[:i+1],
368
 
                MatchesAncestry(b.repository, rev_ids[i]))
 
326
            anc = b.repository.get_ancestry(rev_ids[i])
 
327
            eq(anc, [None] + rev_ids[:i+1])
369
328
 
370
329
    def test_commit_new_subdir_child_selective(self):
371
330
        wt = self.make_branch_and_tree('.')
394
353
    def test_strict_commit_without_unknowns(self):
395
354
        """Try and commit with no unknown files and strict = True,
396
355
        should work."""
 
356
        from bzrlib.errors import StrictCommitFailed
397
357
        wt = self.make_branch_and_tree('.')
398
358
        b = wt.branch
399
359
        file('hello', 'w').write('hello world')
425
385
        wt = self.make_branch_and_tree('.')
426
386
        branch = wt.branch
427
387
        wt.commit("base", allow_pointless=True, rev_id='A')
428
 
        self.assertFalse(branch.repository.has_signature_for_revision_id('A'))
 
388
        self.failIf(branch.repository.has_signature_for_revision_id('A'))
429
389
        try:
430
390
            from bzrlib.testament import Testament
431
391
            # monkey patch gpg signing mechanism
449
409
        wt = self.make_branch_and_tree('.')
450
410
        branch = wt.branch
451
411
        wt.commit("base", allow_pointless=True, rev_id='A')
452
 
        self.assertFalse(branch.repository.has_signature_for_revision_id('A'))
 
412
        self.failIf(branch.repository.has_signature_for_revision_id('A'))
453
413
        try:
 
414
            from bzrlib.testament import Testament
454
415
            # monkey patch gpg signing mechanism
455
416
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.DisabledGPGStrategy
456
417
            config = MustSignConfig(branch)
462
423
                              working_tree=wt)
463
424
            branch = Branch.open(self.get_url('.'))
464
425
            self.assertEqual(branch.revision_history(), ['A'])
465
 
            self.assertFalse(branch.repository.has_revision('B'))
 
426
            self.failIf(branch.repository.has_revision('B'))
466
427
        finally:
467
428
            bzrlib.gpg.GPGStrategy = oldstrategy
468
429
 
523
484
        other_bzrdir = master_branch.bzrdir.sprout('other')
524
485
        other_tree = other_bzrdir.open_workingtree()
525
486
 
526
 
        # do a commit to the other branch changing the content file so
 
487
        # do a commit to the the other branch changing the content file so
527
488
        # that our commit after merging will have a merged revision in the
528
489
        # content file history.
529
490
        self.build_tree_contents([('other/content_file', 'change in other\n')])
540
501
        bound_tree.commit(message='commit of merge in bound tree')
541
502
 
542
503
    def test_commit_reporting_after_merge(self):
543
 
        # when doing a commit of a merge, the reporter needs to still
 
504
        # when doing a commit of a merge, the reporter needs to still 
544
505
        # be called for each item that is added/removed/deleted.
545
506
        this_tree = self.make_branch_and_tree('this')
546
507
        # we need a bunch of files and dirs, to perform one action on each.
589
550
        this_tree.merge_from_branch(other_tree.branch)
590
551
        reporter = CapturingReporter()
591
552
        this_tree.commit('do the commit', reporter=reporter)
592
 
        expected = set([
 
553
        self.assertEqual([
 
554
            ('change', 'unchanged', ''),
 
555
            ('change', 'unchanged', 'dirtoleave'),
 
556
            ('change', 'unchanged', 'filetoleave'),
593
557
            ('change', 'modified', 'filetomodify'),
594
558
            ('change', 'added', 'newdir'),
595
559
            ('change', 'added', 'newfile'),
599
563
            ('renamed', 'renamed', 'filetoreparent', 'renameddir/reparentedfile'),
600
564
            ('deleted', 'dirtoremove'),
601
565
            ('deleted', 'filetoremove'),
602
 
            ])
603
 
        result = set(reporter.calls)
604
 
        missing = expected - result
605
 
        new = result - expected
606
 
        self.assertEqual((set(), set()), (missing, new))
 
566
            ],
 
567
            reporter.calls)
607
568
 
608
569
    def test_commit_removals_respects_filespec(self):
609
570
        """Commit respects the specified_files for removals."""
699
660
    def test_commit_unversioned_specified(self):
700
661
        """Commit should raise if specified files isn't in basis or worktree"""
701
662
        tree = self.make_branch_and_tree('.')
702
 
        self.assertRaises(errors.PathsNotVersionedError, tree.commit,
 
663
        self.assertRaises(errors.PathsNotVersionedError, tree.commit, 
703
664
                          'message', specific_files=['bogus'])
704
665
 
705
666
    class Callback(object):
706
 
 
 
667
        
707
668
        def __init__(self, message, testcase):
708
669
            self.called = False
709
670
            self.message = message
737
698
        """Callback should not be invoked for pointless commit"""
738
699
        tree = self.make_branch_and_tree('.')
739
700
        cb = self.Callback(u'commit 2', self)
740
 
        self.assertRaises(PointlessCommit, tree.commit, message_callback=cb,
 
701
        self.assertRaises(PointlessCommit, tree.commit, message_callback=cb, 
741
702
                          allow_pointless=False)
742
703
        self.assertFalse(cb.called)
743
704
 
747
708
        cb = self.Callback(u'commit 2', self)
748
709
        repository = tree.branch.repository
749
710
        # simulate network failure
750
 
        def raise_(self, arg, arg2, arg3=None, arg4=None):
 
711
        def raise_(self, arg, arg2):
751
712
            raise errors.NoSuchFile('foo')
752
713
        repository.add_inventory = raise_
753
 
        repository.add_inventory_by_delta = raise_
754
714
        self.assertRaises(errors.NoSuchFile, tree.commit, message_callback=cb)
755
715
        self.assertFalse(cb.called)
756
716
 
778
738
        tree.add('a/c/d')
779
739
        tree.rename_one('a/z/x', 'a/c/d/x')
780
740
        tree.commit('test', specific_files=['a/z/y'])
781
 
 
 
741
 
782
742
    def test_commit_no_author(self):
783
743
        """The default kwarg author in MutableTree.commit should not add
784
744
        the 'author' revision property.
787
747
        rev_id = tree.commit('commit 1')
788
748
        rev = tree.branch.repository.get_revision(rev_id)
789
749
        self.assertFalse('author' in rev.properties)
790
 
        self.assertFalse('authors' in rev.properties)
791
750
 
792
751
    def test_commit_author(self):
793
752
        """Passing a non-empty author kwarg to MutableTree.commit should add
794
753
        the 'author' revision property.
795
754
        """
796
755
        tree = self.make_branch_and_tree('foo')
797
 
        rev_id = self.callDeprecated(['The parameter author was '
798
 
                'deprecated in version 1.13. Use authors instead'],
799
 
                tree.commit, 'commit 1', author='John Doe <jdoe@example.com>')
 
756
        rev_id = tree.commit('commit 1', author='John Doe <jdoe@example.com>')
800
757
        rev = tree.branch.repository.get_revision(rev_id)
801
758
        self.assertEqual('John Doe <jdoe@example.com>',
802
 
                         rev.properties['authors'])
803
 
        self.assertFalse('author' in rev.properties)
804
 
 
805
 
    def test_commit_empty_authors_list(self):
806
 
        """Passing an empty list to authors shouldn't add the property."""
807
 
        tree = self.make_branch_and_tree('foo')
808
 
        rev_id = tree.commit('commit 1', authors=[])
809
 
        rev = tree.branch.repository.get_revision(rev_id)
810
 
        self.assertFalse('author' in rev.properties)
811
 
        self.assertFalse('authors' in rev.properties)
812
 
 
813
 
    def test_multiple_authors(self):
814
 
        tree = self.make_branch_and_tree('foo')
815
 
        rev_id = tree.commit('commit 1',
816
 
                authors=['John Doe <jdoe@example.com>',
817
 
                         'Jane Rey <jrey@example.com>'])
818
 
        rev = tree.branch.repository.get_revision(rev_id)
819
 
        self.assertEqual('John Doe <jdoe@example.com>\n'
820
 
                'Jane Rey <jrey@example.com>', rev.properties['authors'])
821
 
        self.assertFalse('author' in rev.properties)
822
 
 
823
 
    def test_author_and_authors_incompatible(self):
824
 
        tree = self.make_branch_and_tree('foo')
825
 
        self.assertRaises(AssertionError, tree.commit, 'commit 1',
826
 
                authors=['John Doe <jdoe@example.com>',
827
 
                         'Jane Rey <jrey@example.com>'],
828
 
                author="Jack Me <jme@example.com>")
829
 
 
830
 
    def test_author_with_newline_rejected(self):
831
 
        tree = self.make_branch_and_tree('foo')
832
 
        self.assertRaises(AssertionError, tree.commit, 'commit 1',
833
 
                authors=['John\nDoe <jdoe@example.com>'])
 
759
                         rev.properties['author'])
834
760
 
835
761
    def test_commit_with_checkout_and_branch_sharing_repo(self):
836
762
        repo = self.make_repository('repo', shared=True)