~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Martin Albisetti
  • Date: 2008-05-06 00:21:18 UTC
  • mto: (3431.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 3432.
  • Revision ID: argentina@gmail.com-20080506002118-7w9ywklw4khddf3g
Added spanish index

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