~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2010-08-24 21:59:21 UTC
  • mfrom: (5363.2.22 controldir-1)
  • Revision ID: pqm@pqm.ubuntu.com-20100824215921-p4nheij9k4x6i1jw
(jelmer) Split generic interface code out of bzrlib.bzrdir.BzrDir into
 bzrlib.controldir.ControlDir. (Jelmer Vernooij)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007, 2009 Canonical Ltd
 
1
# Copyright (C) 2006-2010 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
18
18
"""Tests for the commit CLI of bzr."""
19
19
 
20
20
import os
 
21
import re
21
22
import sys
22
23
 
23
24
from bzrlib import (
 
25
    bzrdir,
24
26
    osutils,
25
27
    ignores,
26
28
    msgeditor,
27
29
    osutils,
 
30
    tests,
28
31
    )
29
32
from bzrlib.bzrdir import BzrDir
30
33
from bzrlib.tests import (
31
34
    probe_bad_non_ascii,
32
35
    TestSkipped,
33
36
    )
34
 
from bzrlib.tests.blackbox import ExternalBase
35
 
 
36
 
 
37
 
class TestCommit(ExternalBase):
 
37
from bzrlib.tests import TestCaseWithTransport
 
38
 
 
39
 
 
40
class TestCommit(TestCaseWithTransport):
38
41
 
39
42
    def test_05_empty_commit(self):
40
43
        """Commit of tree with no versioned files should fail"""
106
109
                              'modified hello\.txt\n'
107
110
                              'Committed revision 2\.\n$')
108
111
 
 
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
 
109
154
    def test_verbose_commit_renamed(self):
110
155
        # Verbose commit of renamed file should say so
111
156
        wt = self.prepare_simple_history()
170
215
        self.assertEqual(err, 'Committing to: %s\n'
171
216
                         'Committed revision 2.\n' % expected)
172
217
 
 
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
 
173
236
    def test_commit_merge_reports_all_modified_files(self):
174
237
        # the commit command should show all the files that are shown by
175
238
        # bzr diff or bzr status when committing, even when they were not
245
308
        self.run_bzr('commit -m ""', retcode=3)
246
309
 
247
310
    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')
248
314
        tree = self.make_branch_and_tree('.')
249
315
        self.build_tree_contents([('foo.c', 'int main() {}')])
250
316
        tree.add('foo.c')
255
321
        if char is None:
256
322
            raise TestSkipped('Cannot find suitable non-ascii character'
257
323
                'for user_encoding (%s)' % osutils.get_user_encoding())
258
 
        # TODO: jam 2009-07-23 This test seems to fail on Windows now. My best
259
 
        #       guess is that the change to use Unicode command lines means
260
 
        #       that we no longer pay any attention to LANG=C when decoding the
261
 
        #       commandline arguments.
262
324
        out,err = self.run_bzr_subprocess('commit -m "%s"' % char,
263
325
                                          retcode=1,
264
326
                                          env_changes={'LANG': 'C'})
273
335
        self.build_tree_contents([
274
336
            ('branch/foo.c', 'int main() {}'),
275
337
            ('branch/bar.c', 'int main() {}')])
276
 
        inner_tree.add('foo.c')
277
 
        inner_tree.add('bar.c')
 
338
        inner_tree.add(['foo.c', 'bar.c'])
278
339
        # can't commit files in different trees; sane error
279
340
        self.run_bzr('commit -m newstuff branch/foo.c .', retcode=3)
 
341
        # can commit to branch - records foo.c only
280
342
        self.run_bzr('commit -m newstuff branch/foo.c')
 
343
        # can commit to branch - records bar.c
281
344
        self.run_bzr('commit -m newstuff branch')
282
 
        self.run_bzr('commit -m newstuff branch', retcode=3)
 
345
        # No changes left
 
346
        self.run_bzr_error(["No changes to commit"], 'commit -m newstuff branch')
283
347
 
284
348
    def test_out_of_date_tree_commit(self):
285
349
        # check we get an error code and a clear message committing with an out
