~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/blackbox/test_commit.py

  • Committer: John Arbash Meinel
  • Date: 2011-05-11 11:35:28 UTC
  • mto: This revision was merged to the branch mainline in revision 5851.
  • Revision ID: john@arbash-meinel.com-20110511113528-qepibuwxicjrbb2h
Break compatibility with python <2.6.

This includes auditing the code for places where we were doing
explicit 'sys.version' checks and removing them as appropriate.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
1
# Copyright (C) 2006-2011 Canonical Ltd
2
2
#
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
12
12
#
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
 
18
18
"""Tests for the commit CLI of bzr."""
19
19
 
 
20
import doctest
20
21
import os
 
22
import re
21
23
import sys
22
24
 
23
 
import bzrlib
 
25
from testtools.matchers import DocTestMatches
 
26
 
24
27
from bzrlib import (
 
28
    config,
25
29
    osutils,
26
30
    ignores,
27
 
    osutils,
 
31
    msgeditor,
 
32
    tests,
28
33
    )
29
34
from bzrlib.bzrdir import BzrDir
30
35
from bzrlib.tests import (
31
36
    probe_bad_non_ascii,
 
37
    test_foreign,
32
38
    TestSkipped,
 
39
    UnicodeFilenameFeature,
33
40
    )
34
 
from bzrlib.tests.blackbox import ExternalBase
35
 
 
36
 
 
37
 
class TestCommit(ExternalBase):
 
41
from bzrlib.tests import TestCaseWithTransport
 
42
 
 
43
 
 
44
class TestCommit(TestCaseWithTransport):
38
45
 
39
46
    def test_05_empty_commit(self):
40
47
        """Commit of tree with no versioned files should fail"""
43
50
        self.build_tree(['hello.txt'])
44
51
        out,err = self.run_bzr('commit -m empty', retcode=3)
45
52
        self.assertEqual('', out)
46
 
        self.assertContainsRe(err, 'bzr: ERROR: no changes to commit\.'
47
 
                                  ' use --unchanged to commit anyhow\n')
 
53
        # Two ugly bits here.
 
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 '\'
 
