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