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
29
29
from bzrlib.bzrdir import BzrDir, BzrDirMetaFormat1
30
30
from bzrlib.commit import Commit, NullCommitReporter
31
31
from bzrlib.config import BranchConfig
32
from bzrlib.errors import (PointlessCommit, BzrError, SigningFailed,
32
from bzrlib.errors import (PointlessCommit, BzrError, SigningFailed,
34
34
from bzrlib.tests import SymlinkFeature, TestCaseWithTransport
35
35
from bzrlib.workingtree import WorkingTree
108
108
self.assertEqual('version 2', text)
110
def test_missing_commit(self):
111
"""Test a commit with a missing file"""
110
def test_delete_commit(self):
111
"""Test a commit with a deleted file"""
112
112
wt = self.make_branch_and_tree('.')
114
114
file('hello', 'w').write('hello world')
121
121
tree = b.repository.revision_tree('rev2')
122
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"])
144
124
def test_pointless_commit(self):
145
125
"""Commit refuses unless there are changes or it's forced."""
146
126
wt = self.make_branch_and_tree('.')
275
255
self.check_inventory_shape(wt.read_working_inventory(),
276
256
['a/', 'a/hello', 'a/b/'])
277
self.check_inventory_shape(b.repository.get_inventory(r3),
257
self.check_inventory_shape(b.repository.get_revision_inventory(r3),
278
258
['a/', 'a/hello', 'a/b/'])
464
444
bound = master.sprout('bound')
465
445
wt = bound.open_workingtree()
466
446
wt.branch.set_bound_location(os.path.realpath('master'))
448
orig_default = lockdir._DEFAULT_TIMEOUT_SECONDS
467
449
master_branch.lock_write()
451
lockdir._DEFAULT_TIMEOUT_SECONDS = 1
469
452
self.assertRaises(LockContention, wt.commit, 'silly')
454
lockdir._DEFAULT_TIMEOUT_SECONDS = orig_default
471
455
master_branch.unlock()
473
457
def test_commit_bound_merge(self):
501
485
bound_tree.commit(message='commit of merge in bound tree')
503
487
def test_commit_reporting_after_merge(self):
504
# when doing a commit of a merge, the reporter needs to still
488
# when doing a commit of a merge, the reporter needs to still
505
489
# be called for each item that is added/removed/deleted.
506
490
this_tree = self.make_branch_and_tree('this')
507
491
# we need a bunch of files and dirs, to perform one action on each.
550
534
this_tree.merge_from_branch(other_tree.branch)
551
535
reporter = CapturingReporter()
552
536
this_tree.commit('do the commit', reporter=reporter)
538
('change', 'unchanged', ''),
539
('change', 'unchanged', 'dirtoleave'),
540
('change', 'unchanged', 'filetoleave'),
554
541
('change', 'modified', 'filetomodify'),
555
542
('change', 'added', 'newdir'),
556
543
('change', 'added', 'newfile'),
560
547
('renamed', 'renamed', 'filetoreparent', 'renameddir/reparentedfile'),
561
548
('deleted', 'dirtoremove'),
562
549
('deleted', 'filetoremove'),
564
result = set(reporter.calls)
565
missing = expected - result
566
new = result - expected
567
self.assertEqual((set(), set()), (missing, new))
569
553
def test_commit_removals_respects_filespec(self):
570
554
"""Commit respects the specified_files for removals."""
660
644
def test_commit_unversioned_specified(self):
661
645
"""Commit should raise if specified files isn't in basis or worktree"""
662
646
tree = self.make_branch_and_tree('.')
663
self.assertRaises(errors.PathsNotVersionedError, tree.commit,
647
self.assertRaises(errors.PathsNotVersionedError, tree.commit,
664
648
'message', specific_files=['bogus'])
666
650
class Callback(object):
668
652
def __init__(self, message, testcase):
669
653
self.called = False
670
654
self.message = message
698
682
"""Callback should not be invoked for pointless commit"""
699
683
tree = self.make_branch_and_tree('.')
700
684
cb = self.Callback(u'commit 2', self)
701
self.assertRaises(PointlessCommit, tree.commit, message_callback=cb,
685
self.assertRaises(PointlessCommit, tree.commit, message_callback=cb,
702
686
allow_pointless=False)
703
687
self.assertFalse(cb.called)
708
692
cb = self.Callback(u'commit 2', self)
709
693
repository = tree.branch.repository
710
694
# simulate network failure
711
def raise_(self, arg, arg2, arg3=None, arg4=None):
695
def raise_(self, arg, arg2):
712
696
raise errors.NoSuchFile('foo')
713
697
repository.add_inventory = raise_
714
repository.add_inventory_by_delta = raise_
715
698
self.assertRaises(errors.NoSuchFile, tree.commit, message_callback=cb)
716
699
self.assertFalse(cb.called)
748
731
rev_id = tree.commit('commit 1')
749
732
rev = tree.branch.repository.get_revision(rev_id)
750
733
self.assertFalse('author' in rev.properties)
751
self.assertFalse('authors' in rev.properties)
753
735
def test_commit_author(self):
754
736
"""Passing a non-empty author kwarg to MutableTree.commit should add
755
737
the 'author' revision property.
757
739
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>')
740
rev_id = tree.commit('commit 1', author='John Doe <jdoe@example.com>')
761
741
rev = tree.branch.repository.get_revision(rev_id)
762
742
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>'])
743
rev.properties['author'])
796
745
def test_commit_with_checkout_and_branch_sharing_repo(self):
797
746
repo = self.make_repository('repo', shared=True)