56
        self.assertThat(
 
57
            err,
 
58
            DocTestMatches("""\
 
59
Committing to: ...
 
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))
48
65
 
49
66
    def test_commit_success(self):
50
67
        """Successful commit should not leave behind a bzr-commit-* file"""
56
73
        self.run_bzr(["commit", "--unchanged", "-m", u'foo\xb5'])
57
74
        self.assertEqual('', self.run_bzr('unknowns')[0])
58
75
 
 
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])
 
81
 
 
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-'))
 
89
 
59
90
    def test_commit_with_path(self):
60
91
        """Commit tree with path of root specified"""
61
92
        a_tree = self.make_branch_and_tree('a')
75
106
        self.run_bzr('resolved b/a_file')
76
107
        self.run_bzr(['commit', '-m', 'merge into b', 'b'])
77
108
 
78
 
 
79
109
    def test_10_verbose_commit(self):
80
110
        """Add one file and examine verbose commit output"""
81
111
        tree = self.make_branch_and_tree('.')
83
113
        tree.add("hello.txt")
84
114
        out,err = self.run_bzr('commit -m added')
85
115
        self.assertEqual('', out)
86
 
        self.assertContainsRe(err, '^Committing revision 1 to ".*"\.\n'
 
116
        self.assertContainsRe(err, '^Committing to: .*\n'
87
117
                              'added hello.txt\n'
88
118
                              'Committed revision 1.\n$',)
89
119
 
102
132
        self.build_tree_contents([('hello.txt', 'new contents')])
103
133
        out, err = self.run_bzr('commit -m modified')
104
134
        self.assertEqual('', out)
105
 
        self.assertContainsRe(err, '^Committing revision 2 to ".*"\.\n'
 
135
        self.assertContainsRe(err, '^Committing to: .*\n'
106
136
                              'modified hello\.txt\n'
107
137
                              'Committed revision 2\.\n$')
108
138
 
 
139
    def test_unicode_commit_message_is_filename(self):
 
140
        """Unicode commit message same as a filename (Bug #563646).
 
141
        """
 
142
        self.requireFeature(UnicodeFilenameFeature)
 
143
        file_name = u'\N{euro sign}'
 
144
        self.run_bzr(['init'])
 
145
        open(file_name, 'w').write('hello world')
 
146
        self.run_bzr(['add'])
 
147
        out, err = self.run_bzr(['commit', '-m', file_name])
 
148
        reflags = re.MULTILINE|re.DOTALL|re.UNICODE
 
149
        te = osutils.get_terminal_encoding()
 
150
        self.assertContainsRe(err.decode(te),
 
151
            u'The commit message is a file name:',
 
152
            flags=reflags)
 
153
 
 
154
        # Run same test with a filename that causes encode
 
155
        # error for the terminal encoding. We do this
 
156
        # by forcing terminal encoding of ascii for
 
157
        # osutils.get_terminal_encoding which is used
 
158
        # by ui.text.show_warning
 
159
        default_get_terminal_enc = osutils.get_terminal_encoding
 
160
        try:
 
161
            osutils.get_terminal_encoding = lambda trace=None: 'ascii'
 
162
            file_name = u'foo\u1234'
 
163
            open(file_name, 'w').write('hello world')
 
164
            self.run_bzr(['add'])
 
165
            out, err = self.run_bzr(['commit', '-m', file_name])
 
166
            reflags = re.MULTILINE|re.DOTALL|re.UNICODE
 
167
            te = osutils.get_terminal_encoding()
 
168
            self.assertContainsRe(err.decode(te, 'replace'),
 
169
                u'The commit message is a file name:',
 
170
                flags=reflags)
 
171
        finally:
 
172
            osutils.get_terminal_encoding = default_get_terminal_enc
 
173
 
 
174
    def test_warn_about_forgotten_commit_message(self):
 
175
        """Test that the lack of -m parameter is caught"""
 
176
        wt = self.make_branch_and_tree('.')
 
177
        self.build_tree(['one', 'two'])
 
178
        wt.add(['two'])
 
179
        out, err = self.run_bzr('commit -m one two')
 
180
        self.assertContainsRe(err, "The commit message is a file name")
 
181
 
109
182
    def test_verbose_commit_renamed(self):
110
183
        # Verbose commit of renamed file should say so
111
184
        wt = self.prepare_simple_history()
112
185
        wt.rename_one('hello.txt', 'gutentag.txt')
113
186
        out, err = self.run_bzr('commit -m renamed')
114
187
        self.assertEqual('', out)
115
 
        self.assertContainsRe(err, '^Committing revision 2 to ".*"\.\n'
 
188
        self.assertContainsRe(err, '^Committing to: .*\n'
116
189
                              'renamed hello\.txt => gutentag\.txt\n'
117
190
                              'Committed revision 2\.$\n')
118
191
 
124
197
        wt.rename_one('hello.txt', 'subdir/hello.txt')
125
198
        out, err = self.run_bzr('commit -m renamed')
126
199
        self.assertEqual('', out)
127
 
        self.assertContainsRe(err, '^Committing revision 2 to ".*"\.\n'
128
 
                              'added subdir\n'
129
 
                              'renamed hello\.txt => subdir/hello\.txt\n'
130
 
                              'Committed revision 2\.\n$')
 
200
        self.assertEqual(set([
 
201
            'Committing to: %s/' % osutils.getcwd(),
 
202
            'added subdir',
 
203
            'renamed hello.txt => subdir/hello.txt',
 
204
            'Committed revision 2.',
 
205
            '',
 
206
            ]), set(err.split('\n')))
131
207
 
132
208
    def test_verbose_commit_with_unknown(self):
133
209
        """Unknown files should not be listed by default in verbose output"""
137
213
        wt.add(['hello.txt'])
138
214
        out,err = self.run_bzr('commit -m added')
139
215
        self.assertEqual('', out)
140
 
        self.assertContainsRe(err, '^Committing revision 1 to ".*"\.\n'
 
216
        self.assertContainsRe(err, '^Committing to: .*\n'
141
217
                              'added hello\.txt\n'
142
218
                              'Committed revision 1\.\n$')
143
219
 
150
226
        tree.add("hello.txt")
151
227
        out,err = self.run_bzr('commit -m added')
152
228
        self.assertEqual('', out)
153
 
        self.assertContainsRe(err, '^Committing revision 2 to ".*"\.\n'
 
229
        self.assertContainsRe(err, '^Committing to: .*\n'
154
230
                              'added hello\.txt\n'
155
231
                              'Committed revision 2\.$\n')
156
232
 
164
240
        b_tree = a_tree.branch.create_checkout('b')
165
241
        expected = "%s/" % (osutils.abspath('a'), )
166
242
        out, err = self.run_bzr('commit -m blah --unchanged', working_dir='b')
167
 
        self.assertEqual(err, 'Committing revision 2 to "%s".\n'
 
243
        self.assertEqual(err, 'Committing to: %s\n'
168
244
                         'Committed revision 2.\n' % expected)
169
245
 
 
246
    def test_commit_sanitizes_CR_in_message(self):
 
247
        # See bug #433779, basically Emacs likes to pass '\r\n' style line
 
248
        # endings to 'bzr commit -m ""' which breaks because we don't allow
 
249
        # '\r' in commit messages. (Mostly because of issues where XML style
 
250
        # formats arbitrarily strip it out of the data while parsing.)
 
251
        # To make life easier for users, we just always translate '\r\n' =>
 
252
        # '\n'. And '\r' => '\n'.
 
253
        a_tree = self.make_branch_and_tree('a')
 
254
        self.build_tree(['a/b'])
 
255
        a_tree.add('b')
 
256
        self.run_bzr(['commit',
 
257
                      '-m', 'a string\r\n\r\nwith mixed\r\rendings\n'],
 
258
                     working_dir='a')
 
259
        rev_id = a_tree.branch.last_revision()
 
260
        rev = a_tree.branch.repository.get_revision(rev_id)
 
261
        self.assertEqualDiff('a string\n\nwith mixed\n\nendings\n',
 
262
                             rev.message)
 
263
 
170
264
    def test_commit_merge_reports_all_modified_files(self):
171
265
        # the commit command should show all the files that are shown by
172
266
        # bzr diff or bzr status when committing, even when they were not
220
314
        os.chdir('this')
221
315
        out,err = self.run_bzr('commit -m added')
222
316
        self.assertEqual('', out)
223
 
        expected = '%s/' % (osutils.getcwd(), )
224
 
        self.assertEqualDiff(
225
 
            'Committing revision 2 to "%s".\n'
226
 
            'modified filetomodify\n'
227
 
            'added newdir\n'
228
 
            'added newfile\n'
229
 
            'renamed dirtorename => renameddir\n'
230
 
            'renamed filetorename => renamedfile\n'
231
 
            'renamed dirtoreparent => renameddir/reparenteddir\n'
232
 
            'renamed filetoreparent => renameddir/reparentedfile\n'
233
 
            'deleted dirtoremove\n'
234
 
            'deleted filetoremove\n'
235
 
            'Committed revision 2.\n' % (expected, ),
236
 
            err)
 
317
        self.assertEqual(set([
 
318
            'Committing to: %s/' % osutils.getcwd(),
 
319
            'modified filetomodify',
 
320
            'added newdir',
 
321
            'added newfile',
 
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.',
 
329
            ''
 
330
            ]), set(err.split('\n')))
237
331
 
238
332
    def test_empty_commit_message(self):
239
333
        tree = self.make_branch_and_tree('.')
241
335
        tree.add('foo.c')
242
336
        self.run_bzr('commit -m ""', retcode=3)
243
337
 
244
 
    def test_unsupported_encoding_commit_message(self):
245
 
        tree = self.make_branch_and_tree('.')
246
 
        self.build_tree_contents([('foo.c', 'int main() {}')])
247
 
        tree.add('foo.c')
248
 
        # LANG env variable has no effect on Windows
249
 
        # but some characters anyway cannot be represented
250
 
        # in default user encoding
251
 
        char = probe_bad_non_ascii(bzrlib.user_encoding)
252
 
        if char is None:
253
 
            raise TestSkipped('Cannot find suitable non-ascii character'
254
 
                'for user_encoding (%s)' % bzrlib.user_encoding)
255
 
        out,err = self.run_bzr_subprocess('commit -m "%s"' % char,
256
 
                                          retcode=1,
257
 
                                          env_changes={'LANG': 'C'})
258
 
        self.assertContainsRe(err, r'bzrlib.errors.BzrError: Parameter.*is '
259
 
                                    'unsupported by the current encoding.')
260
 
 
261
338
    def test_other_branch_commit(self):
262
339
        # this branch is to ensure consistent behaviour, whether we're run
263
340
        # inside a branch, or not.
266
343
        self.build_tree_contents([
267
344
            ('branch/foo.c', 'int main() {}'),
268
345
            ('branch/bar.c', 'int main() {}')])
269
 
        inner_tree.add('foo.c')
270
 
        inner_tree.add('bar.c')
 
346
        inner_tree.add(['foo.c', 'bar.c'])
271
347
        # can't commit files in different trees; sane error
272
348
        self.run_bzr('commit -m newstuff branch/foo.c .', retcode=3)
 
349
        # can commit to branch - records foo.c only
273
350
        self.run_bzr('commit -m newstuff branch/foo.c')
 
351
        # can commit to branch - records bar.c
274
352
        self.run_bzr('commit -m newstuff branch')
275
 
        self.run_bzr('commit -m newstuff branch', retcode=3)
 
353
        # No changes left
 
354
        self.run_bzr_error(["No changes to commit"], 'commit -m newstuff branch')
276
355
 
277
356
    def test_out_of_date_tree_commit(self):
278
357
        # check we get an error code and a clear message committing with an out
302
381
    def test_commit_a_text_merge_in_a_checkout(self):
303
382
        # checkouts perform multiple actions in a transaction across bond
304
383
        # branches and their master, and have been observed to fail in the
305
 
        # past. This is a user story reported to fail in bug #43959 where 
 
384
        # past. This is a user story reported to fail in bug #43959 where
306
385
        # a merge done in a checkout (using the update command) failed to
307
386
        # commit correctly.
308
387
        trunk = self.make_branch_and_tree('trunk')
309
388
 
310
389
        u1 = trunk.branch.create_checkout('u1')
311
 
        self.build_tree_contents([('u1/hosts', 'initial contents')])
 
390
        self.build_tree_contents([('u1/hosts', 'initial contents\n')])
312
391
        u1.add('hosts')
313
392
        self.run_bzr('commit -m add-hosts u1')
314
393
 
315
394
        u2 = trunk.branch.create_checkout('u2')
316
 
        self.build_tree_contents([('u2/hosts', 'altered in u2')])
 
395
        self.build_tree_contents([('u2/hosts', 'altered in u2\n')])
317
396
        self.run_bzr('commit -m checkin-from-u2 u2')
318
397
 
319
398
        # make an offline commits
320
 
        self.build_tree_contents([('u1/hosts', 'first offline change in u1')])
 
399
        self.build_tree_contents([('u1/hosts', 'first offline change in u1\n')])
321
400
        self.run_bzr('commit -m checkin-offline --local u1')
322
401
 
323
402
        # now try to pull in online work from u2, and then commit our offline
324
403
        # work as a merge
325
404
        # retcode 1 as we expect a text conflict
326
405
        self.run_bzr('update u1', retcode=1)
 
406
        self.assertFileEqual('''\
 
407
<<<<<<< TREE
 
408
first offline change in u1
 
409
=======
 
410
altered in u2
 
411
>>>>>>> MERGE-SOURCE
 
412
''',
 
413
                             'u1/hosts')
 
414
 
327
415
        self.run_bzr('resolved u1/hosts')
328
416
        # add a text change here to represent resolving the merge conflicts in
329
417
        # favour of a new version of the file not identical to either the u1
331
419
        self.build_tree_contents([('u1/hosts', 'merge resolution\n')])
332
420
        self.run_bzr('commit -m checkin-merge-of-the-offline-work-from-u1 u1')
333
421
 
 
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)
 
434
 
 
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)
 
450
 
334
451
    def test_commit_respects_spec_for_removals(self):
335
452
        """Commit with a file spec should only commit removals that match"""
336
453
        t = self.make_branch_and_tree('.')
363
480
 
364
481
        # With no changes, it should just be 'no changes'
365
482
        # Make sure that commit is failing because there is nothing to do
366
 
        self.run_bzr_error(['no changes to commit'],
 
483
        self.run_bzr_error(['No changes to commit'],
367
484
                           'commit --strict -m no-changes',
368
485
                           working_dir='tree')
369
486
 
397
514
        output, err = self.run_bzr(
398
515
            'commit -m hello --fixes=lp:23452 tree/hello.txt')
399
516
        self.assertEqual('', output)
400
 
        self.assertContainsRe(err, 'Committing revision 1 to ".*"\.\n'
 
517
        self.assertContainsRe(err, 'Committing to: .*\n'
401
518
                              'added hello\.txt\n'
402
519
                              'Committed revision 1\.\n')
403
520
 
488
605
        self.build_tree(['tree/hello.txt'])
489
606
        tree.add('hello.txt')
490
607
        self.run_bzr_error(
491
 
            ["Invalid bug identifier for %s. Commit refused." % 'lp:orange'],
 
608
            ["Did not understand bug identifier orange: Must be an integer. "
 
609
             "See \"bzr help bugs\" for more information on this feature.\n"
 
610
             "Commit refused."],
492
611
            'commit -m add-b --fixes=lp:orange',
493
612
            working_dir='tree')
494
613
 
498
617
        self.build_tree(['tree/hello.txt'])
499
618
        tree.add('hello.txt')
500
619
        self.run_bzr_error(
501
 
            [r"Invalid bug orange. Must be in the form of 'tag:id'\. "
 
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"
502
622
             r"Commit refused\."],
503
623
            'commit -m add-b --fixes=orange',
504
624
            working_dir='tree')
520
640
        tree = self.make_branch_and_tree('tree')
521
641
        self.build_tree(['tree/hello.txt'])
522
642
        tree.add('hello.txt')
523
 
        self.run_bzr("commit -m hello --author='John Doe <jdoe@example.com>' "
524
 
                     "tree/hello.txt")
 
643
        self.run_bzr(["commit", '-m', 'hello',
 
644
                      '--author', u'John D\xf6 <jdoe@example.com>',
 
645
                     "tree/hello.txt"])
525
646
        last_rev = tree.branch.repository.get_revision(tree.last_revision())
526
647
        properties = last_rev.properties
527
 
        self.assertEqual('John Doe <jdoe@example.com>', properties['author'])
 
648
        self.assertEqual(u'John D\xf6 <jdoe@example.com>', properties['authors'])
528
649
 
529
650
    def test_author_no_email(self):
530
651
        """Author's name without an email address is allowed, too."""
535
656
                                "tree/hello.txt")
536
657
        last_rev = tree.branch.repository.get_revision(tree.last_revision())
537
658
        properties = last_rev.properties
538
 
        self.assertEqual('John Doe', properties['author'])
 
659
        self.assertEqual('John Doe', properties['authors'])
 
660
 
 
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'])
 
671
 
 
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())
 
679
        self.assertEqual(
 
680
            'Sat 2009-10-10 08:00:00 +0100',
 
681
            osutils.format_date(last_rev.timestamp, last_rev.timezone))
 
682
        
 
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:")
539
691
 
540
692
    def test_partial_commit_with_renames_in_tree(self):
541
693
        # this test illustrates bug #140419
555
707
        self.assertContainsRe(err, r'modified test\nCommitted revision 2.')
556
708
 
557
709
    def test_commit_readonly_checkout(self):
558
 
        # https://bugs.edge.launchpad.net/bzr/+bug/129701
 
710
        # https://bugs.launchpad.net/bzr/+bug/129701
559
711
        # "UnlockableTransport error trying to commit in checkout of readonly
560
712
        # branch"
561
713
        self.make_branch('master')
566
718
            retcode=3)
567
719
        self.assertContainsRe(err,
568
720
            r'^bzr: ERROR: Cannot lock.*readonly transport')
 
721
 
 
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')
 
727
            f.close()
 
728
            self.overrideEnv('BZR_EDITOR', "fed.bat")
 
729
        else:
 
730
            f = file('fed.sh', 'wb')
 
731
            f.write('#!/bin/sh\n')
 
732
            f.close()
 
733
            os.chmod('fed.sh', 0755)
 
734
            self.overrideEnv('BZR_EDITOR', "./fed.sh")
 
735
 
 
736
    def setup_commit_with_template(self):
 
737
        self.setup_editor()
 
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')
 
743
        return tree
 
744
 
 
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)
 
750
 
 
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())
 
757
 
 
758
    def test_commit_without_username(self):
 
759
        """Ensure commit error if username is not set.
 
760
        """
 
761
        self.run_bzr(['init', 'foo'])
 
762
        os.chdir('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')
 
772
 
 
773
    def test_commit_recursive_checkout(self):
 
774
        """Ensure that a commit to a recursive checkout fails cleanly.
 
775
        """
 
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')
 
786