/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

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

  • Committer: Ian Clatworthy
  • Date: 2007-11-23 05:52:03 UTC
  • mto: (3054.1.1 ianc-integration)
  • mto: This revision was merged to the branch mainline in revision 3055.
  • Revision ID: ian.clatworthy@internode.on.net-20071123055203-r2t2r27amhzllubr
first cut at Central development chapter

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
 
18
18
"""Tests for the commit CLI of bzr."""
19
19
 
20
20
import os
21
 
import re
22
21
import sys
23
22
 
 
23
import bzrlib
24
24
from bzrlib import (
25
25
    osutils,
26
26
    ignores,
27
 
    msgeditor,
28
27
    osutils,
29
 
    tests,
30
28
    )
31
29
from bzrlib.bzrdir import BzrDir
32
30
from bzrlib.tests import (
45
43
        self.build_tree(['hello.txt'])
46
44
        out,err = self.run_bzr('commit -m empty', retcode=3)
47
45
        self.assertEqual('', out)
48
 
        self.assertContainsRe(err, 'bzr: ERROR: No changes to commit\.'
49
 
                                  ' Use --unchanged to commit anyhow.\n')
 
46
        self.assertContainsRe(err, 'bzr: ERROR: no changes to commit\.'
 
47
                                  ' use --unchanged to commit anyhow\n')
50
48
 
51
49
    def test_commit_success(self):
52
50
        """Successful commit should not leave behind a bzr-commit-* file"""
85
83
        tree.add("hello.txt")
86
84
        out,err = self.run_bzr('commit -m added')
87
85
        self.assertEqual('', out)
88
 
        self.assertContainsRe(err, '^Committing to: .*\n'
 
86
        self.assertContainsRe(err, '^Committing revision 1 to ".*"\.\n'
89
87
                              'added hello.txt\n'
90
88
                              'Committed revision 1.\n$',)
91
89
 
104
102
        self.build_tree_contents([('hello.txt', 'new contents')])
105
103
        out, err = self.run_bzr('commit -m modified')
106
104
        self.assertEqual('', out)
107
 
        self.assertContainsRe(err, '^Committing to: .*\n'
 
105
        self.assertContainsRe(err, '^Committing revision 2 to ".*"\.\n'
108
106
                              'modified hello\.txt\n'
109
107
                              'Committed revision 2\.\n$')
110
108
 
111
 
    def test_unicode_commit_message_is_filename(self):
112
 
        """Unicode commit message same as a filename (Bug #563646).
113
 
        """
114
 
        file_name = u'\N{euro sign}'
115
 
        self.run_bzr(['init'])
116
 
        open(file_name, 'w').write('hello world')
117
 
        self.run_bzr(['add'])
118
 
        out, err = self.run_bzr(['commit', '-m', file_name])
119
 
        reflags = re.MULTILINE|re.DOTALL|re.UNICODE
120
 
        te = osutils.get_terminal_encoding()
121
 
        self.assertContainsRe(err.decode(te),
122
 
            u'The commit message is a file name:',
123
 
            flags=reflags)
124
 
 
125
 
        # Run same test with a filename that causes encode
126
 
        # error for the terminal encoding. We do this
127
 
        # by forcing terminal encoding of ascii for
128
 
        # osutils.get_terminal_encoding which is used
129
 
        # by ui.text.show_warning
130
 
        default_get_terminal_enc = osutils.get_terminal_encoding
131
 
        try:
132
 
            osutils.get_terminal_encoding = lambda: 'ascii'
133
 
            file_name = u'foo\u1234'
134
 
            open(file_name, 'w').write('hello world')
135
 
            self.run_bzr(['add'])
136
 
            out, err = self.run_bzr(['commit', '-m', file_name])
137
 
            reflags = re.MULTILINE|re.DOTALL|re.UNICODE
138
 
            te = osutils.get_terminal_encoding()
139
 
            self.assertContainsRe(err.decode(te, 'replace'),
140
 
                u'The commit message is a file name:',
141
 
                flags=reflags)
142
 
        finally:
143
 
            osutils.get_terminal_encoding = default_get_terminal_enc
144
 
 
145
 
    def test_warn_about_forgotten_commit_message(self):
146
 
        """Test that the lack of -m parameter is caught"""
147
 
        wt = self.make_branch_and_tree('.')
148
 
        self.build_tree(['one', 'two'])
149
 
        wt.add(['two'])
150
 
        out, err = self.run_bzr('commit -m one two')
151
 
        self.assertContainsRe(err, "The commit message is a file name")
152
 
 
153
109
    def test_verbose_commit_renamed(self):
154
110
        # Verbose commit of renamed file should say so
155
111
        wt = self.prepare_simple_history()
156
112
        wt.rename_one('hello.txt', 'gutentag.txt')
157
113
        out, err = self.run_bzr('commit -m renamed')
158
114
        self.assertEqual('', out)
159
 
        self.assertContainsRe(err, '^Committing to: .*\n'
 
115
        self.assertContainsRe(err, '^Committing revision 2 to ".*"\.\n'
160
116
                              'renamed hello\.txt => gutentag\.txt\n'
161
117
                              'Committed revision 2\.$\n')
162
118
 
168
124
        wt.rename_one('hello.txt', 'subdir/hello.txt')
169
125
        out, err = self.run_bzr('commit -m renamed')
170
126
        self.assertEqual('', out)
171
 
        self.assertEqual(set([
172
 
            'Committing to: %s/' % osutils.getcwd(),
173
 
            'added subdir',
174
 
            'renamed hello.txt => subdir/hello.txt',
175
 
            'Committed revision 2.',
176
 
            '',
177
 
            ]), set(err.split('\n')))
 
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$')
178
131
 
179
132
    def test_verbose_commit_with_unknown(self):
180
133
        """Unknown files should not be listed by default in verbose output"""
184
137
        wt.add(['hello.txt'])
185
138
        out,err = self.run_bzr('commit -m added')
186
139
        self.assertEqual('', out)
187
 
        self.assertContainsRe(err, '^Committing to: .*\n'
 
140
        self.assertContainsRe(err, '^Committing revision 1 to ".*"\.\n'
188
141
                              'added hello\.txt\n'
189
142
                              'Committed revision 1\.\n$')
190
143
 
197
150
        tree.add("hello.txt")
198
151
        out,err = self.run_bzr('commit -m added')
199
152
        self.assertEqual('', out)
200
 
        self.assertContainsRe(err, '^Committing to: .*\n'
 
153
        self.assertContainsRe(err, '^Committing revision 2 to ".*"\.\n'
201
154
                              'added hello\.txt\n'
202
155
                              'Committed revision 2\.$\n')
203
156
 
211
164
        b_tree = a_tree.branch.create_checkout('b')
212
165
        expected = "%s/" % (osutils.abspath('a'), )
213
166
        out, err = self.run_bzr('commit -m blah --unchanged', working_dir='b')
214
 
        self.assertEqual(err, 'Committing to: %s\n'
 
167
        self.assertEqual(err, 'Committing revision 2 to "%s".\n'
215
168
                         'Committed revision 2.\n' % expected)
216
169
 
217
 
    def test_commit_sanitizes_CR_in_message(self):
218
 
        # See bug #433779, basically Emacs likes to pass '\r\n' style line
219
 
        # endings to 'bzr commit -m ""' which breaks because we don't allow
220
 
        # '\r' in commit messages. (Mostly because of issues where XML style
221
 
        # formats arbitrarily strip it out of the data while parsing.)
222
 
        # To make life easier for users, we just always translate '\r\n' =>
223
 
        # '\n'. And '\r' => '\n'.
224
 
        a_tree = self.make_branch_and_tree('a')
225
 
        self.build_tree(['a/b'])
226
 
        a_tree.add('b')
227
 
        self.run_bzr(['commit',
228
 
                      '-m', 'a string\r\n\r\nwith mixed\r\rendings\n'],
229
 
                     working_dir='a')
230
 
        rev_id = a_tree.branch.last_revision()
231
 
        rev = a_tree.branch.repository.get_revision(rev_id)
232
 
        self.assertEqualDiff('a string\n\nwith mixed\n\nendings\n',
233
 
                             rev.message)
234
 
 
235
170
    def test_commit_merge_reports_all_modified_files(self):
236
171
        # the commit command should show all the files that are shown by
237
172
        # bzr diff or bzr status when committing, even when they were not
285
220
        os.chdir('this')
286
221
        out,err = self.run_bzr('commit -m added')
287
222
        self.assertEqual('', out)
288
 
        self.assertEqual(set([
289
 
            'Committing to: %s/' % osutils.getcwd(),
290
 
            'modified filetomodify',
291
 
            'added newdir',
292
 
            'added newfile',
293
 
            'renamed dirtorename => renameddir',
294
 
            'renamed filetorename => renamedfile',
295
 
            'renamed dirtoreparent => renameddir/reparenteddir',
296
 
            'renamed filetoreparent => renameddir/reparentedfile',
297
 
            'deleted dirtoremove',
298
 
            'deleted filetoremove',
299
 
            'Committed revision 2.',
300
 
            ''
301
 
            ]), set(err.split('\n')))
 
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)
302
237
 
303
238
    def test_empty_commit_message(self):
304
239
        tree = self.make_branch_and_tree('.')
307
242
        self.run_bzr('commit -m ""', retcode=3)
308
243
 
309
244
    def test_unsupported_encoding_commit_message(self):
310
 
        if sys.platform == 'win32':
311
 
            raise tests.TestNotApplicable('Win32 parses arguments directly'
312
 
                ' as Unicode, so we can\'t pass invalid non-ascii')
313
245
        tree = self.make_branch_and_tree('.')
314
246
        self.build_tree_contents([('foo.c', 'int main() {}')])
315
247
        tree.add('foo.c')
316
248
        # LANG env variable has no effect on Windows
317
249
        # but some characters anyway cannot be represented
318
250
        # in default user encoding
319
 
        char = probe_bad_non_ascii(osutils.get_user_encoding())
 
251
        char = probe_bad_non_ascii(bzrlib.user_encoding)
320
252
        if char is None:
321
253
            raise TestSkipped('Cannot find suitable non-ascii character'
322
 
                'for user_encoding (%s)' % osutils.get_user_encoding())
 
254
                'for user_encoding (%s)' % bzrlib.user_encoding)
323
255
        out,err = self.run_bzr_subprocess('commit -m "%s"' % char,
324
256
                                          retcode=1,
325
257
                                          env_changes={'LANG': 'C'})
334
266
        self.build_tree_contents([
335
267
            ('branch/foo.c', 'int main() {}'),
336
268
            ('branch/bar.c', 'int main() {}')])
337
 
        inner_tree.add(['foo.c', 'bar.c'])
 
269
        inner_tree.add('foo.c')
 
270
        inner_tree.add('bar.c')
338
271
        # can't commit files in different trees; sane error
339
272
        self.run_bzr('commit -m newstuff branch/foo.c .', retcode=3)
340
 
        # can commit to branch - records foo.c only
341
273
        self.run_bzr('commit -m newstuff branch/foo.c')
342
 
        # can commit to branch - records bar.c
343
274
        self.run_bzr('commit -m newstuff branch')
344
 
        # No changes left
345
 
        self.run_bzr_error(["No changes to commit"], 'commit -m newstuff branch')
 
275
        self.run_bzr('commit -m newstuff branch', retcode=3)
346
276
 
347
277
    def test_out_of_date_tree_commit(self):
348
278
        # check we get an error code and a clear message committing with an out
372
302
    def test_commit_a_text_merge_in_a_checkout(self):
373
303
        # checkouts perform multiple actions in a transaction across bond
374
304
        # branches and their master, and have been observed to fail in the
375
 
        # past. This is a user story reported to fail in bug #43959 where
 
305
        # past. This is a user story reported to fail in bug #43959 where 
376
306
        # a merge done in a checkout (using the update command) failed to
377
307
        # commit correctly.
378
308
        trunk = self.make_branch_and_tree('trunk')
379
309
 
380
310
        u1 = trunk.branch.create_checkout('u1')
381
 
        self.build_tree_contents([('u1/hosts', 'initial contents\n')])
 
311
        self.build_tree_contents([('u1/hosts', 'initial contents')])
382
312
        u1.add('hosts')
383
313
        self.run_bzr('commit -m add-hosts u1')
384
314
 
385
315
        u2 = trunk.branch.create_checkout('u2')
386
 
        self.build_tree_contents([('u2/hosts', 'altered in u2\n')])
 
316
        self.build_tree_contents([('u2/hosts', 'altered in u2')])
387
317
        self.run_bzr('commit -m checkin-from-u2 u2')
388
318
 
389
319
        # make an offline commits
390
 
        self.build_tree_contents([('u1/hosts', 'first offline change in u1\n')])
 
320
        self.build_tree_contents([('u1/hosts', 'first offline change in u1')])
391
321
        self.run_bzr('commit -m checkin-offline --local u1')
392
322
 
393
323
        # now try to pull in online work from u2, and then commit our offline
394
324
        # work as a merge
395
325
        # retcode 1 as we expect a text conflict
396
326
        self.run_bzr('update u1', retcode=1)
397
 
        self.assertFileEqual('''\
398
 
<<<<<<< TREE
399
 
first offline change in u1
400
 
=======
401
 
altered in u2
402
 
>>>>>>> MERGE-SOURCE
403
 
''',
404
 
                             'u1/hosts')
405
 
 
406
327
        self.run_bzr('resolved u1/hosts')
407
328
        # add a text change here to represent resolving the merge conflicts in
408
329
        # favour of a new version of the file not identical to either the u1
410
331
        self.build_tree_contents([('u1/hosts', 'merge resolution\n')])
411
332
        self.run_bzr('commit -m checkin-merge-of-the-offline-work-from-u1 u1')
412
333
 
413
 
    def test_commit_exclude_excludes_modified_files(self):
414
 
        """Commit -x foo should ignore changes to foo."""
415
 
        tree = self.make_branch_and_tree('.')
416
 
        self.build_tree(['a', 'b', 'c'])
417
 
        tree.smart_add(['.'])
418
 
        out, err = self.run_bzr(['commit', '-m', 'test', '-x', 'b'])
419
 
        self.assertFalse('added b' in out)
420
 
        self.assertFalse('added b' in err)
421
 
        # If b was excluded it will still be 'added' in status.
422
 
        out, err = self.run_bzr(['added'])
423
 
        self.assertEqual('b\n', out)
424
 
        self.assertEqual('', err)
425
 
 
426
 
    def test_commit_exclude_twice_uses_both_rules(self):
427
 
        """Commit -x foo -x bar should ignore changes to foo and bar."""
428
 
        tree = self.make_branch_and_tree('.')
429
 
        self.build_tree(['a', 'b', 'c'])
430
 
        tree.smart_add(['.'])
431
 
        out, err = self.run_bzr(['commit', '-m', 'test', '-x', 'b', '-x', 'c'])
432
 
        self.assertFalse('added b' in out)
433
 
        self.assertFalse('added c' in out)
434
 
        self.assertFalse('added b' in err)
435
 
        self.assertFalse('added c' in err)
436
 
        # If b was excluded it will still be 'added' in status.
437
 
        out, err = self.run_bzr(['added'])
438
 
        self.assertTrue('b\n' in out)
439
 
        self.assertTrue('c\n' in out)
440
 
        self.assertEqual('', err)
441
 
 
442
334
    def test_commit_respects_spec_for_removals(self):
443
335
        """Commit with a file spec should only commit removals that match"""
444
336
        t = self.make_branch_and_tree('.')
471
363
 
472
364
        # With no changes, it should just be 'no changes'
473
365
        # Make sure that commit is failing because there is nothing to do
474
 
        self.run_bzr_error(['No changes to commit'],
 
366
        self.run_bzr_error(['no changes to commit'],
475
367
                           'commit --strict -m no-changes',
476
368
                           working_dir='tree')
477
369
 
505
397
        output, err = self.run_bzr(
506
398
            'commit -m hello --fixes=lp:23452 tree/hello.txt')
507
399
        self.assertEqual('', output)
508
 
        self.assertContainsRe(err, 'Committing to: .*\n'
 
400
        self.assertContainsRe(err, 'Committing revision 1 to ".*"\.\n'
509
401
                              'added hello\.txt\n'
510
402
                              'Committed revision 1\.\n')
511
403
 
596
488
        self.build_tree(['tree/hello.txt'])
597
489
        tree.add('hello.txt')
598
490
        self.run_bzr_error(
599
 
            ["Did not understand bug identifier orange: Must be an integer. "
600
 
             "See \"bzr help bugs\" for more information on this feature.\n"
601
 
             "Commit refused."],
 
491
            ["Invalid bug identifier for %s. Commit refused." % 'lp:orange'],
602
492
            'commit -m add-b --fixes=lp:orange',
603
493
            working_dir='tree')
604
494
 
608
498
        self.build_tree(['tree/hello.txt'])
609
499
        tree.add('hello.txt')
610
500
        self.run_bzr_error(
611
 
            [r"Invalid bug orange. Must be in the form of 'tracker:id'\. "
612
 
             r"See \"bzr help bugs\" for more information on this feature.\n"
 
501
            [r"Invalid bug orange. Must be in the form of 'tag:id'\. "
613
502
             r"Commit refused\."],
614
503
            'commit -m add-b --fixes=orange',
615
504
            working_dir='tree')
631
520
        tree = self.make_branch_and_tree('tree')
632
521
        self.build_tree(['tree/hello.txt'])
633
522
        tree.add('hello.txt')
634
 
        self.run_bzr(["commit", '-m', 'hello',
635
 
                      '--author', u'John D\xf6 <jdoe@example.com>',
636
 
                     "tree/hello.txt"])
 
523
        self.run_bzr("commit -m hello --author='John Doe <jdoe@example.com>' "
 
524
                     "tree/hello.txt")
637
525
        last_rev = tree.branch.repository.get_revision(tree.last_revision())
638
526
        properties = last_rev.properties
639
 
        self.assertEqual(u'John D\xf6 <jdoe@example.com>', properties['authors'])
 
527
        self.assertEqual('John Doe <jdoe@example.com>', properties['author'])
640
528
 
641
529
    def test_author_no_email(self):
642
530
        """Author's name without an email address is allowed, too."""
647
535
                                "tree/hello.txt")
648
536
        last_rev = tree.branch.repository.get_revision(tree.last_revision())
649
537
        properties = last_rev.properties
650
 
        self.assertEqual('John Doe', properties['authors'])
651
 
 
652
 
    def test_multiple_authors(self):
653
 
        """Multiple authors can be specyfied, and all are stored."""
654
 
        tree = self.make_branch_and_tree('tree')
655
 
        self.build_tree(['tree/hello.txt'])
656
 
        tree.add('hello.txt')
657
 
        out, err = self.run_bzr("commit -m hello --author='John Doe' "
658
 
                                "--author='Jane Rey' tree/hello.txt")
659
 
        last_rev = tree.branch.repository.get_revision(tree.last_revision())
660
 
        properties = last_rev.properties
661
 
        self.assertEqual('John Doe\nJane Rey', properties['authors'])
662
 
 
663
 
    def test_commit_time(self):
664
 
        tree = self.make_branch_and_tree('tree')
665
 
        self.build_tree(['tree/hello.txt'])
666
 
        tree.add('hello.txt')
667
 
        out, err = self.run_bzr("commit -m hello "
668
 
            "--commit-time='2009-10-10 08:00:00 +0100' tree/hello.txt")
669
 
        last_rev = tree.branch.repository.get_revision(tree.last_revision())
670
 
        self.assertEqual(
671
 
            'Sat 2009-10-10 08:00:00 +0100',
672
 
            osutils.format_date(last_rev.timestamp, last_rev.timezone))
673
 
        
674
 
    def test_commit_time_bad_time(self):
675
 
        tree = self.make_branch_and_tree('tree')
676
 
        self.build_tree(['tree/hello.txt'])
677
 
        tree.add('hello.txt')
678
 
        out, err = self.run_bzr("commit -m hello "
679
 
            "--commit-time='NOT A TIME' tree/hello.txt", retcode=3)
680
 
        self.assertStartsWith(
681
 
            err, "bzr: ERROR: Could not parse --commit-time:")
 
538
        self.assertEqual('John Doe', properties['author'])
682
539
 
683
540
    def test_partial_commit_with_renames_in_tree(self):
684
541
        # this test illustrates bug #140419
709
566
            retcode=3)
710
567
        self.assertContainsRe(err,
711
568
            r'^bzr: ERROR: Cannot lock.*readonly transport')
712
 
 
713
 
    def setup_editor(self):
714
 
        # Test that commit template hooks work
715
 
        if sys.platform == "win32":
716
 
            f = file('fed.bat', 'w')
717
 
            f.write('@rem dummy fed')
718
 
            f.close()
719
 
            osutils.set_or_unset_env('BZR_EDITOR', "fed.bat")
720
 
        else:
721
 
            f = file('fed.sh', 'wb')
722
 
            f.write('#!/bin/sh\n')
723
 
            f.close()
724
 
            os.chmod('fed.sh', 0755)
725
 
            osutils.set_or_unset_env('BZR_EDITOR', "./fed.sh")
726
 
 
727
 
    def setup_commit_with_template(self):
728
 
        self.setup_editor()
729
 
        msgeditor.hooks.install_named_hook("commit_message_template",
730
 
                lambda commit_obj, msg: "save me some typing\n", None)
731
 
        tree = self.make_branch_and_tree('tree')
732
 
        self.build_tree(['tree/hello.txt'])
733
 
        tree.add('hello.txt')
734
 
        return tree
735
 
 
736
 
    def test_commit_hook_template_accepted(self):
737
 
        tree = self.setup_commit_with_template()
738
 
        out, err = self.run_bzr("commit tree/hello.txt", stdin="y\n")
739
 
        last_rev = tree.branch.repository.get_revision(tree.last_revision())
740
 
        self.assertEqual('save me some typing\n', last_rev.message)
741
 
 
742
 
    def test_commit_hook_template_rejected(self):
743
 
        tree = self.setup_commit_with_template()
744
 
        expected = tree.last_revision()
745
 
        out, err = self.run_bzr_error(["empty commit message"],
746
 
            "commit tree/hello.txt", stdin="n\n")
747
 
        self.assertEqual(expected, tree.last_revision())
748
 
 
749
 
    def test_commit_without_username(self):
750
 
        """Ensure commit error if username is not set.
751
 
        """
752
 
        self.run_bzr(['init', 'foo'])
753
 
        os.chdir('foo')
754
 
        open('foo.txt', 'w').write('hello')
755
 
        self.run_bzr(['add'])
756
 
        osutils.set_or_unset_env('EMAIL', None)
757
 
        osutils.set_or_unset_env('BZR_EMAIL', None)
758
 
        out, err = self.run_bzr(['commit', '-m', 'initial'], 3)
759
 
        self.assertContainsRe(err, 'Unable to determine your name')