1
# Copyright (C) 2006-2010 Canonical Ltd
1
# Copyright (C) 2006-2011 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
18
18
"""Tests for the commit CLI of bzr."""
25
from testtools.matchers import DocTestMatches
24
27
from bzrlib import (
32
33
from bzrlib.bzrdir import BzrDir
33
34
from bzrlib.tests import (
36
UnicodeFilenameFeature,
38
38
from bzrlib.tests import TestCaseWithTransport
39
from bzrlib.tests.matchers import ContainsNoVfsCalls
41
42
class TestCommit(TestCaseWithTransport):
47
48
self.build_tree(['hello.txt'])
48
49
out,err = self.run_bzr('commit -m empty', retcode=3)
49
50
self.assertEqual('', out)
50
self.assertContainsRe(err, 'bzr: ERROR: No changes to commit\.'
51
' Use --unchanged to commit anyhow.\n')
52
# 1) We really don't want 'aborting commit write group' anymore.
53
# 2) bzr: ERROR: is a really long line, so we wrap it with '\'
58
bzr: ERROR: No changes to commit.\
59
Please 'bzr add' the files you want to commit,\
60
or use --unchanged to force an empty commit.
61
""", flags=doctest.ELLIPSIS|doctest.REPORT_UDIFF))
53
63
def test_commit_success(self):
54
64
"""Successful commit should not leave behind a bzr-commit-* file"""
60
70
self.run_bzr(["commit", "--unchanged", "-m", u'foo\xb5'])
61
71
self.assertEqual('', self.run_bzr('unknowns')[0])
73
def test_commit_lossy_native(self):
74
"""A --lossy option to commit is supported."""
75
self.make_branch_and_tree('.')
76
self.run_bzr('commit --lossy --unchanged -m message')
77
self.assertEqual('', self.run_bzr('unknowns')[0])
79
def test_commit_lossy_foreign(self):
80
test_foreign.register_dummy_foreign_for_test(self)
81
self.make_branch_and_tree('.',
82
format=test_foreign.DummyForeignVcsDirFormat())
83
self.run_bzr('commit --lossy --unchanged -m message')
84
output = self.run_bzr('revision-info')[0]
85
self.assertTrue(output.startswith('1 dummy-'))
63
87
def test_commit_with_path(self):
64
88
"""Commit tree with path of root specified"""
65
89
a_tree = self.make_branch_and_tree('a')
79
103
self.run_bzr('resolved b/a_file')
80
104
self.run_bzr(['commit', '-m', 'merge into b', 'b'])
83
106
def test_10_verbose_commit(self):
84
107
"""Add one file and examine verbose commit output"""
85
108
tree = self.make_branch_and_tree('.')
113
136
def test_unicode_commit_message_is_filename(self):
114
137
"""Unicode commit message same as a filename (Bug #563646).
116
self.requireFeature(UnicodeFilenameFeature)
139
self.requireFeature(features.UnicodeFilenameFeature)
117
140
file_name = u'\N{euro sign}'
118
141
self.run_bzr(['init'])
119
142
open(file_name, 'w').write('hello world')
146
169
osutils.get_terminal_encoding = default_get_terminal_enc
171
def test_non_ascii_file_unversioned_utf8(self):
172
self.requireFeature(features.UnicodeFilenameFeature)
173
tree = self.make_branch_and_tree(".")
174
self.build_tree(["f"])
176
out, err = self.run_bzr(["commit", "-m", "Wrong filename", u"\xa7"],
177
encoding="utf-8", retcode=3)
178
self.assertContainsRe(err, "(?m)not versioned: \"\xc2\xa7\"$")
180
def test_non_ascii_file_unversioned_iso_8859_5(self):
181
self.requireFeature(features.UnicodeFilenameFeature)
182
tree = self.make_branch_and_tree(".")
183
self.build_tree(["f"])
185
out, err = self.run_bzr(["commit", "-m", "Wrong filename", u"\xa7"],
186
encoding="iso-8859-5", retcode=3)
187
self.expectFailure("Error messages are always written as UTF-8",
188
self.assertNotContainsString, err, "\xc2\xa7")
189
self.assertContainsRe(err, "(?m)not versioned: \"\xfd\"$")
148
191
def test_warn_about_forgotten_commit_message(self):
149
192
"""Test that the lack of -m parameter is caught"""
150
193
wt = self.make_branch_and_tree('.')
307
350
tree = self.make_branch_and_tree('.')
308
351
self.build_tree_contents([('foo.c', 'int main() {}')])
309
352
tree.add('foo.c')
310
self.run_bzr('commit -m ""', retcode=3)
312
def test_unsupported_encoding_commit_message(self):
313
if sys.platform == 'win32':
314
raise tests.TestNotApplicable('Win32 parses arguments directly'
315
' as Unicode, so we can\'t pass invalid non-ascii')
316
tree = self.make_branch_and_tree('.')
317
self.build_tree_contents([('foo.c', 'int main() {}')])
319
# LANG env variable has no effect on Windows
320
# but some characters anyway cannot be represented
321
# in default user encoding
322
char = probe_bad_non_ascii(osutils.get_user_encoding())
324
raise TestSkipped('Cannot find suitable non-ascii character'
325
'for user_encoding (%s)' % osutils.get_user_encoding())
326
out,err = self.run_bzr_subprocess('commit -m "%s"' % char,
328
env_changes={'LANG': 'C'})
329
self.assertContainsRe(err, r'bzrlib.errors.BzrError: Parameter.*is '
330
'unsupported by the current encoding.')
353
self.run_bzr('commit -m ""')
332
355
def test_other_branch_commit(self):
333
356
# this branch is to ensure consistent behaviour, whether we're run
594
617
'commit -m add-b --fixes=xxx:123',
595
618
working_dir='tree')
620
def test_fixes_bug_with_default_tracker(self):
621
"""commit --fixes=234 uses the default bug tracker."""
622
tree = self.make_branch_and_tree('tree')
623
self.build_tree(['tree/hello.txt'])
624
tree.add('hello.txt')
626
["bzr: ERROR: No tracker specified for bug 123. Use the form "
627
"'tracker:id' or specify a default bug tracker using the "
628
"`bugtracker` option.\n"
629
"See \"bzr help bugs\" for more information on this feature. "
631
'commit -m add-b --fixes=123',
633
tree.branch.get_config().set_user_option("bugtracker", "lp")
634
self.run_bzr('commit -m hello --fixes=234 tree/hello.txt')
635
last_rev = tree.branch.repository.get_revision(tree.last_revision())
636
self.assertEqual('https://launchpad.net/bugs/234 fixed',
637
last_rev.properties['bugs'])
597
639
def test_fixes_invalid_bug_number(self):
598
640
tree = self.make_branch_and_tree('tree')
599
641
self.build_tree(['tree/hello.txt'])
611
653
self.build_tree(['tree/hello.txt'])
612
654
tree.add('hello.txt')
613
655
self.run_bzr_error(
614
[r"Invalid bug orange. Must be in the form of 'tracker:id'\. "
615
r"See \"bzr help bugs\" for more information on this feature.\n"
616
r"Commit refused\."],
617
'commit -m add-b --fixes=orange',
656
[r"Invalid bug orange:apples:bananas. Must be in the form of "
657
r"'tracker:id'\. See \"bzr help bugs\" for more information on "
658
r"this feature.\nCommit refused\."],
659
'commit -m add-b --fixes=orange:apples:bananas',
618
660
working_dir='tree')
620
662
def test_no_author(self):
683
725
self.assertStartsWith(
684
726
err, "bzr: ERROR: Could not parse --commit-time:")
728
def test_commit_time_missing_tz(self):
729
tree = self.make_branch_and_tree('tree')
730
self.build_tree(['tree/hello.txt'])
731
tree.add('hello.txt')
732
out, err = self.run_bzr("commit -m hello "
733
"--commit-time='2009-10-10 08:00:00' tree/hello.txt", retcode=3)
734
self.assertStartsWith(
735
err, "bzr: ERROR: Could not parse --commit-time:")
736
# Test that it is actually checking and does not simply crash with
737
# some other exception
738
self.assertContainsString(err, "missing a timezone offset")
686
740
def test_partial_commit_with_renames_in_tree(self):
687
741
# this test illustrates bug #140419
688
742
t = self.make_branch_and_tree('.')
719
773
f = file('fed.bat', 'w')
720
774
f.write('@rem dummy fed')
722
osutils.set_or_unset_env('BZR_EDITOR', "fed.bat")
776
self.overrideEnv('BZR_EDITOR', "fed.bat")
724
778
f = file('fed.sh', 'wb')
725
779
f.write('#!/bin/sh\n')
727
781
os.chmod('fed.sh', 0755)
728
osutils.set_or_unset_env('BZR_EDITOR', "./fed.sh")
782
self.overrideEnv('BZR_EDITOR', "./fed.sh")
730
784
def setup_commit_with_template(self):
731
785
self.setup_editor()
736
790
tree.add('hello.txt')
793
def test_edit_empty_message(self):
794
tree = self.make_branch_and_tree('tree')
796
self.build_tree(['tree/hello.txt'])
797
tree.add('hello.txt')
798
out, err = self.run_bzr("commit tree/hello.txt", retcode=3,
800
self.assertContainsRe(err,
801
"bzr: ERROR: Empty commit message specified")
739
803
def test_commit_hook_template_accepted(self):
740
804
tree = self.setup_commit_with_template()
741
805
out, err = self.run_bzr("commit tree/hello.txt", stdin="y\n")
745
809
def test_commit_hook_template_rejected(self):
746
810
tree = self.setup_commit_with_template()
747
811
expected = tree.last_revision()
748
out, err = self.run_bzr_error(["empty commit message"],
812
out, err = self.run_bzr_error(["Empty commit message specified."
813
" Please specify a commit message with either"
814
" --message or --file or leave a blank message"
815
" with --message \"\"."],
749
816
"commit tree/hello.txt", stdin="n\n")
750
817
self.assertEqual(expected, tree.last_revision())
819
def test_set_commit_message(self):
820
msgeditor.hooks.install_named_hook("set_commit_message",
821
lambda commit_obj, msg: "save me some typing\n", None)
822
tree = self.make_branch_and_tree('tree')
823
self.build_tree(['tree/hello.txt'])
824
tree.add('hello.txt')
825
out, err = self.run_bzr("commit tree/hello.txt")
826
last_rev = tree.branch.repository.get_revision(tree.last_revision())
827
self.assertEqual('save me some typing\n', last_rev.message)
752
829
def test_commit_without_username(self):
753
830
"""Ensure commit error if username is not set.
757
834
open('foo.txt', 'w').write('hello')
758
835
self.run_bzr(['add'])
759
osutils.set_or_unset_env('EMAIL', None)
760
osutils.set_or_unset_env('BZR_EMAIL', None)
836
self.overrideEnv('EMAIL', None)
837
self.overrideEnv('BZR_EMAIL', None)
838
# Also, make sure that it's not inferred from mailname.
839
self.overrideAttr(config, '_auto_user_id',
840
lambda: (None, None))
761
841
out, err = self.run_bzr(['commit', '-m', 'initial'], 3)
762
842
self.assertContainsRe(err, 'Unable to determine your name')
775
855
self.assertContainsRe(err,
776
856
'Branch.*test_checkout.*appears to be bound to itself')
859
class TestSmartServerCommit(TestCaseWithTransport):
861
def test_commit_to_lightweight(self):
862
self.setup_smart_server_with_call_log()
863
t = self.make_branch_and_tree('from')
864
for count in range(9):
865
t.commit(message='commit %d' % count)
866
out, err = self.run_bzr(['checkout', '--lightweight', self.get_url('from'),
868
self.reset_smart_call_log()
869
self.build_tree(['target/afile'])
870
self.run_bzr(['add', 'target/afile'])
871
out, err = self.run_bzr(['commit', '-m', 'do something', 'target'])
872
# This figure represent the amount of work to perform this use case. It
873
# is entirely ok to reduce this number if a test fails due to rpc_count
874
# being too low. If rpc_count increases, more network roundtrips have
875
# become necessary for this use case. Please do not adjust this number
876
# upwards without agreement from bzr's network support maintainers.
877
self.assertLength(213, self.hpss_calls)
878
self.expectFailure("commit still uses VFS calls",
879
self.assertThat, self.hpss_calls, ContainsNoVfsCalls)