121
112
tree = b.repository.revision_tree('rev2')
122
113
self.assertFalse(tree.has_id('hello-id'))
124
def test_partial_commit_move(self):
125
"""Test a partial commit where a file was renamed but not committed.
127
https://bugs.launchpad.net/bzr/+bug/83039
129
If not handled properly, commit will try to snapshot
130
dialog.py with olive/ as a parent, while
131
olive/ has not been snapshotted yet.
133
wt = self.make_branch_and_tree('.')
135
self.build_tree(['annotate/', 'annotate/foo.py',
136
'olive/', 'olive/dialog.py'
138
wt.add(['annotate', 'olive', 'annotate/foo.py', 'olive/dialog.py'])
139
wt.commit(message='add files')
140
wt.rename_one("olive/dialog.py", "aaa")
141
self.build_tree_contents([('annotate/foo.py', 'modified\n')])
142
wt.commit('renamed hello', specific_files=["annotate"])
144
115
def test_pointless_commit(self):
145
116
"""Commit refuses unless there are changes or it's forced."""
146
117
wt = self.make_branch_and_tree('.')
260
223
wt.move(['hello'], 'a')
261
224
r2 = 'test@rev-2'
262
225
wt.commit('two', rev_id=r2, allow_pointless=False)
265
self.check_inventory_shape(wt.read_working_inventory(),
266
['a/', 'a/hello', 'b/'])
226
self.check_inventory_shape(wt.read_working_inventory(),
227
['a', 'a/hello', 'b'])
270
229
wt.move(['b'], 'a')
271
230
r3 = 'test@rev-3'
272
231
wt.commit('three', rev_id=r3, allow_pointless=False)
275
self.check_inventory_shape(wt.read_working_inventory(),
276
['a/', 'a/hello', 'a/b/'])
277
self.check_inventory_shape(b.repository.get_inventory(r3),
278
['a/', 'a/hello', 'a/b/'])
232
self.check_inventory_shape(wt.read_working_inventory(),
233
['a', 'a/hello', 'a/b'])
234
self.check_inventory_shape(b.repository.get_revision_inventory(r3),
235
['a', 'a/hello', 'a/b'])
282
237
wt.move(['a/hello'], 'a/b')
283
238
r4 = 'test@rev-4'
284
239
wt.commit('four', rev_id=r4, allow_pointless=False)
287
self.check_inventory_shape(wt.read_working_inventory(),
288
['a/', 'a/b/hello', 'a/b/'])
240
self.check_inventory_shape(wt.read_working_inventory(),
241
['a', 'a/b/hello', 'a/b'])
292
inv = b.repository.get_inventory(r4)
243
inv = b.repository.get_revision_inventory(r4)
293
244
eq(inv['hello-id'].revision, r4)
294
245
eq(inv['a-id'].revision, r1)
295
246
eq(inv['b-id'].revision, r3)
297
248
def test_removed_commit(self):
298
249
"""Commit with a removed file"""
299
250
wt = self.make_branch_and_tree('.')
550
503
this_tree.merge_from_branch(other_tree.branch)
551
504
reporter = CapturingReporter()
552
505
this_tree.commit('do the commit', reporter=reporter)
507
('change', 'unchanged', ''),
508
('change', 'unchanged', 'dirtoleave'),
509
('change', 'unchanged', 'filetoleave'),
554
510
('change', 'modified', 'filetomodify'),
555
511
('change', 'added', 'newdir'),
556
512
('change', 'added', 'newfile'),
557
513
('renamed', 'renamed', 'dirtorename', 'renameddir'),
558
('renamed', 'renamed', 'filetorename', 'renamedfile'),
559
514
('renamed', 'renamed', 'dirtoreparent', 'renameddir/reparenteddir'),
560
515
('renamed', 'renamed', 'filetoreparent', 'renameddir/reparentedfile'),
516
('renamed', 'renamed', 'filetorename', 'renamedfile'),
561
517
('deleted', 'dirtoremove'),
562
518
('deleted', 'filetoremove'),
564
result = set(reporter.calls)
565
missing = expected - result
566
new = result - expected
567
self.assertEqual((set(), set()), (missing, new))
569
522
def test_commit_removals_respects_filespec(self):
570
523
"""Commit respects the specified_files for removals."""
605
554
timestamp_1ms = round(timestamp, 3)
606
555
self.assertEqual(timestamp_1ms, timestamp)
608
def assertBasisTreeKind(self, kind, tree, file_id):
609
basis = tree.basis_tree()
612
self.assertEqual(kind, basis.kind(file_id))
616
557
def test_commit_kind_changes(self):
617
self.requireFeature(SymlinkFeature)
558
if not osutils.has_symlinks():
559
raise tests.TestSkipped('Test requires symlink support')
618
560
tree = self.make_branch_and_tree('.')
619
561
os.symlink('target', 'name')
620
562
tree.add('name', 'a-file-id')
621
563
tree.commit('Added a symlink')
622
self.assertBasisTreeKind('symlink', tree, 'a-file-id')
564
self.assertEqual('symlink', tree.basis_tree().kind('a-file-id'))
624
566
os.unlink('name')
625
567
self.build_tree(['name'])
626
568
tree.commit('Changed symlink to file')
627
self.assertBasisTreeKind('file', tree, 'a-file-id')
569
self.assertEqual('file', tree.basis_tree().kind('a-file-id'))
629
571
os.unlink('name')
630
572
os.symlink('target', 'name')
631
573
tree.commit('file to symlink')
632
self.assertBasisTreeKind('symlink', tree, 'a-file-id')
574
self.assertEqual('symlink', tree.basis_tree().kind('a-file-id'))
634
576
os.unlink('name')
636
578
tree.commit('symlink to directory')
637
self.assertBasisTreeKind('directory', tree, 'a-file-id')
579
self.assertEqual('directory', tree.basis_tree().kind('a-file-id'))
640
582
os.symlink('target', 'name')
641
583
tree.commit('directory to symlink')
642
self.assertBasisTreeKind('symlink', tree, 'a-file-id')
584
self.assertEqual('symlink', tree.basis_tree().kind('a-file-id'))
644
586
# prepare for directory <-> file tests
645
587
os.unlink('name')
647
589
tree.commit('symlink to directory')
648
self.assertBasisTreeKind('directory', tree, 'a-file-id')
590
self.assertEqual('directory', tree.basis_tree().kind('a-file-id'))
651
593
self.build_tree(['name'])
652
594
tree.commit('Changed directory to file')
653
self.assertBasisTreeKind('file', tree, 'a-file-id')
595
self.assertEqual('file', tree.basis_tree().kind('a-file-id'))
655
597
os.unlink('name')
657
599
tree.commit('file to directory')
658
self.assertBasisTreeKind('directory', tree, 'a-file-id')
600
self.assertEqual('directory', tree.basis_tree().kind('a-file-id'))
660
602
def test_commit_unversioned_specified(self):
661
603
"""Commit should raise if specified files isn't in basis or worktree"""
662
604
tree = self.make_branch_and_tree('.')
663
self.assertRaises(errors.PathsNotVersionedError, tree.commit,
605
self.assertRaises(errors.PathsNotVersionedError, tree.commit,
664
606
'message', specific_files=['bogus'])
666
608
class Callback(object):
668
610
def __init__(self, message, testcase):
669
611
self.called = False
670
612
self.message = message
708
650
cb = self.Callback(u'commit 2', self)
709
651
repository = tree.branch.repository
710
652
# simulate network failure
711
def raise_(self, arg, arg2, arg3=None, arg4=None):
653
def raise_(self, arg, arg2):
712
654
raise errors.NoSuchFile('foo')
713
655
repository.add_inventory = raise_
714
repository.add_inventory_by_delta = raise_
715
656
self.assertRaises(errors.NoSuchFile, tree.commit, message_callback=cb)
716
657
self.assertFalse(cb.called)
718
def test_selected_file_merge_commit(self):
719
"""Ensure the correct error is raised"""
720
tree = self.make_branch_and_tree('foo')
721
# pending merge would turn into a left parent
722
tree.commit('commit 1')
723
tree.add_parent_tree_id('example')
724
self.build_tree(['foo/bar', 'foo/baz'])
725
tree.add(['bar', 'baz'])
726
err = self.assertRaises(errors.CannotCommitSelectedFileMerge,
727
tree.commit, 'commit 2', specific_files=['bar', 'baz'])
728
self.assertEqual(['bar', 'baz'], err.files)
729
self.assertEqual('Selected-file commit of merges is not supported'
730
' yet: files bar, baz', str(err))
732
def test_commit_ordering(self):
733
"""Test of corner-case commit ordering error"""
734
tree = self.make_branch_and_tree('.')
735
self.build_tree(['a/', 'a/z/', 'a/c/', 'a/z/x', 'a/z/y'])
736
tree.add(['a/', 'a/z/', 'a/c/', 'a/z/x', 'a/z/y'])
738
self.build_tree(['a/c/d/'])
740
tree.rename_one('a/z/x', 'a/c/d/x')
741
tree.commit('test', specific_files=['a/z/y'])
743
def test_commit_no_author(self):
744
"""The default kwarg author in MutableTree.commit should not add
745
the 'author' revision property.
747
tree = self.make_branch_and_tree('foo')
748
rev_id = tree.commit('commit 1')
749
rev = tree.branch.repository.get_revision(rev_id)
750
self.assertFalse('author' in rev.properties)
751
self.assertFalse('authors' in rev.properties)
753
def test_commit_author(self):
754
"""Passing a non-empty author kwarg to MutableTree.commit should add
755
the 'author' revision property.
757
tree = self.make_branch_and_tree('foo')
758
rev_id = self.callDeprecated(['The parameter author was '
759
'deprecated in version 1.13. Use authors instead'],
760
tree.commit, 'commit 1', author='John Doe <jdoe@example.com>')
761
rev = tree.branch.repository.get_revision(rev_id)
762
self.assertEqual('John Doe <jdoe@example.com>',
763
rev.properties['authors'])
764
self.assertFalse('author' in rev.properties)
766
def test_commit_empty_authors_list(self):
767
"""Passing an empty list to authors shouldn't add the property."""
768
tree = self.make_branch_and_tree('foo')
769
rev_id = tree.commit('commit 1', authors=[])
770
rev = tree.branch.repository.get_revision(rev_id)
771
self.assertFalse('author' in rev.properties)
772
self.assertFalse('authors' in rev.properties)
774
def test_multiple_authors(self):
775
tree = self.make_branch_and_tree('foo')
776
rev_id = tree.commit('commit 1',
777
authors=['John Doe <jdoe@example.com>',
778
'Jane Rey <jrey@example.com>'])
779
rev = tree.branch.repository.get_revision(rev_id)
780
self.assertEqual('John Doe <jdoe@example.com>\n'
781
'Jane Rey <jrey@example.com>', rev.properties['authors'])
782
self.assertFalse('author' in rev.properties)
784
def test_author_and_authors_incompatible(self):
785
tree = self.make_branch_and_tree('foo')
786
self.assertRaises(AssertionError, tree.commit, 'commit 1',
787
authors=['John Doe <jdoe@example.com>',
788
'Jane Rey <jrey@example.com>'],
789
author="Jack Me <jme@example.com>")
791
def test_author_with_newline_rejected(self):
792
tree = self.make_branch_and_tree('foo')
793
self.assertRaises(AssertionError, tree.commit, 'commit 1',
794
authors=['John\nDoe <jdoe@example.com>'])
796
def test_commit_with_checkout_and_branch_sharing_repo(self):
797
repo = self.make_repository('repo', shared=True)
798
# make_branch_and_tree ignores shared repos
799
branch = bzrdir.BzrDir.create_branch_convenience('repo/branch')
800
tree2 = branch.create_checkout('repo/tree2')
801
tree2.commit('message', rev_id='rev1')
802
self.assertTrue(tree2.branch.repository.has_revision('rev1'))