1
# Copyright (C) 2006-2011 Canonical Ltd
1
# Copyright (C) 2005, 2006 by Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
11
# GNU General Public License for more details.
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
18
18
"""Tests for the commit CLI of bzr."""
25
from testtools.matchers import DocTestMatches
24
from bzrlib.branch import Branch
34
25
from bzrlib.bzrdir import BzrDir
35
from bzrlib.tests import (
39
UnicodeFilenameFeature,
41
from bzrlib.tests import TestCaseWithTransport
44
class TestCommit(TestCaseWithTransport):
26
from bzrlib.errors import BzrCommandError
27
from bzrlib.tests.blackbox import ExternalBase
28
from bzrlib.workingtree import WorkingTree
31
class TestCommit(ExternalBase):
46
33
def test_05_empty_commit(self):
47
34
"""Commit of tree with no versioned files should fail"""
48
35
# If forced, it should succeed, but this is not tested here.
49
self.make_branch_and_tree('.')
50
37
self.build_tree(['hello.txt'])
51
out,err = self.run_bzr('commit -m empty', retcode=3)
52
self.assertEqual('', out)
54
# 1) We really don't want 'aborting commit write group' anymore.
55
# 2) bzr: ERROR: is a really long line, so we wrap it with '\'
60
aborting commit write group: PointlessCommit(No changes to commit)
61
bzr: ERROR: No changes to commit.\
62
Please 'bzr add' the files you want to commit,\
63
or use --unchanged to force an empty commit.
64
""", flags=doctest.ELLIPSIS|doctest.REPORT_UDIFF))
66
def test_commit_success(self):
67
"""Successful commit should not leave behind a bzr-commit-* file"""
68
self.make_branch_and_tree('.')
69
self.run_bzr('commit --unchanged -m message')
70
self.assertEqual('', self.run_bzr('unknowns')[0])
72
# same for unicode messages
73
self.run_bzr(["commit", "--unchanged", "-m", u'foo\xb5'])
74
self.assertEqual('', self.run_bzr('unknowns')[0])
76
def test_commit_lossy_native(self):
77
"""A --lossy option to commit is supported."""
78
self.make_branch_and_tree('.')
79
self.run_bzr('commit --lossy --unchanged -m message')
80
self.assertEqual('', self.run_bzr('unknowns')[0])
82
def test_commit_lossy_foreign(self):
83
test_foreign.register_dummy_foreign_for_test(self)
84
self.make_branch_and_tree('.',
85
format=test_foreign.DummyForeignVcsDirFormat())
86
self.run_bzr('commit --lossy --unchanged -m message')
87
output = self.run_bzr('revision-info')[0]
88
self.assertTrue(output.startswith('1 dummy-'))
38
self.runbzr("commit -m empty", retcode=3)
90
40
def test_commit_with_path(self):
91
41
"""Commit tree with path of root specified"""
92
a_tree = self.make_branch_and_tree('a')
42
self.run_bzr('init', 'a')
93
43
self.build_tree(['a/a_file'])
95
self.run_bzr(['commit', '-m', 'first commit', 'a'])
44
self.run_bzr('add', 'a/a_file')
45
self.run_bzr('commit', '-m', 'first commit', 'a')
97
b_tree = a_tree.bzrdir.sprout('b').open_workingtree()
47
self.run_bzr('branch', 'a', 'b')
98
48
self.build_tree_contents([('b/a_file', 'changes in b')])
99
self.run_bzr(['commit', '-m', 'first commit in b', 'b'])
49
self.run_bzr('commit', '-m', 'first commit in b', 'b')
101
51
self.build_tree_contents([('a/a_file', 'new contents')])
102
self.run_bzr(['commit', '-m', 'change in a', 'a'])
104
b_tree.merge_from_branch(a_tree.branch)
105
self.assertEqual(len(b_tree.conflicts()), 1)
106
self.run_bzr('resolved b/a_file')
107
self.run_bzr(['commit', '-m', 'merge into b', 'b'])
52
self.run_bzr('commit', '-m', 'change in a', 'a')
55
self.run_bzr('merge', '../a', retcode=1) # will conflict
57
self.run_bzr('resolved', 'b/a_file')
58
self.run_bzr('commit', '-m', 'merge into b', 'b')
109
61
def test_10_verbose_commit(self):
110
62
"""Add one file and examine verbose commit output"""
111
tree = self.make_branch_and_tree('.')
112
64
self.build_tree(['hello.txt'])
113
tree.add("hello.txt")
114
out,err = self.run_bzr('commit -m added')
65
self.runbzr("add hello.txt")
66
out,err = self.run_bzr("commit", "-m", "added")
115
67
self.assertEqual('', out)
116
self.assertContainsRe(err, '^Committing to: .*\n'
118
'Committed revision 1.\n$',)
68
self.assertEqual('added hello.txt\n'
69
'Committed revision 1.\n',
120
72
def prepare_simple_history(self):
121
73
"""Prepare and return a working tree with one commit of one file"""
310
184
other_tree.commit('modify all sample files and dirs.')
312
186
other_tree.unlock()
313
this_tree.merge_from_branch(other_tree.branch)
187
self.merge(other_tree.branch, this_tree)
315
out,err = self.run_bzr('commit -m added')
189
out,err = self.run_bzr("commit", "-m", "added")
316
191
self.assertEqual('', out)
317
self.assertEqual(set([
318
'Committing to: %s/' % osutils.getcwd(),
319
'modified filetomodify',
322
'renamed dirtorename => renameddir',
323
'renamed filetorename => renamedfile',
324
'renamed dirtoreparent => renameddir/reparenteddir',
325
'renamed filetoreparent => renameddir/reparentedfile',
326
'deleted dirtoremove',
327
'deleted filetoremove',
328
'Committed revision 2.',
330
]), set(err.split('\n')))
192
self.assertEqualDiff(
193
'modified filetomodify\n'
196
'renamed dirtorename => renameddir\n'
197
'renamed dirtoreparent => renameddir/reparenteddir\n'
198
'renamed filetoreparent => renameddir/reparentedfile\n'
199
'renamed filetorename => renamedfile\n'
200
'deleted dirtoremove\n'
201
'deleted filetoremove\n'
202
'Committed revision 2.\n',
332
205
def test_empty_commit_message(self):
333
tree = self.make_branch_and_tree('.')
334
self.build_tree_contents([('foo.c', 'int main() {}')])
336
self.run_bzr('commit -m ""', retcode=3)
207
file('foo.c', 'wt').write('int main() {}')
208
self.runbzr(['add', 'foo.c'])
209
self.runbzr(["commit", "-m", ""] , retcode=3)
338
211
def test_other_branch_commit(self):
339
212
# this branch is to ensure consistent behaviour, whether we're run
340
213
# inside a branch, or not.
341
outer_tree = self.make_branch_and_tree('.')
342
inner_tree = self.make_branch_and_tree('branch')
343
self.build_tree_contents([
344
('branch/foo.c', 'int main() {}'),
345
('branch/bar.c', 'int main() {}')])
346
inner_tree.add(['foo.c', 'bar.c'])
214
os.mkdir('empty_branch')
215
os.chdir('empty_branch')
220
file('foo.c', 'wt').write('int main() {}')
221
file('bar.c', 'wt').write('int main() {}')
223
self.runbzr(['add', 'branch/foo.c'])
224
self.runbzr(['add', 'branch'])
347
225
# can't commit files in different trees; sane error
348
self.run_bzr('commit -m newstuff branch/foo.c .', retcode=3)
349
# can commit to branch - records foo.c only
350
self.run_bzr('commit -m newstuff branch/foo.c')
351
# can commit to branch - records bar.c
352
self.run_bzr('commit -m newstuff branch')
354
self.run_bzr_error(["No changes to commit"], 'commit -m newstuff branch')
226
self.runbzr('commit -m newstuff branch/foo.c .', retcode=3)
227
self.runbzr('commit -m newstuff branch/foo.c')
228
self.runbzr('commit -m newstuff branch')
229
self.runbzr('commit -m newstuff branch', retcode=3)
356
231
def test_out_of_date_tree_commit(self):
357
232
# check we get an error code and a clear message committing with an out
358
233
# of date checkout
359
tree = self.make_branch_and_tree('branch')
234
self.make_branch_and_tree('branch')
360
235
# make a checkout
361
checkout = tree.branch.create_checkout('checkout', lightweight=True)
236
self.runbzr('checkout --lightweight branch checkout')
362
237
# commit to the original branch to make the checkout out of date
363
tree.commit('message branch', allow_pointless=True)
238
self.runbzr('commit --unchanged -m message branch')
364
239
# now commit to the checkout should emit
365
240
# ERROR: Out of date with the branch, 'bzr update' is suggested
366
output = self.run_bzr('commit --unchanged -m checkout_message '
241
output = self.runbzr('commit --unchanged -m checkout_message '
367
242
'checkout', retcode=3)
368
243
self.assertEqual(output,
370
"bzr: ERROR: Working tree is out of date, please "
371
"run 'bzr update'.\n"))
245
"bzr: ERROR: Working tree is out of date, please run "
373
248
def test_local_commit_unbound(self):
374
249
# a --local commit on an unbound branch is an error
375
250
self.make_branch_and_tree('.')
376
out, err = self.run_bzr('commit --local', retcode=3)
251
out, err = self.run_bzr('commit', '--local', retcode=3)
377
252
self.assertEqualDiff('', out)
378
253
self.assertEqualDiff('bzr: ERROR: Cannot perform local-only commits '
379
254
'on unbound branches.\n', err)
381
256
def test_commit_a_text_merge_in_a_checkout(self):
382
257
# checkouts perform multiple actions in a transaction across bond
383
258
# branches and their master, and have been observed to fail in the
384
# past. This is a user story reported to fail in bug #43959 where
259
# past. This is a user story reported to fail in bug #43959 where
385
260
# a merge done in a checkout (using the update command) failed to
386
261
# commit correctly.
387
trunk = self.make_branch_and_tree('trunk')
389
u1 = trunk.branch.create_checkout('u1')
390
self.build_tree_contents([('u1/hosts', 'initial contents\n')])
392
self.run_bzr('commit -m add-hosts u1')
394
u2 = trunk.branch.create_checkout('u2')
395
self.build_tree_contents([('u2/hosts', 'altered in u2\n')])
396
self.run_bzr('commit -m checkin-from-u2 u2')
262
self.run_bzr('init', 'trunk')
264
self.run_bzr('checkout', 'trunk', 'u1')
265
self.build_tree_contents([('u1/hosts', 'initial contents')])
266
self.run_bzr('add', 'u1/hosts')
267
self.run_bzr('commit', '-m', 'add hosts', 'u1')
269
self.run_bzr('checkout', 'trunk', 'u2')
270
self.build_tree_contents([('u2/hosts', 'altered in u2')])
271
self.run_bzr('commit', '-m', 'checkin from u2', 'u2')
398
273
# make an offline commits
399
self.build_tree_contents([('u1/hosts', 'first offline change in u1\n')])
400
self.run_bzr('commit -m checkin-offline --local u1')
274
self.build_tree_contents([('u1/hosts', 'first offline change in u1')])
275
self.run_bzr('commit', '-m', 'checkin offline', '--local', 'u1')
402
277
# now try to pull in online work from u2, and then commit our offline
403
278
# work as a merge
404
279
# retcode 1 as we expect a text conflict
405
self.run_bzr('update u1', retcode=1)
406
self.assertFileEqual('''\
408
first offline change in u1
415
self.run_bzr('resolved u1/hosts')
280
self.run_bzr('update', 'u1', retcode=1)
281
self.run_bzr('resolved', 'u1/hosts')
416
282
# add a text change here to represent resolving the merge conflicts in
417
283
# favour of a new version of the file not identical to either the u1
418
284
# version or the u2 version.
419
285
self.build_tree_contents([('u1/hosts', 'merge resolution\n')])
420
self.run_bzr('commit -m checkin-merge-of-the-offline-work-from-u1 u1')
422
def test_commit_exclude_excludes_modified_files(self):
423
"""Commit -x foo should ignore changes to foo."""
424
tree = self.make_branch_and_tree('.')
425
self.build_tree(['a', 'b', 'c'])
426
tree.smart_add(['.'])
427
out, err = self.run_bzr(['commit', '-m', 'test', '-x', 'b'])
428
self.assertFalse('added b' in out)
429
self.assertFalse('added b' in err)
430
# If b was excluded it will still be 'added' in status.
431
out, err = self.run_bzr(['added'])
432
self.assertEqual('b\n', out)
433
self.assertEqual('', err)
435
def test_commit_exclude_twice_uses_both_rules(self):
436
"""Commit -x foo -x bar should ignore changes to foo and bar."""
437
tree = self.make_branch_and_tree('.')
438
self.build_tree(['a', 'b', 'c'])
439
tree.smart_add(['.'])
440
out, err = self.run_bzr(['commit', '-m', 'test', '-x', 'b', '-x', 'c'])
441
self.assertFalse('added b' in out)
442
self.assertFalse('added c' in out)
443
self.assertFalse('added b' in err)
444
self.assertFalse('added c' in err)
445
# If b was excluded it will still be 'added' in status.
446
out, err = self.run_bzr(['added'])
447
self.assertTrue('b\n' in out)
448
self.assertTrue('c\n' in out)
449
self.assertEqual('', err)
451
def test_commit_respects_spec_for_removals(self):
452
"""Commit with a file spec should only commit removals that match"""
453
t = self.make_branch_and_tree('.')
454
self.build_tree(['file-a', 'dir-a/', 'dir-a/file-b'])
455
t.add(['file-a', 'dir-a', 'dir-a/file-b'])
457
t.remove(['file-a', 'dir-a/file-b'])
459
result = self.run_bzr('commit . -m removed-file-b')[1]
460
self.assertNotContainsRe(result, 'file-a')
461
result = self.run_bzr('status')[0]
462
self.assertContainsRe(result, 'removed:\n file-a')
464
def test_strict_commit(self):
465
"""Commit with --strict works if everything is known"""
466
ignores._set_user_ignores([])
467
tree = self.make_branch_and_tree('tree')
468
self.build_tree(['tree/a'])
470
# A simple change should just work
471
self.run_bzr('commit --strict -m adding-a',
474
def test_strict_commit_no_changes(self):
475
"""commit --strict gives "no changes" if there is nothing to commit"""
476
tree = self.make_branch_and_tree('tree')
477
self.build_tree(['tree/a'])
479
tree.commit('adding a')
481
# With no changes, it should just be 'no changes'
482
# Make sure that commit is failing because there is nothing to do
483
self.run_bzr_error(['No changes to commit'],
484
'commit --strict -m no-changes',
487
# But --strict doesn't care if you supply --unchanged
488
self.run_bzr('commit --strict --unchanged -m no-changes',
491
def test_strict_commit_unknown(self):
492
"""commit --strict fails if a file is unknown"""
493
tree = self.make_branch_and_tree('tree')
494
self.build_tree(['tree/a'])
496
tree.commit('adding a')
498
# Add one file so there is a change, but forget the other
499
self.build_tree(['tree/b', 'tree/c'])
501
self.run_bzr_error(['Commit refused because there are unknown files'],
502
'commit --strict -m add-b',
505
# --no-strict overrides --strict
506
self.run_bzr('commit --strict -m add-b --no-strict',
509
def test_fixes_bug_output(self):
510
"""commit --fixes=lp:23452 succeeds without output."""
511
tree = self.make_branch_and_tree('tree')
512
self.build_tree(['tree/hello.txt'])
513
tree.add('hello.txt')
514
output, err = self.run_bzr(
515
'commit -m hello --fixes=lp:23452 tree/hello.txt')
516
self.assertEqual('', output)
517
self.assertContainsRe(err, 'Committing to: .*\n'
519
'Committed revision 1\.\n')
521
def test_no_bugs_no_properties(self):
522
"""If no bugs are fixed, the bugs property is not set.
524
see https://beta.launchpad.net/bzr/+bug/109613
526
tree = self.make_branch_and_tree('tree')
527
self.build_tree(['tree/hello.txt'])
528
tree.add('hello.txt')
529
self.run_bzr( 'commit -m hello tree/hello.txt')
530
# Get the revision properties, ignoring the branch-nick property, which
531
# we don't care about for this test.
532
last_rev = tree.branch.repository.get_revision(tree.last_revision())
533
properties = dict(last_rev.properties)
534
del properties['branch-nick']
535
self.assertFalse('bugs' in properties)
537
def test_fixes_bug_sets_property(self):
538
"""commit --fixes=lp:234 sets the lp:234 revprop to 'fixed'."""
539
tree = self.make_branch_and_tree('tree')
540
self.build_tree(['tree/hello.txt'])
541
tree.add('hello.txt')
542
self.run_bzr('commit -m hello --fixes=lp:234 tree/hello.txt')
544
# Get the revision properties, ignoring the branch-nick property, which
545
# we don't care about for this test.
546
last_rev = tree.branch.repository.get_revision(tree.last_revision())
547
properties = dict(last_rev.properties)
548
del properties['branch-nick']
550
self.assertEqual({'bugs': 'https://launchpad.net/bugs/234 fixed'},
553
def test_fixes_multiple_bugs_sets_properties(self):
554
"""--fixes can be used more than once to show that bugs are fixed."""
555
tree = self.make_branch_and_tree('tree')
556
self.build_tree(['tree/hello.txt'])
557
tree.add('hello.txt')
558
self.run_bzr('commit -m hello --fixes=lp:123 --fixes=lp:235'
561
# Get the revision properties, ignoring the branch-nick property, which
562
# we don't care about for this test.
563
last_rev = tree.branch.repository.get_revision(tree.last_revision())
564
properties = dict(last_rev.properties)
565
del properties['branch-nick']
568
{'bugs': 'https://launchpad.net/bugs/123 fixed\n'
569
'https://launchpad.net/bugs/235 fixed'},
572
def test_fixes_bug_with_alternate_trackers(self):
573
"""--fixes can be used on a properly configured branch to mark bug
574
fixes on multiple trackers.
576
tree = self.make_branch_and_tree('tree')
577
tree.branch.get_config().set_user_option(
578
'trac_twisted_url', 'http://twistedmatrix.com/trac')
579
self.build_tree(['tree/hello.txt'])
580
tree.add('hello.txt')
581
self.run_bzr('commit -m hello --fixes=lp:123 --fixes=twisted:235 tree/')
583
# Get the revision properties, ignoring the branch-nick property, which
584
# we don't care about for this test.
585
last_rev = tree.branch.repository.get_revision(tree.last_revision())
586
properties = dict(last_rev.properties)
587
del properties['branch-nick']
590
{'bugs': 'https://launchpad.net/bugs/123 fixed\n'
591
'http://twistedmatrix.com/trac/ticket/235 fixed'},
594
def test_fixes_unknown_bug_prefix(self):
595
tree = self.make_branch_and_tree('tree')
596
self.build_tree(['tree/hello.txt'])
597
tree.add('hello.txt')
599
["Unrecognized bug %s. Commit refused." % 'xxx:123'],
600
'commit -m add-b --fixes=xxx:123',
603
def test_fixes_invalid_bug_number(self):
604
tree = self.make_branch_and_tree('tree')
605
self.build_tree(['tree/hello.txt'])
606
tree.add('hello.txt')
608
["Did not understand bug identifier orange: Must be an integer. "
609
"See \"bzr help bugs\" for more information on this feature.\n"
611
'commit -m add-b --fixes=lp:orange',
614
def test_fixes_invalid_argument(self):
615
"""Raise an appropriate error when the fixes argument isn't tag:id."""
616
tree = self.make_branch_and_tree('tree')
617
self.build_tree(['tree/hello.txt'])
618
tree.add('hello.txt')
620
[r"Invalid bug orange. Must be in the form of 'tracker:id'\. "
621
r"See \"bzr help bugs\" for more information on this feature.\n"
622
r"Commit refused\."],
623
'commit -m add-b --fixes=orange',
626
def test_no_author(self):
627
"""If the author is not specified, the author property is not set."""
628
tree = self.make_branch_and_tree('tree')
629
self.build_tree(['tree/hello.txt'])
630
tree.add('hello.txt')
631
self.run_bzr( 'commit -m hello tree/hello.txt')
632
last_rev = tree.branch.repository.get_revision(tree.last_revision())
633
properties = last_rev.properties
634
self.assertFalse('author' in properties)
636
def test_author_sets_property(self):
637
"""commit --author='John Doe <jdoe@example.com>' sets the author
640
tree = self.make_branch_and_tree('tree')
641
self.build_tree(['tree/hello.txt'])
642
tree.add('hello.txt')
643
self.run_bzr(["commit", '-m', 'hello',
644
'--author', u'John D\xf6 <jdoe@example.com>',
646
last_rev = tree.branch.repository.get_revision(tree.last_revision())
647
properties = last_rev.properties
648
self.assertEqual(u'John D\xf6 <jdoe@example.com>', properties['authors'])
650
def test_author_no_email(self):
651
"""Author's name without an email address is allowed, too."""
652
tree = self.make_branch_and_tree('tree')
653
self.build_tree(['tree/hello.txt'])
654
tree.add('hello.txt')
655
out, err = self.run_bzr("commit -m hello --author='John Doe' "
657
last_rev = tree.branch.repository.get_revision(tree.last_revision())
658
properties = last_rev.properties
659
self.assertEqual('John Doe', properties['authors'])
661
def test_multiple_authors(self):
662
"""Multiple authors can be specyfied, and all are stored."""
663
tree = self.make_branch_and_tree('tree')
664
self.build_tree(['tree/hello.txt'])
665
tree.add('hello.txt')
666
out, err = self.run_bzr("commit -m hello --author='John Doe' "
667
"--author='Jane Rey' tree/hello.txt")
668
last_rev = tree.branch.repository.get_revision(tree.last_revision())
669
properties = last_rev.properties
670
self.assertEqual('John Doe\nJane Rey', properties['authors'])
672
def test_commit_time(self):
673
tree = self.make_branch_and_tree('tree')
674
self.build_tree(['tree/hello.txt'])
675
tree.add('hello.txt')
676
out, err = self.run_bzr("commit -m hello "
677
"--commit-time='2009-10-10 08:00:00 +0100' tree/hello.txt")
678
last_rev = tree.branch.repository.get_revision(tree.last_revision())
680
'Sat 2009-10-10 08:00:00 +0100',
681
osutils.format_date(last_rev.timestamp, last_rev.timezone))
683
def test_commit_time_bad_time(self):
684
tree = self.make_branch_and_tree('tree')
685
self.build_tree(['tree/hello.txt'])
686
tree.add('hello.txt')
687
out, err = self.run_bzr("commit -m hello "
688
"--commit-time='NOT A TIME' tree/hello.txt", retcode=3)
689
self.assertStartsWith(
690
err, "bzr: ERROR: Could not parse --commit-time:")
692
def test_partial_commit_with_renames_in_tree(self):
693
# this test illustrates bug #140419
694
t = self.make_branch_and_tree('.')
695
self.build_tree(['dir/', 'dir/a', 'test'])
696
t.add(['dir/', 'dir/a', 'test'])
697
t.commit('initial commit')
698
# important part: file dir/a should change parent
699
# and should appear before old parent
700
# then during partial commit we have error
701
# parent_id {dir-XXX} not in inventory
702
t.rename_one('dir/a', 'a')
703
self.build_tree_contents([('test', 'changes in test')])
705
out, err = self.run_bzr('commit test -m "partial commit"')
706
self.assertEquals('', out)
707
self.assertContainsRe(err, r'modified test\nCommitted revision 2.')
709
def test_commit_readonly_checkout(self):
710
# https://bugs.launchpad.net/bzr/+bug/129701
711
# "UnlockableTransport error trying to commit in checkout of readonly
713
self.make_branch('master')
714
master = BzrDir.open_from_transport(
715
self.get_readonly_transport('master')).open_branch()
716
master.create_checkout('checkout')
717
out, err = self.run_bzr(['commit', '--unchanged', '-mfoo', 'checkout'],
719
self.assertContainsRe(err,
720
r'^bzr: ERROR: Cannot lock.*readonly transport')
722
def setup_editor(self):
723
# Test that commit template hooks work
724
if sys.platform == "win32":
725
f = file('fed.bat', 'w')
726
f.write('@rem dummy fed')
728
self.overrideEnv('BZR_EDITOR', "fed.bat")
730
f = file('fed.sh', 'wb')
731
f.write('#!/bin/sh\n')
733
os.chmod('fed.sh', 0755)
734
self.overrideEnv('BZR_EDITOR', "./fed.sh")
736
def setup_commit_with_template(self):
738
msgeditor.hooks.install_named_hook("commit_message_template",
739
lambda commit_obj, msg: "save me some typing\n", None)
740
tree = self.make_branch_and_tree('tree')
741
self.build_tree(['tree/hello.txt'])
742
tree.add('hello.txt')
745
def test_commit_hook_template_accepted(self):
746
tree = self.setup_commit_with_template()
747
out, err = self.run_bzr("commit tree/hello.txt", stdin="y\n")
748
last_rev = tree.branch.repository.get_revision(tree.last_revision())
749
self.assertEqual('save me some typing\n', last_rev.message)
751
def test_commit_hook_template_rejected(self):
752
tree = self.setup_commit_with_template()
753
expected = tree.last_revision()
754
out, err = self.run_bzr_error(["empty commit message"],
755
"commit tree/hello.txt", stdin="n\n")
756
self.assertEqual(expected, tree.last_revision())
758
def test_commit_without_username(self):
759
"""Ensure commit error if username is not set.
761
self.run_bzr(['init', 'foo'])
763
open('foo.txt', 'w').write('hello')
764
self.run_bzr(['add'])
765
self.overrideEnv('EMAIL', None)
766
self.overrideEnv('BZR_EMAIL', None)
767
# Also, make sure that it's not inferred from mailname.
768
self.overrideAttr(config, '_auto_user_id',
769
lambda: (None, None))
770
out, err = self.run_bzr(['commit', '-m', 'initial'], 3)
771
self.assertContainsRe(err, 'Unable to determine your name')
773
def test_commit_recursive_checkout(self):
774
"""Ensure that a commit to a recursive checkout fails cleanly.
776
self.run_bzr(['init', 'test_branch'])
777
self.run_bzr(['checkout', 'test_branch', 'test_checkout'])
778
os.chdir('test_checkout')
779
self.run_bzr(['bind', '.']) # bind to self
780
open('foo.txt', 'w').write('hello')
781
self.run_bzr(['add'])
782
out, err = self.run_bzr(['commit', '-m', 'addedfoo'], 3)
783
self.assertEqual(out, '')
784
self.assertContainsRe(err,
785
'Branch.*test_checkout.*appears to be bound to itself')
286
self.run_bzr('commit', '-m', 'checkin merge of the offline work from u1', 'u1')