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
21
21
from bzrlib import (
28
29
from bzrlib.bzrdir import BzrDir, BzrDirMetaFormat1
29
30
from bzrlib.commit import Commit, NullCommitReporter
30
31
from bzrlib.config import BranchConfig
31
from bzrlib.errors import (PointlessCommit, BzrError, SigningFailed,
32
from bzrlib.errors import (PointlessCommit, BzrError, SigningFailed,
33
from bzrlib.tests import TestCaseWithTransport
34
from bzrlib.tests import SymlinkFeature, TestCaseWithTransport
34
35
from bzrlib.workingtree import WorkingTree
92
96
eq(rev.message, 'add hello')
94
98
tree1 = b.repository.revision_tree(rh[0])
95
100
text = tree1.get_file_text(file_id)
96
eq(text, 'hello world')
102
self.assertEqual('hello world', text)
98
104
tree2 = b.repository.revision_tree(rh[1])
99
eq(tree2.get_file_text(file_id), 'version 2')
106
text = tree2.get_file_text(file_id)
108
self.assertEqual('version 2', text)
101
def test_delete_commit(self):
102
"""Test a commit with a deleted file"""
110
def test_missing_commit(self):
111
"""Test a commit with a missing file"""
103
112
wt = self.make_branch_and_tree('.')
105
114
file('hello', 'w').write('hello world')
112
121
tree = b.repository.revision_tree('rev2')
113
122
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"])
115
144
def test_pointless_commit(self):
116
145
"""Commit refuses unless there are changes or it's forced."""
117
146
wt = self.make_branch_and_tree('.')
167
196
tree2 = b.repository.revision_tree('test@rev-2')
198
self.addCleanup(tree2.unlock)
168
199
self.assertTrue(tree2.has_filename('hello'))
169
200
self.assertEquals(tree2.get_file_text('hello-id'), 'hello')
170
201
self.assertEquals(tree2.get_file_text('buongia-id'), 'new text')
172
203
tree3 = b.repository.revision_tree('test@rev-3')
205
self.addCleanup(tree3.unlock)
173
206
self.assertFalse(tree3.has_filename('hello'))
174
207
self.assertEquals(tree3.get_file_text('buongia-id'), 'new text')
427
464
bound = master.sprout('bound')
428
465
wt = bound.open_workingtree()
429
466
wt.branch.set_bound_location(os.path.realpath('master'))
431
orig_default = lockdir._DEFAULT_TIMEOUT_SECONDS
432
467
master_branch.lock_write()
434
lockdir._DEFAULT_TIMEOUT_SECONDS = 1
435
469
self.assertRaises(LockContention, wt.commit, 'silly')
437
lockdir._DEFAULT_TIMEOUT_SECONDS = orig_default
438
471
master_branch.unlock()
440
473
def test_commit_bound_merge(self):
468
501
bound_tree.commit(message='commit of merge in bound tree')
470
503
def test_commit_reporting_after_merge(self):
471
# 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
472
505
# be called for each item that is added/removed/deleted.
473
506
this_tree = self.make_branch_and_tree('this')
474
507
# we need a bunch of files and dirs, to perform one action on each.
517
550
this_tree.merge_from_branch(other_tree.branch)
518
551
reporter = CapturingReporter()
519
552
this_tree.commit('do the commit', reporter=reporter)
521
('change', 'unchanged', ''),
522
('change', 'unchanged', 'dirtoleave'),
523
('change', 'unchanged', 'filetoleave'),
524
554
('change', 'modified', 'filetomodify'),
525
555
('change', 'added', 'newdir'),
526
556
('change', 'added', 'newfile'),
527
557
('renamed', 'renamed', 'dirtorename', 'renameddir'),
558
('renamed', 'renamed', 'filetorename', 'renamedfile'),
528
559
('renamed', 'renamed', 'dirtoreparent', 'renameddir/reparenteddir'),
529
560
('renamed', 'renamed', 'filetoreparent', 'renameddir/reparentedfile'),
530
('renamed', 'renamed', 'filetorename', 'renamedfile'),
531
561
('deleted', 'dirtoremove'),
532
562
('deleted', 'filetoremove'),
564
result = set(reporter.calls)
565
missing = expected - result
566
new = result - expected
567
self.assertEqual((set(), set()), (missing, new))
536
569
def test_commit_removals_respects_filespec(self):
537
570
"""Commit respects the specified_files for removals."""
628
660
def test_commit_unversioned_specified(self):
629
661
"""Commit should raise if specified files isn't in basis or worktree"""
630
662
tree = self.make_branch_and_tree('.')
631
self.assertRaises(errors.PathsNotVersionedError, tree.commit,
663
self.assertRaises(errors.PathsNotVersionedError, tree.commit,
632
664
'message', specific_files=['bogus'])
634
666
class Callback(object):
636
668
def __init__(self, message, testcase):
637
669
self.called = False
638
670
self.message = message
666
698
"""Callback should not be invoked for pointless commit"""
667
699
tree = self.make_branch_and_tree('.')
668
700
cb = self.Callback(u'commit 2', self)
669
self.assertRaises(PointlessCommit, tree.commit, message_callback=cb,
701
self.assertRaises(PointlessCommit, tree.commit, message_callback=cb,
670
702
allow_pointless=False)
671
703
self.assertFalse(cb.called)
676
708
cb = self.Callback(u'commit 2', self)
677
709
repository = tree.branch.repository
678
710
# simulate network failure
679
def raise_(self, arg, arg2):
711
def raise_(self, arg, arg2, arg3=None, arg4=None):
680
712
raise errors.NoSuchFile('foo')
681
713
repository.add_inventory = raise_
714
repository.add_inventory_by_delta = raise_
682
715
self.assertRaises(errors.NoSuchFile, tree.commit, message_callback=cb)
683
716
self.assertFalse(cb.called)
696
729
self.assertEqual('Selected-file commit of merges is not supported'
697
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'])
699
743
def test_commit_no_author(self):
700
744
"""The default kwarg author in MutableTree.commit should not add
701
745
the 'author' revision property.
704
748
rev_id = tree.commit('commit 1')
705
749
rev = tree.branch.repository.get_revision(rev_id)
706
750
self.assertFalse('author' in rev.properties)
751
self.assertFalse('authors' in rev.properties)
708
753
def test_commit_author(self):
709
754
"""Passing a non-empty author kwarg to MutableTree.commit should add
710
755
the 'author' revision property.
712
757
tree = self.make_branch_and_tree('foo')
713
rev_id = tree.commit('commit 1', author='John Doe <jdoe@example.com>')
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>')
714
761
rev = tree.branch.repository.get_revision(rev_id)
715
762
self.assertEqual('John Doe <jdoe@example.com>',
716
rev.properties['author'])
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'))