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 (
25
28
from bzrlib.branch import Branch
26
from bzrlib.bzrdir import BzrDirMetaFormat1
29
from bzrlib.bzrdir import BzrDir, BzrDirMetaFormat1
27
30
from bzrlib.commit import Commit, NullCommitReporter
28
31
from bzrlib.config import BranchConfig
29
from bzrlib.errors import (
35
from bzrlib.tests import (
36
TestCaseWithTransport,
39
from bzrlib.tests.features import (
42
from bzrlib.tests.matchers import MatchesAncestry
32
from bzrlib.errors import (PointlessCommit, BzrError, SigningFailed,
34
from bzrlib.tests import SymlinkFeature, TestCaseWithTransport
35
from bzrlib.workingtree import WorkingTree
45
38
# TODO: Test commit with some added, and added-but-missing files
115
108
self.assertEqual('version 2', text)
117
def test_commit_lossy_native(self):
118
"""Attempt a lossy commit to a native branch."""
119
wt = self.make_branch_and_tree('.')
121
file('hello', 'w').write('hello world')
123
revid = wt.commit(message='add hello', rev_id='revid', lossy=True)
124
self.assertEquals('revid', revid)
126
def test_commit_lossy_foreign(self):
127
"""Attempt a lossy commit to a foreign branch."""
128
test_foreign.register_dummy_foreign_for_test(self)
129
wt = self.make_branch_and_tree('.',
130
format=test_foreign.DummyForeignVcsDirFormat())
132
file('hello', 'w').write('hello world')
134
revid = wt.commit(message='add hello', lossy=True,
135
timestamp=1302659388, timezone=0)
136
self.assertEquals('dummy-v1:1302659388.0-0-UNKNOWN', revid)
138
def test_commit_bound_lossy_foreign(self):
139
"""Attempt a lossy commit to a bzr branch bound to a foreign branch."""
140
test_foreign.register_dummy_foreign_for_test(self)
141
foreign_branch = self.make_branch('foreign',
142
format=test_foreign.DummyForeignVcsDirFormat())
143
wt = foreign_branch.create_checkout("local")
145
file('local/hello', 'w').write('hello world')
147
revid = wt.commit(message='add hello', lossy=True,
148
timestamp=1302659388, timezone=0)
149
self.assertEquals('dummy-v1:1302659388.0-0-0', revid)
150
self.assertEquals('dummy-v1:1302659388.0-0-0',
151
foreign_branch.last_revision())
152
self.assertEquals('dummy-v1:1302659388.0-0-0',
153
wt.branch.last_revision())
155
def test_missing_commit(self):
156
"""Test a commit with a missing file"""
110
def test_delete_commit(self):
111
"""Test a commit with a deleted file"""
157
112
wt = self.make_branch_and_tree('.')
159
114
file('hello', 'w').write('hello world')
170
125
"""Test a partial commit where a file was renamed but not committed.
172
127
https://bugs.launchpad.net/bzr/+bug/83039
174
129
If not handled properly, commit will try to snapshot
175
dialog.py with olive/ as a parent, while
130
dialog.py with olive/ as a parent, while
176
131
olive/ has not been snapshotted yet.
178
133
wt = self.make_branch_and_tree('.')
269
224
eq(tree1.id2path('hello-id'), 'hello')
270
225
eq(tree1.get_file_text('hello-id'), 'contents of hello\n')
271
226
self.assertFalse(tree1.has_filename('fruity'))
272
self.check_tree_shape(tree1, ['hello'])
273
eq(tree1.get_file_revision('hello-id'), 'test@rev-1')
227
self.check_inventory_shape(tree1.inventory, ['hello'])
228
ie = tree1.inventory['hello-id']
229
eq(ie.revision, 'test@rev-1')
275
231
tree2 = b.repository.revision_tree('test@rev-2')
276
232
tree2.lock_read()
277
233
self.addCleanup(tree2.unlock)
278
234
eq(tree2.id2path('hello-id'), 'fruity')
279
235
eq(tree2.get_file_text('hello-id'), 'contents of hello\n')
280
self.check_tree_shape(tree2, ['fruity'])
281
eq(tree2.get_file_revision('hello-id'), 'test@rev-2')
236
self.check_inventory_shape(tree2.inventory, ['fruity'])
237
ie = tree2.inventory['hello-id']
238
eq(ie.revision, 'test@rev-2')
283
240
def test_reused_rev_id(self):
284
241
"""Test that a revision id cannot be reused in a branch"""
314
272
wt.commit('three', rev_id=r3, allow_pointless=False)
317
self.check_tree_shape(wt,
275
self.check_inventory_shape(wt.read_working_inventory(),
318
276
['a/', 'a/hello', 'a/b/'])
319
self.check_tree_shape(b.repository.revision_tree(r3),
277
self.check_inventory_shape(b.repository.get_revision_inventory(r3),
320
278
['a/', 'a/hello', 'a/b/'])
326
284
wt.commit('four', rev_id=r4, allow_pointless=False)
329
self.check_tree_shape(wt, ['a/', 'a/b/hello', 'a/b/'])
287
self.check_inventory_shape(wt.read_working_inventory(),
288
['a/', 'a/b/hello', 'a/b/'])
333
inv = b.repository.get_inventory(r4)
292
inv = b.repository.get_revision_inventory(r4)
334
293
eq(inv['hello-id'].revision, r4)
335
294
eq(inv['a-id'].revision, r1)
336
295
eq(inv['b-id'].revision, r3)
364
323
eq = self.assertEquals
365
324
eq(b.revision_history(), rev_ids)
366
325
for i in range(4):
367
self.assertThat(rev_ids[:i+1],
368
MatchesAncestry(b.repository, rev_ids[i]))
326
anc = b.repository.get_ancestry(rev_ids[i])
327
eq(anc, [None] + rev_ids[:i+1])
370
329
def test_commit_new_subdir_child_selective(self):
371
330
wt = self.make_branch_and_tree('.')
449
409
wt = self.make_branch_and_tree('.')
450
410
branch = wt.branch
451
411
wt.commit("base", allow_pointless=True, rev_id='A')
452
self.assertFalse(branch.repository.has_signature_for_revision_id('A'))
412
self.failIf(branch.repository.has_signature_for_revision_id('A'))
414
from bzrlib.testament import Testament
454
415
# monkey patch gpg signing mechanism
455
416
bzrlib.gpg.GPGStrategy = bzrlib.gpg.DisabledGPGStrategy
456
417
config = MustSignConfig(branch)
540
501
bound_tree.commit(message='commit of merge in bound tree')
542
503
def test_commit_reporting_after_merge(self):
543
# 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
544
505
# be called for each item that is added/removed/deleted.
545
506
this_tree = self.make_branch_and_tree('this')
546
507
# we need a bunch of files and dirs, to perform one action on each.
589
550
this_tree.merge_from_branch(other_tree.branch)
590
551
reporter = CapturingReporter()
591
552
this_tree.commit('do the commit', reporter=reporter)
554
('change', 'unchanged', ''),
555
('change', 'unchanged', 'dirtoleave'),
556
('change', 'unchanged', 'filetoleave'),
593
557
('change', 'modified', 'filetomodify'),
594
558
('change', 'added', 'newdir'),
595
559
('change', 'added', 'newfile'),
599
563
('renamed', 'renamed', 'filetoreparent', 'renameddir/reparentedfile'),
600
564
('deleted', 'dirtoremove'),
601
565
('deleted', 'filetoremove'),
603
result = set(reporter.calls)
604
missing = expected - result
605
new = result - expected
606
self.assertEqual((set(), set()), (missing, new))
608
569
def test_commit_removals_respects_filespec(self):
609
570
"""Commit respects the specified_files for removals."""
699
660
def test_commit_unversioned_specified(self):
700
661
"""Commit should raise if specified files isn't in basis or worktree"""
701
662
tree = self.make_branch_and_tree('.')
702
self.assertRaises(errors.PathsNotVersionedError, tree.commit,
663
self.assertRaises(errors.PathsNotVersionedError, tree.commit,
703
664
'message', specific_files=['bogus'])
705
666
class Callback(object):
707
668
def __init__(self, message, testcase):
708
669
self.called = False
709
670
self.message = message
737
698
"""Callback should not be invoked for pointless commit"""
738
699
tree = self.make_branch_and_tree('.')
739
700
cb = self.Callback(u'commit 2', self)
740
self.assertRaises(PointlessCommit, tree.commit, message_callback=cb,
701
self.assertRaises(PointlessCommit, tree.commit, message_callback=cb,
741
702
allow_pointless=False)
742
703
self.assertFalse(cb.called)
747
708
cb = self.Callback(u'commit 2', self)
748
709
repository = tree.branch.repository
749
710
# simulate network failure
750
def raise_(self, arg, arg2, arg3=None, arg4=None):
711
def raise_(self, arg, arg2):
751
712
raise errors.NoSuchFile('foo')
752
713
repository.add_inventory = raise_
753
repository.add_inventory_by_delta = raise_
754
714
self.assertRaises(errors.NoSuchFile, tree.commit, message_callback=cb)
755
715
self.assertFalse(cb.called)
787
747
rev_id = tree.commit('commit 1')
788
748
rev = tree.branch.repository.get_revision(rev_id)
789
749
self.assertFalse('author' in rev.properties)
790
self.assertFalse('authors' in rev.properties)
792
751
def test_commit_author(self):
793
752
"""Passing a non-empty author kwarg to MutableTree.commit should add
794
753
the 'author' revision property.
796
755
tree = self.make_branch_and_tree('foo')
797
rev_id = self.callDeprecated(['The parameter author was '
798
'deprecated in version 1.13. Use authors instead'],
799
tree.commit, 'commit 1', author='John Doe <jdoe@example.com>')
756
rev_id = tree.commit('commit 1', author='John Doe <jdoe@example.com>')
800
757
rev = tree.branch.repository.get_revision(rev_id)
801
758
self.assertEqual('John Doe <jdoe@example.com>',
802
rev.properties['authors'])
803
self.assertFalse('author' in rev.properties)
805
def test_commit_empty_authors_list(self):
806
"""Passing an empty list to authors shouldn't add the property."""
807
tree = self.make_branch_and_tree('foo')
808
rev_id = tree.commit('commit 1', authors=[])
809
rev = tree.branch.repository.get_revision(rev_id)
810
self.assertFalse('author' in rev.properties)
811
self.assertFalse('authors' in rev.properties)
813
def test_multiple_authors(self):
814
tree = self.make_branch_and_tree('foo')
815
rev_id = tree.commit('commit 1',
816
authors=['John Doe <jdoe@example.com>',
817
'Jane Rey <jrey@example.com>'])
818
rev = tree.branch.repository.get_revision(rev_id)
819
self.assertEqual('John Doe <jdoe@example.com>\n'
820
'Jane Rey <jrey@example.com>', rev.properties['authors'])
821
self.assertFalse('author' in rev.properties)
823
def test_author_and_authors_incompatible(self):
824
tree = self.make_branch_and_tree('foo')
825
self.assertRaises(AssertionError, tree.commit, 'commit 1',
826
authors=['John Doe <jdoe@example.com>',
827
'Jane Rey <jrey@example.com>'],
828
author="Jack Me <jme@example.com>")
830
def test_author_with_newline_rejected(self):
831
tree = self.make_branch_and_tree('foo')
832
self.assertRaises(AssertionError, tree.commit, 'commit 1',
833
authors=['John\nDoe <jdoe@example.com>'])
759
rev.properties['author'])
835
761
def test_commit_with_checkout_and_branch_sharing_repo(self):
836
762
repo = self.make_repository('repo', shared=True)