~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: 2010-01-05 04:30:07 UTC
  • mfrom: (4932 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4934.
  • Revision ID: john@arbash-meinel.com-20100105043007-ehgbldqd3q0gtyws
Merge bzr.dev, resolve conflicts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2011 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007, 2009 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
17
17
 
18
18
"""Tests for the commit CLI of bzr."""
19
19
 
20
 
import doctest
21
20
import os
22
 
import re
23
21
import sys
24
22
 
25
 
from testtools.matchers import DocTestMatches
26
 
 
27
23
from bzrlib import (
28
 
    config,
29
24
    osutils,
30
25
    ignores,
31
26
    msgeditor,
 
27
    osutils,
 
28
    tests,
32
29
    )
33
30
from bzrlib.bzrdir import BzrDir
34
31
from bzrlib.tests import (
35
 
    test_foreign,
36
 
    features,
 
32
    probe_bad_non_ascii,
 
33
    TestSkipped,
37
34
    )
38
 
from bzrlib.tests import TestCaseWithTransport
39
 
 
40
 
 
41
 
class TestCommit(TestCaseWithTransport):
 
35
from bzrlib.tests.blackbox import ExternalBase
 
36
 
 
37
 
 
38
class TestCommit(ExternalBase):
42
39
 
43
40
    def test_05_empty_commit(self):
44
41
        """Commit of tree with no versioned files should fail"""
47
44
        self.build_tree(['hello.txt'])
48
45
        out,err = self.run_bzr('commit -m empty', retcode=3)
49
46
        self.assertEqual('', out)
50
 
        # Two ugly bits here.
51
 
        # 1) We really don't want 'aborting commit write group' anymore.
52
 
        # 2) bzr: ERROR: is a really long line, so we wrap it with '\'
53
 
        self.assertThat(
54
 
            err,
55
 
            DocTestMatches("""\
56
 
Committing to: ...
57
 
bzr: ERROR: No changes to commit.\
58
 
 Please 'bzr add' the files you want to commit,\
59
 
 or use --unchanged to force an empty commit.
60
 
""", flags=doctest.ELLIPSIS|doctest.REPORT_UDIFF))
 
47
        self.assertContainsRe(err, 'bzr: ERROR: No changes to commit\.'
 
48
                                  ' Use --unchanged to commit anyhow.\n')
61
49
 
62
50
    def test_commit_success(self):
63
51
        """Successful commit should not leave behind a bzr-commit-* file"""
69
57
        self.run_bzr(["commit", "--unchanged", "-m", u'foo\xb5'])
70
58
        self.assertEqual('', self.run_bzr('unknowns')[0])
71
59
 
72
 
    def test_commit_lossy_native(self):
73
 
        """A --lossy option to commit is supported."""
74
 
        self.make_branch_and_tree('.')
75
 
        self.run_bzr('commit --lossy --unchanged -m message')
76
 
        self.assertEqual('', self.run_bzr('unknowns')[0])
77
 
 
78
 
    def test_commit_lossy_foreign(self):
79
 
        test_foreign.register_dummy_foreign_for_test(self)
80
 
        self.make_branch_and_tree('.',
81
 
            format=test_foreign.DummyForeignVcsDirFormat())
82
 
        self.run_bzr('commit --lossy --unchanged -m message')
83
 
        output = self.run_bzr('revision-info')[0]
84
 
        self.assertTrue(output.startswith('1 dummy-'))
85
 
 
86
60
    def test_commit_with_path(self):
87
61
        """Commit tree with path of root specified"""
88
62
        a_tree = self.make_branch_and_tree('a')
102
76
        self.run_bzr('resolved b/a_file')
103
77
        self.run_bzr(['commit', '-m', 'merge into b', 'b'])
104
78
 
 
79
 
105
80
    def test_10_verbose_commit(self):
106
81
        """Add one file and examine verbose commit output"""
107
82
        tree = self.make_branch_and_tree('.')
132
107
                              'modified hello\.txt\n'
133
108
                              'Committed revision 2\.\n$')
134
109
 
135
 
    def test_unicode_commit_message_is_filename(self):
136
 
        """Unicode commit message same as a filename (Bug #563646).
137
 
        """
138
 
        self.requireFeature(features.UnicodeFilenameFeature)
139
 
        file_name = u'\N{euro sign}'
140
 
        self.run_bzr(['init'])
