86
96
eq(rev.message, 'add hello')
88
98
tree1 = b.repository.revision_tree(rh[0])
89
100
text = tree1.get_file_text(file_id)
90
eq(text, 'hello world')
102
self.assertEqual('hello world', text)
92
104
tree2 = b.repository.revision_tree(rh[1])
93
eq(tree2.get_file_text(file_id), 'version 2')
95
def test_delete_commit(self):
96
"""Test a commit with a deleted file"""
106
text = tree2.get_file_text(file_id)
108
self.assertEqual('version 2', text)
110
def test_commit_lossy_native(self):
111
"""Attempt a lossy commit to a native branch."""
112
wt = self.make_branch_and_tree('.')
114
file('hello', 'w').write('hello world')
116
revid = wt.commit(message='add hello', rev_id='revid', lossy=True)
117
self.assertEquals('revid', revid)
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())
125
file('hello', 'w').write('hello world')
127
revid = wt.commit(message='add hello', lossy=True,
128
timestamp=1302659388, timezone=0)
129
self.assertEquals('dummy-v1:1302659388.0-0-UNKNOWN', revid)
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")
138
file('local/hello', 'w').write('hello world')
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())
148
def test_missing_commit(self):
149
"""Test a commit with a missing file"""
97
150
wt = self.make_branch_and_tree('.')
99
152
file('hello', 'w').write('hello world')
217
296
wt.move(['hello'], 'a')
218
297
r2 = 'test@rev-2'
219
298
wt.commit('two', rev_id=r2, allow_pointless=False)
220
self.check_inventory_shape(wt.read_working_inventory(),
221
['a', 'a/hello', 'b'])
301
self.check_tree_shape(wt, ['a/', 'a/hello', 'b/'])
223
305
wt.move(['b'], 'a')
224
306
r3 = 'test@rev-3'
225
307
wt.commit('three', rev_id=r3, allow_pointless=False)
226
self.check_inventory_shape(wt.read_working_inventory(),
227
['a', 'a/hello', 'a/b'])
228
self.check_inventory_shape(b.repository.get_revision_inventory(r3),
229
['a', 'a/hello', 'a/b'])
310
self.check_tree_shape(wt,
311
['a/', 'a/hello', 'a/b/'])
312
self.check_tree_shape(b.repository.revision_tree(r3),
313
['a/', 'a/hello', 'a/b/'])
231
317
wt.move(['a/hello'], 'a/b')
232
318
r4 = 'test@rev-4'
233
319
wt.commit('four', rev_id=r4, allow_pointless=False)
234
self.check_inventory_shape(wt.read_working_inventory(),
235
['a', 'a/b/hello', 'a/b'])
322
self.check_tree_shape(wt, ['a/', 'a/b/hello', 'a/b/'])
237
inv = b.repository.get_revision_inventory(r4)
326
inv = b.repository.get_inventory(r4)
238
327
eq(inv['hello-id'].revision, r4)
239
328
eq(inv['a-id'].revision, r1)
240
329
eq(inv['b-id'].revision, r3)
242
331
def test_removed_commit(self):
243
332
"""Commit with a removed file"""
244
333
wt = self.make_branch_and_tree('.')
490
579
other_tree.commit('modify all sample files and dirs.')
492
581
other_tree.unlock()
493
self.merge(other_tree.branch, this_tree)
582
this_tree.merge_from_branch(other_tree.branch)
494
583
reporter = CapturingReporter()
495
584
this_tree.commit('do the commit', reporter=reporter)
497
('change', 'unchanged', ''),
498
('change', 'unchanged', 'dirtoleave'),
499
('change', 'unchanged', 'filetoleave'),
500
586
('change', 'modified', 'filetomodify'),
501
587
('change', 'added', 'newdir'),
502
588
('change', 'added', 'newfile'),
503
589
('renamed', 'renamed', 'dirtorename', 'renameddir'),
590
('renamed', 'renamed', 'filetorename', 'renamedfile'),
504
591
('renamed', 'renamed', 'dirtoreparent', 'renameddir/reparenteddir'),
505
592
('renamed', 'renamed', 'filetoreparent', 'renameddir/reparentedfile'),
506
('renamed', 'renamed', 'filetorename', 'renamedfile'),
507
593
('deleted', 'dirtoremove'),
508
594
('deleted', 'filetoremove'),
596
result = set(reporter.calls)
597
missing = expected - result
598
new = result - expected
599
self.assertEqual((set(), set()), (missing, new))
512
601
def test_commit_removals_respects_filespec(self):
513
602
"""Commit respects the specified_files for removals."""
543
636
timestamp = rev.timestamp
544
637
timestamp_1ms = round(timestamp, 3)
545
638
self.assertEqual(timestamp_1ms, timestamp)
640
def assertBasisTreeKind(self, kind, tree, file_id):
641
basis = tree.basis_tree()
644
self.assertEqual(kind, basis.kind(file_id))
648
def test_commit_kind_changes(self):
649
self.requireFeature(SymlinkFeature)
650
tree = self.make_branch_and_tree('.')
651
os.symlink('target', 'name')
652
tree.add('name', 'a-file-id')
653
tree.commit('Added a symlink')
654
self.assertBasisTreeKind('symlink', tree, 'a-file-id')
657
self.build_tree(['name'])
658
tree.commit('Changed symlink to file')
659
self.assertBasisTreeKind('file', tree, 'a-file-id')
662
os.symlink('target', 'name')
663
tree.commit('file to symlink')
664
self.assertBasisTreeKind('symlink', tree, 'a-file-id')
668
tree.commit('symlink to directory')
669
self.assertBasisTreeKind('directory', tree, 'a-file-id')
672
os.symlink('target', 'name')
673
tree.commit('directory to symlink')
674
self.assertBasisTreeKind('symlink', tree, 'a-file-id')
676
# prepare for directory <-> file tests
679
tree.commit('symlink to directory')
680
self.assertBasisTreeKind('directory', tree, 'a-file-id')
683
self.build_tree(['name'])
684
tree.commit('Changed directory to file')
685
self.assertBasisTreeKind('file', tree, 'a-file-id')
689
tree.commit('file to directory')
690
self.assertBasisTreeKind('directory', tree, 'a-file-id')
692
def test_commit_unversioned_specified(self):
693
"""Commit should raise if specified files isn't in basis or worktree"""
694
tree = self.make_branch_and_tree('.')
695
self.assertRaises(errors.PathsNotVersionedError, tree.commit,
696
'message', specific_files=['bogus'])
698
class Callback(object):
700
def __init__(self, message, testcase):
702
self.message = message
703
self.testcase = testcase
705
def __call__(self, commit_obj):
707
self.testcase.assertTrue(isinstance(commit_obj, Commit))
710
def test_commit_callback(self):
711
"""Commit should invoke a callback to get the message"""
713
tree = self.make_branch_and_tree('.')
717
self.assertTrue(isinstance(e, BzrError))
718
self.assertEqual('The message or message_callback keyword'
719
' parameter is required for commit().', str(e))
721
self.fail('exception not raised')
722
cb = self.Callback(u'commit 1', self)
723
tree.commit(message_callback=cb)
724
self.assertTrue(cb.called)
725
repository = tree.branch.repository
726
message = repository.get_revision(tree.last_revision()).message
727
self.assertEqual('commit 1', message)
729
def test_no_callback_pointless(self):
730
"""Callback should not be invoked for pointless commit"""
731
tree = self.make_branch_and_tree('.')
732
cb = self.Callback(u'commit 2', self)
733
self.assertRaises(PointlessCommit, tree.commit, message_callback=cb,
734
allow_pointless=False)
735
self.assertFalse(cb.called)
737
def test_no_callback_netfailure(self):
738
"""Callback should not be invoked if connectivity fails"""
739
tree = self.make_branch_and_tree('.')
740
cb = self.Callback(u'commit 2', self)
741
repository = tree.branch.repository
742
# simulate network failure
743
def raise_(self, arg, arg2, arg3=None, arg4=None):
744
raise errors.NoSuchFile('foo')
745
repository.add_inventory = raise_
746
repository.add_inventory_by_delta = raise_
747
self.assertRaises(errors.NoSuchFile, tree.commit, message_callback=cb)
748
self.assertFalse(cb.called)
750
def test_selected_file_merge_commit(self):
751
"""Ensure the correct error is raised"""
752
tree = self.make_branch_and_tree('foo')
753
# pending merge would turn into a left parent
754
tree.commit('commit 1')
755
tree.add_parent_tree_id('example')
756
self.build_tree(['foo/bar', 'foo/baz'])
757
tree.add(['bar', 'baz'])
758
err = self.assertRaises(errors.CannotCommitSelectedFileMerge,
759
tree.commit, 'commit 2', specific_files=['bar', 'baz'])
760
self.assertEqual(['bar', 'baz'], err.files)
761
self.assertEqual('Selected-file commit of merges is not supported'
762
' yet: files bar, baz', str(err))
764
def test_commit_ordering(self):
765
"""Test of corner-case commit ordering error"""
766
tree = self.make_branch_and_tree('.')
767
self.build_tree(['a/', 'a/z/', 'a/c/', 'a/z/x', 'a/z/y'])
768
tree.add(['a/', 'a/z/', 'a/c/', 'a/z/x', 'a/z/y'])
770
self.build_tree(['a/c/d/'])
772
tree.rename_one('a/z/x', 'a/c/d/x')
773
tree.commit('test', specific_files=['a/z/y'])
775
def test_commit_no_author(self):
776
"""The default kwarg author in MutableTree.commit should not add
777
the 'author' revision property.
779
tree = self.make_branch_and_tree('foo')
780
rev_id = tree.commit('commit 1')
781
rev = tree.branch.repository.get_revision(rev_id)
782
self.assertFalse('author' in rev.properties)
783
self.assertFalse('authors' in rev.properties)
785
def test_commit_author(self):
786
"""Passing a non-empty author kwarg to MutableTree.commit should add
787
the 'author' revision property.
789
tree = self.make_branch_and_tree('foo')
790
rev_id = self.callDeprecated(['The parameter author was '
791
'deprecated in version 1.13. Use authors instead'],
792
tree.commit, 'commit 1', author='John Doe <jdoe@example.com>')
793
rev = tree.branch.repository.get_revision(rev_id)
794
self.assertEqual('John Doe <jdoe@example.com>',
795
rev.properties['authors'])
796
self.assertFalse('author' in rev.properties)
798
def test_commit_empty_authors_list(self):
799
"""Passing an empty list to authors shouldn't add the property."""
800
tree = self.make_branch_and_tree('foo')
801
rev_id = tree.commit('commit 1', authors=[])
802
rev = tree.branch.repository.get_revision(rev_id)
803
self.assertFalse('author' in rev.properties)
804
self.assertFalse('authors' in rev.properties)
806
def test_multiple_authors(self):
807
tree = self.make_branch_and_tree('foo')
808
rev_id = tree.commit('commit 1',
809
authors=['John Doe <jdoe@example.com>',
810
'Jane Rey <jrey@example.com>'])
811
rev = tree.branch.repository.get_revision(rev_id)
812
self.assertEqual('John Doe <jdoe@example.com>\n'
813
'Jane Rey <jrey@example.com>', rev.properties['authors'])
814
self.assertFalse('author' in rev.properties)
816
def test_author_and_authors_incompatible(self):
817
tree = self.make_branch_and_tree('foo')
818
self.assertRaises(AssertionError, tree.commit, 'commit 1',
819
authors=['John Doe <jdoe@example.com>',
820
'Jane Rey <jrey@example.com>'],
821
author="Jack Me <jme@example.com>")
823
def test_author_with_newline_rejected(self):
824
tree = self.make_branch_and_tree('foo')
825
self.assertRaises(AssertionError, tree.commit, 'commit 1',
826
authors=['John\nDoe <jdoe@example.com>'])
828
def test_commit_with_checkout_and_branch_sharing_repo(self):
829
repo = self.make_repository('repo', shared=True)
830
# make_branch_and_tree ignores shared repos
831
branch = bzrdir.BzrDir.create_branch_convenience('repo/branch')
832
tree2 = branch.create_checkout('repo/tree2')
833
tree2.commit('message', rev_id='rev1')
834
self.assertTrue(tree2.branch.repository.has_revision('rev1'))