315
379
        trunk = self.make_branch_and_tree('trunk')
316
380
 
317
381
        u1 = trunk.branch.create_checkout('u1')
318
 
        self.build_tree_contents([('u1/hosts', 'initial contents')])
 
382
        self.build_tree_contents([('u1/hosts', 'initial contents\n')])
319
383
        u1.add('hosts')
320
384
        self.run_bzr('commit -m add-hosts u1')
321
385
 
322
386
        u2 = trunk.branch.create_checkout('u2')
323
 
        self.build_tree_contents([('u2/hosts', 'altered in u2')])
 
387
        self.build_tree_contents([('u2/hosts', 'altered in u2\n')])
324
388
        self.run_bzr('commit -m checkin-from-u2 u2')
325
389
 
326
390
        # make an offline commits
327
 
        self.build_tree_contents([('u1/hosts', 'first offline change in u1')])
 
391
        self.build_tree_contents([('u1/hosts', 'first offline change in u1\n')])
328
392
        self.run_bzr('commit -m checkin-offline --local u1')
329
393
 
330
394
        # now try to pull in online work from u2, and then commit our offline
331
395
        # work as a merge
332
396
        # retcode 1 as we expect a text conflict
333
397
        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
 
334
407
        self.run_bzr('resolved u1/hosts')
335
408
        # add a text change here to represent resolving the merge conflicts in
336
409
        # favour of a new version of the file not identical to either the u1
588
661
        properties = last_rev.properties
589
662
        self.assertEqual('John Doe\nJane Rey', properties['authors'])
590
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:")
 
683
 
591
684
    def test_partial_commit_with_renames_in_tree(self):
592
685
        # this test illustrates bug #140419
593
686
        t = self.make_branch_and_tree('.')
606
699
        self.assertContainsRe(err, r'modified test\nCommitted revision 2.')
607
700
 
608
701
    def test_commit_readonly_checkout(self):
609
 
        # https://bugs.edge.launchpad.net/bzr/+bug/129701
 
702
        # https://bugs.launchpad.net/bzr/+bug/129701
610
703
        # "UnlockableTransport error trying to commit in checkout of readonly
611
704
        # branch"
612
705
        self.make_branch('master')
618
711
        self.assertContainsRe(err,
619
712
            r'^bzr: ERROR: Cannot lock.*readonly transport')
620
713
 
621
 
    def test_commit_hook_template(self):
 
714
    def setup_editor(self):
622
715
        # Test that commit template hooks work
623
 
        def restoreDefaults():
624
 
            msgeditor.hooks['commit_message_template'] = []
625
 
            osutils.set_or_unset_env('BZR_EDITOR', default_editor)
626
716
        if sys.platform == "win32":
627
717
            f = file('fed.bat', 'w')
628
718
            f.write('@rem dummy fed')
629
719
            f.close()
630
 
            default_editor = osutils.set_or_unset_env('BZR_EDITOR', "fed.bat")
 
720
            osutils.set_or_unset_env('BZR_EDITOR', "fed.bat")
631
721
        else:
632
722
            f = file('fed.sh', 'wb')
633
723
            f.write('#!/bin/sh\n')
634
724
            f.close()
635
725
            os.chmod('fed.sh', 0755)
636
 
            default_editor = osutils.set_or_unset_env('BZR_EDITOR', "./fed.sh")
637
 
        self.addCleanup(restoreDefaults)
 
726
            osutils.set_or_unset_env('BZR_EDITOR', "./fed.sh")
 
727
 
 
728
    def setup_commit_with_template(self):
 
729
        self.setup_editor()
638
730
        msgeditor.hooks.install_named_hook("commit_message_template",
639
731
                lambda commit_obj, msg: "save me some typing\n", None)
640
732
        tree = self.make_branch_and_tree('tree')
641
733
        self.build_tree(['tree/hello.txt'])
642
734
        tree.add('hello.txt')
643
 
        out, err = self.run_bzr("commit tree/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")
644
740
        last_rev = tree.branch.repository.get_revision(tree.last_revision())
645
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