141
 
        open(file_name, 'w').write('hello world')
142
 
        self.run_bzr(['add'])
143
 
        out, err = self.run_bzr(['commit', '-m', file_name])
144
 
        reflags = re.MULTILINE|re.DOTALL|re.UNICODE
145
 
        te = osutils.get_terminal_encoding()
146
 
        self.assertContainsRe(err.decode(te),
147
 
            u'The commit message is a file name:',
148
 
            flags=reflags)
149
 
 
150
 
        # Run same test with a filename that causes encode
151
 
        # error for the terminal encoding. We do this
152
 
        # by forcing terminal encoding of ascii for
153
 
        # osutils.get_terminal_encoding which is used
154
 
        # by ui.text.show_warning
155
 
        default_get_terminal_enc = osutils.get_terminal_encoding
156
 
        try:
157
 
            osutils.get_terminal_encoding = lambda trace=None: 'ascii'
158
 
            file_name = u'foo\u1234'
159
 
            open(file_name, 'w').write('hello world')
160
 
            self.run_bzr(['add'])
161
 
            out, err = self.run_bzr(['commit', '-m', file_name])
162
 
            reflags = re.MULTILINE|re.DOTALL|re.UNICODE
163
 
            te = osutils.get_terminal_encoding()
164
 
            self.assertContainsRe(err.decode(te, 'replace'),
165
 
                u'The commit message is a file name:',
166
 
                flags=reflags)
167
 
        finally:
168
 
            osutils.get_terminal_encoding = default_get_terminal_enc
169
 
 
170
110
    def test_warn_about_forgotten_commit_message(self):
171
111
        """Test that the lack of -m parameter is caught"""
172
112
        wt = self.make_branch_and_tree('.')
329
269
        tree = self.make_branch_and_tree('.')
330
270
        self.build_tree_contents([('foo.c', 'int main() {}')])
331
271
        tree.add('foo.c')
332
 
        self.run_bzr('commit -m ""')
 
272
        self.run_bzr('commit -m ""', retcode=3)
 
273
 
 
274
    def test_unsupported_encoding_commit_message(self):
 
275
        if sys.platform == 'win32':
 
276
            raise tests.TestNotApplicable('Win32 parses arguments directly'
 
277
                ' as Unicode, so we can\'t pass invalid non-ascii')
 
278
        tree = self.make_branch_and_tree('.')
 
279
        self.build_tree_contents([('foo.c', 'int main() {}')])
 
280
        tree.add('foo.c')
 
281
        # LANG env variable has no effect on Windows
 
282
        # but some characters anyway cannot be represented
 
283
        # in default user encoding
 
284
        char = probe_bad_non_ascii(osutils.get_user_encoding())
 
285
        if char is None:
 
286
            raise TestSkipped('Cannot find suitable non-ascii character'
 
287
                'for user_encoding (%s)' % osutils.get_user_encoding())
 
288
        out,err = self.run_bzr_subprocess('commit -m "%s"' % char,
 
289
                                          retcode=1,
 
290
                                          env_changes={'LANG': 'C'})
 
291
        self.assertContainsRe(err, r'bzrlib.errors.BzrError: Parameter.*is '
 
292
                                    'unsupported by the current encoding.')
333
293
 
334
294
    def test_other_branch_commit(self):
335
295
        # this branch is to ensure consistent behaviour, whether we're run
383
343
        trunk = self.make_branch_and_tree('trunk')
384
344
 
385
345
        u1 = trunk.branch.create_checkout('u1')
386
 
        self.build_tree_contents([('u1/hosts', 'initial contents\n')])
 
346
        self.build_tree_contents([('u1/hosts', 'initial contents')])
387
347
        u1.add('hosts')
388
348
        self.run_bzr('commit -m add-hosts u1')
389
349
 
390
350
        u2 = trunk.branch.create_checkout('u2')
391
 
        self.build_tree_contents([('u2/hosts', 'altered in u2\n')])
 
351
        self.build_tree_contents([('u2/hosts', 'altered in u2')])
392
352
        self.run_bzr('commit -m checkin-from-u2 u2')
393
353
 
394
354
        # make an offline commits
395
 
        self.build_tree_contents([('u1/hosts', 'first offline change in u1\n')])
 
355
        self.build_tree_contents([('u1/hosts', 'first offline change in u1')])
396
356
        self.run_bzr('commit -m checkin-offline --local u1')
397
357
 
398
358
        # now try to pull in online work from u2, and then commit our offline
399
359
        # work as a merge
400
360
        # retcode 1 as we expect a text conflict
401
361
        self.run_bzr('update u1', retcode=1)
402
 
        self.assertFileEqual('''\
403
 
<<<<<<< TREE
404
 
first offline change in u1
405
 
=======
406
 
altered in u2
407
 
>>>>>>> MERGE-SOURCE
408
 
''',
409
 
                             'u1/hosts')
410
 
 
411
362
        self.run_bzr('resolved u1/hosts')
412
363
        # add a text change here to represent resolving the merge conflicts in
413
364
        # favour of a new version of the file not identical to either the u1
596
547
            'commit -m add-b --fixes=xxx:123',
597
548
            working_dir='tree')
598
549
 
599
 
    def test_fixes_bug_with_default_tracker(self):
600
 
        """commit --fixes=234 uses the default bug tracker."""
601
 
        tree = self.make_branch_and_tree('tree')
602
 
        self.build_tree(['tree/hello.txt'])
603
 
        tree.add('hello.txt')
604
 
        self.run_bzr_error(
605
 
            ["bzr: ERROR: No tracker specified for bug 123. Use the form "
606
 
            "'tracker:id' or specify a default bug tracker using the "
607
 
            "`bugtracker` option.\n"
608
 
            "See \"bzr help bugs\" for more information on this feature. "
609
 
            "Commit refused."],
610
 
            'commit -m add-b --fixes=123',
611
 
            working_dir='tree')
612
 
        tree.branch.get_config().set_user_option("bugtracker", "lp")
613
 
        self.run_bzr('commit -m hello --fixes=234 tree/hello.txt')
614
 
        last_rev = tree.branch.repository.get_revision(tree.last_revision())
615
 
        self.assertEqual('https://launchpad.net/bugs/234 fixed',
616
 
                         last_rev.properties['bugs'])
617
 
 
618
550
    def test_fixes_invalid_bug_number(self):
619
551
        tree = self.make_branch_and_tree('tree')
620
552
        self.build_tree(['tree/hello.txt'])
632
564
        self.build_tree(['tree/hello.txt'])
633
565
        tree.add('hello.txt')
634
566
        self.run_bzr_error(
635
 
            [r"Invalid bug orange:apples:bananas. Must be in the form of "
636
 
             r"'tracker:id'\. See \"bzr help bugs\" for more information on "
637
 
             r"this feature.\nCommit refused\."],
638
 
            'commit -m add-b --fixes=orange:apples:bananas',
 
567
            [r"Invalid bug orange. Must be in the form of 'tracker:id'\. "
 
568
             r"See \"bzr help bugs\" for more information on this feature.\n"
 
569
             r"Commit refused\."],
 
570
            'commit -m add-b --fixes=orange',
639
571
            working_dir='tree')
640
572
 
641
573
    def test_no_author(self):
722
654
        self.assertContainsRe(err, r'modified test\nCommitted revision 2.')
723
655
 
724
656
    def test_commit_readonly_checkout(self):
725
 
        # https://bugs.launchpad.net/bzr/+bug/129701
 
657
        # https://bugs.edge.launchpad.net/bzr/+bug/129701
726
658
        # "UnlockableTransport error trying to commit in checkout of readonly
727
659
        # branch"
728
660
        self.make_branch('master')
734
666
        self.assertContainsRe(err,
735
667
            r'^bzr: ERROR: Cannot lock.*readonly transport')
736
668
 
737
 
    def setup_editor(self):
 
669
    def test_commit_hook_template(self):
738
670
        # Test that commit template hooks work
 
671
        def restoreDefaults():
 
672
            msgeditor.hooks['commit_message_template'] = []
 
673
            osutils.set_or_unset_env('BZR_EDITOR', default_editor)
739
674
        if sys.platform == "win32":
740
675
            f = file('fed.bat', 'w')
741
676
            f.write('@rem dummy fed')
742
677
            f.close()
743
 
            self.overrideEnv('BZR_EDITOR', "fed.bat")
 
678
            default_editor = osutils.set_or_unset_env('BZR_EDITOR', "fed.bat")
744
679
        else:
745
680
            f = file('fed.sh', 'wb')
746
681
            f.write('#!/bin/sh\n')
747
682
            f.close()
748
683
            os.chmod('fed.sh', 0755)
749
 
            self.overrideEnv('BZR_EDITOR', "./fed.sh")
750
 
 
751
 
    def setup_commit_with_template(self):
752
 
        self.setup_editor()
 
684
            default_editor = osutils.set_or_unset_env('BZR_EDITOR', "./fed.sh")
 
685
        self.addCleanup(restoreDefaults)
753
686
        msgeditor.hooks.install_named_hook("commit_message_template",
754
687
                lambda commit_obj, msg: "save me some typing\n", None)
755
688
        tree = self.make_branch_and_tree('tree')
756
689
        self.build_tree(['tree/hello.txt'])
757
690
        tree.add('hello.txt')
758
 
        return tree
759
 
 
760
 
    def test_edit_empty_message(self):
761
 
        tree = self.make_branch_and_tree('tree')
762
 
        self.setup_editor()
763
 
        self.build_tree(['tree/hello.txt'])
764
 
        tree.add('hello.txt')
765
 
        out, err = self.run_bzr("commit tree/hello.txt", retcode=3,
766
 
            stdin="y\n")
767
 
        self.assertContainsRe(err,
768
 
            "bzr: ERROR: Empty commit message specified")
769
 
 
770
 
    def test_commit_hook_template_accepted(self):
771
 
        tree = self.setup_commit_with_template()
772
 
        out, err = self.run_bzr("commit tree/hello.txt", stdin="y\n")
773
 
        last_rev = tree.branch.repository.get_revision(tree.last_revision())
774
 
        self.assertEqual('save me some typing\n', last_rev.message)
775
 
 
776
 
    def test_commit_hook_template_rejected(self):
777
 
        tree = self.setup_commit_with_template()
778
 
        expected = tree.last_revision()
779
 
        out, err = self.run_bzr_error(["Empty commit message specified."
780
 
                  " Please specify a commit message with either"
781
 
                  " --message or --file or leave a blank message"
782
 
                  " with --message \"\"."],
783
 
            "commit tree/hello.txt", stdin="n\n")
784
 
        self.assertEqual(expected, tree.last_revision())
785
 
 
786
 
    def test_set_commit_message(self):
787
 
        msgeditor.hooks.install_named_hook("set_commit_message",
788
 
                lambda commit_obj, msg: "save me some typing\n", None)
789
 
        tree = self.make_branch_and_tree('tree')
790
 
        self.build_tree(['tree/hello.txt'])
791
 
        tree.add('hello.txt')
792
691
        out, err = self.run_bzr("commit tree/hello.txt")
793
692
        last_rev = tree.branch.repository.get_revision(tree.last_revision())
794
693
        self.assertEqual('save me some typing\n', last_rev.message)
795
 
 
796
 
    def test_commit_without_username(self):
797
 
        """Ensure commit error if username is not set.
798
 
        """
799
 
        self.run_bzr(['init', 'foo'])
800
 
        os.chdir('foo')
801
 
        open('foo.txt', 'w').write('hello')
802
 
        self.run_bzr(['add'])
803
 
        self.overrideEnv('EMAIL', None)
804
 
        self.overrideEnv('BZR_EMAIL', None)
805
 
        # Also, make sure that it's not inferred from mailname.
806
 
        self.overrideAttr(config, '_auto_user_id',
807
 
            lambda: (None, None))
808
 
        out, err = self.run_bzr(['commit', '-m', 'initial'], 3)
809
 
        self.assertContainsRe(err, 'Unable to determine your name')
810
 
 
811
 
    def test_commit_recursive_checkout(self):
812
 
        """Ensure that a commit to a recursive checkout fails cleanly.
813
 
        """
814
 
        self.run_bzr(['init', 'test_branch'])
815
 
        self.run_bzr(['checkout', 'test_branch', 'test_checkout'])
816
 
        os.chdir('test_checkout')
817
 
        self.run_bzr(['bind', '.']) # bind to self
818
 
        open('foo.txt', 'w').write('hello')
819
 
        self.run_bzr(['add'])
820
 
        out, err = self.run_bzr(['commit', '-m', 'addedfoo'], 3)
821
 
        self.assertEqual(out, '')
822
 
        self.assertContainsRe(err,
823
 
            'Branch.*test_checkout.*appears to be bound to itself')