~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_msgeditor.py

  • Committer: Ian Clatworthy
  • Date: 2007-12-11 02:07:30 UTC
  • mto: (3119.1.1 ianc-integration)
  • mto: This revision was merged to the branch mainline in revision 3120.
  • Revision ID: ian.clatworthy@internode.on.net-20071211020730-sdj4kj794dw0628e
make help topics more discoverable

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2005 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
"""Test commit message editor.
18
18
"""
20
20
import os
21
21
import sys
22
22
 
 
23
import bzrlib
23
24
from bzrlib import (
24
 
    commit,
25
 
    config,
26
25
    errors,
27
26
    msgeditor,
28
27
    osutils,
29
 
    tests,
30
 
    trace,
31
28
    )
 
29
from bzrlib.branch import Branch
 
30
from bzrlib.config import ensure_config_dir_exists, config_filename
32
31
from bzrlib.msgeditor import (
33
32
    make_commit_message_template_encoded,
34
33
    edit_commit_message_encoded
35
34
)
36
35
from bzrlib.tests import (
37
 
    TestCaseInTempDir,
 
36
    probe_bad_non_ascii,
38
37
    TestCaseWithTransport,
39
38
    TestNotApplicable,
40
39
    TestSkipped,
41
 
    multiply_tests,
42
 
    probe_bad_non_ascii,
43
 
    split_suite_by_re,
44
40
    )
45
 
from bzrlib.tests.EncodingAdapter import encoding_scenarios
46
41
from bzrlib.trace import mutter
47
42
 
48
43
 
49
 
def load_tests(standard_tests, module, loader):
50
 
    """Parameterize the test for tempfile creation with different encodings."""
51
 
    to_adapt, result = split_suite_by_re(standard_tests,
52
 
        "test__create_temp_file_with_commit_template_in_unicode_dir")
53
 
    return multiply_tests(to_adapt, encoding_scenarios, result)
54
 
 
55
 
 
56
44
class MsgEditorTest(TestCaseWithTransport):
57
45
 
58
46
    def make_uncommitted_tree(self):
67
55
                "filesystem encoding %s" % sys.getfilesystemencoding())
68
56
        working_tree.add(filename)
69
57
        return working_tree
70
 
 
 
58
    
71
59
    def test_commit_template(self):
72
60
        """Test building a commit message template"""
73
61
        working_tree = self.make_uncommitted_tree()
79
67
  hell\u00d8
80
68
""")
81
69
 
82
 
    def make_multiple_pending_tree(self):
83
 
        from bzrlib import config
84
 
        config.GlobalConfig().set_user_option('email',
85
 
                                              'Bilbo Baggins <bb@hobbit.net>')
86
 
        tree = self.make_branch_and_tree('a')
87
 
        tree.commit('Initial checkin.', timestamp=1230912900, timezone=0)
88
 
        tree2 = tree.bzrdir.clone('b').open_workingtree()
89
 
        tree.commit('Minor tweak.', timestamp=1231977840, timezone=0)
90
 
        tree2.commit('Feature X work.', timestamp=1233186240, timezone=0)
91
 
        tree3 = tree2.bzrdir.clone('c').open_workingtree()
92
 
        tree2.commit('Feature X finished.', timestamp=1233187680, timezone=0)
93
 
        tree3.commit('Feature Y, based on initial X work.',
94
 
                     timestamp=1233285960, timezone=0)
95
 
        tree.merge_from_branch(tree2.branch)
96
 
        tree.merge_from_branch(tree3.branch, force=True)
97
 
        return tree
98
 
 
99
 
    def test_commit_template_pending_merges(self):
100
 
        """Test building a commit message template when there are pending
101
 
        merges.  The commit message should show all pending merge revisions,
102
 
        as does 'status -v', not only the merge tips.
103
 
        """
104
 
        working_tree = self.make_multiple_pending_tree()
105
 
        template = msgeditor.make_commit_message_template(working_tree, None)
106
 
        self.assertEqualDiff(template,
107
 
u"""\
108
 
pending merges:
109
 
  Bilbo Baggins 2009-01-29 Feature X finished.
110
 
    Bilbo Baggins 2009-01-28 Feature X work.
111
 
  Bilbo Baggins 2009-01-30 Feature Y, based on initial X work.
112
 
""")
113
 
 
114
70
    def test_commit_template_encoded(self):
115
71
        """Test building a commit message template"""
116
72
        working_tree = self.make_uncommitted_tree()
141
97
  hell\u00d8
142
98
""".encode('utf8') in template)
143
99
 
144
 
    def make_do_nothing_editor(self, basename='fed'):
 
100
    def test_run_editor(self):
145
101
        if sys.platform == "win32":
146
 
            name = basename + '.bat'
147
 
            f = file(name, 'w')
 
102
            f = file('fed.bat', 'w')
148
103
            f.write('@rem dummy fed')
149
104
            f.close()
150
 
            return name
 
105
            os.environ['BZR_EDITOR'] = 'fed.bat'
151
106
        else:
152
 
            name = basename + '.sh'
153
 
            f = file(name, 'wb')
 
107
            f = file('fed.sh', 'wb')
154
108
            f.write('#!/bin/sh\n')
155
109
            f.close()
156
 
            os.chmod(name, 0755)
157
 
            return './' + name
 
110
            os.chmod('fed.sh', 0755)
 
111
            os.environ['BZR_EDITOR'] = './fed.sh'
158
112
 
159
 
    def test_run_editor(self):
160
 
        self.overrideEnv('BZR_EDITOR', self.make_do_nothing_editor())
161
113
        self.assertEqual(True, msgeditor._run_editor(''),
162
114
                         'Unable to run dummy fake editor')
163
115
 
164
 
    def test_parse_editor_name(self):
165
 
        """Correctly interpret names with spaces.
166
 
 
167
 
        See <https://bugs.launchpad.net/bzr/+bug/220331>
168
 
        """
169
 
        self.overrideEnv('BZR_EDITOR',
170
 
            '"%s"' % self.make_do_nothing_editor('name with spaces'))
171
 
        self.assertEqual(True, msgeditor._run_editor('a_filename'))    
172
 
 
173
116
    def make_fake_editor(self, message='test message from fed\\n'):
174
117
        """Set up environment so that an editor will be a known script.
175
118
 
200
143
"%s" fed.py %%1
201
144
""" % sys.executable)
202
145
            f.close()
203
 
            self.overrideEnv('BZR_EDITOR', 'fed.bat')
 
146
            os.environ['BZR_EDITOR'] = 'fed.bat'
204
147
        else:
205
148
            # [non-win32] make python script executable and set BZR_EDITOR
206
149
            os.chmod('fed.py', 0755)
207
 
            self.overrideEnv('BZR_EDITOR', './fed.py')
 
150
            os.environ['BZR_EDITOR'] = './fed.py'
208
151
 
209
152
    def test_edit_commit_message(self):
210
153
        working_tree = self.make_uncommitted_tree()
239
182
        working_tree = self.make_uncommitted_tree()
240
183
 
241
184
        if sys.platform == 'win32':
242
 
            editor = 'cmd.exe /c del'
 
185
            os.environ['BZR_EDITOR'] = 'cmd.exe /c del'
243
186
        else:
244
 
            editor = 'rm'
245
 
        self.overrideEnv('BZR_EDITOR', editor)
 
187
            os.environ['BZR_EDITOR'] = 'rm'
246
188
 
247
189
        self.assertRaises((IOError, OSError), msgeditor.edit_commit_message, '')
248
190
 
249
191
    def test__get_editor(self):
250
 
        self.overrideEnv('BZR_EDITOR', 'bzr_editor')
251
 
        self.overrideEnv('VISUAL', 'visual')
252
 
        self.overrideEnv('EDITOR', 'editor')
253
 
 
254
 
        conf = config.GlobalConfig.from_string('editor = config_editor\n',
255
 
                                               save=True)
256
 
 
257
 
        editors = list(msgeditor._get_editor())
258
 
        editors = [editor for (editor, cfg_src) in editors]
259
 
 
260
 
        self.assertEqual(['bzr_editor', 'config_editor', 'visual', 'editor'],
261
 
                         editors[:4])
262
 
 
263
 
        if sys.platform == 'win32':
264
 
            self.assertEqual(['wordpad.exe', 'notepad.exe'], editors[4:])
265
 
        else:
266
 
            self.assertEqual(['/usr/bin/editor', 'vi', 'pico', 'nano', 'joe'],
267
 
                             editors[4:])
268
 
 
269
 
 
270
 
    def test__run_editor_EACCES(self):
271
 
        """If running a configured editor raises EACESS, the user is warned."""
272
 
        self.overrideEnv('BZR_EDITOR', 'eacces.py')
273
 
        f = file('eacces.py', 'wb')
274
 
        f.write('# Not a real editor')
275
 
        f.close()
276
 
        # Make the fake editor unreadable (and unexecutable)
277
 
        os.chmod('eacces.py', 0)
278
 
        # Set $EDITOR so that _run_editor will terminate before trying real
279
 
        # editors.
280
 
        self.overrideEnv('EDITOR', self.make_do_nothing_editor())
281
 
        # Call _run_editor, capturing mutter.warning calls.
282
 
        warnings = []
283
 
        def warning(*args):
284
 
            if len(args) > 1:
285
 
                warnings.append(args[0] % args[1:])
286
 
            else:
287
 
                warnings.append(args[0])
288
 
        _warning = trace.warning
289
 
        trace.warning = warning
 
192
        # Test that _get_editor can return a decent list of items
 
193
        bzr_editor = os.environ.get('BZR_EDITOR')
 
194
        visual = os.environ.get('VISUAL')
 
195
        editor = os.environ.get('EDITOR')
290
196
        try:
291
 
            msgeditor._run_editor('')
 
197
            os.environ['BZR_EDITOR'] = 'bzr_editor'
 
198
            os.environ['VISUAL'] = 'visual'
 
199
            os.environ['EDITOR'] = 'editor'
 
200
 
 
201
            ensure_config_dir_exists()
 
202
            f = open(config_filename(), 'wb')
 
203
            f.write('editor = config_editor\n')
 
204
            f.close()
 
205
 
 
206
            editors = list(msgeditor._get_editor())
 
207
 
 
208
            self.assertEqual(['bzr_editor', 'config_editor', 'visual',
 
209
                              'editor'], editors[:4])
 
210
 
 
211
            if sys.platform == 'win32':
 
212
                self.assertEqual(['wordpad.exe', 'notepad.exe'], editors[4:])
 
213
            else:
 
214
                self.assertEqual(['/usr/bin/editor', 'vi', 'pico', 'nano',
 
215
                                  'joe'], editors[4:])
 
216
 
292
217
        finally:
293
 
            trace.warning = _warning
294
 
        self.assertStartsWith(warnings[0], 'Could not start editor "eacces.py"')
 
218
            # Restore the environment
 
219
            if bzr_editor is None:
 
220
                del os.environ['BZR_EDITOR']
 
221
            else:
 
222
                os.environ['BZR_EDITOR'] = bzr_editor
 
223
            if visual is None:
 
224
                del os.environ['VISUAL']
 
225
            else:
 
226
                os.environ['VISUAL'] = visual
 
227
            if editor is None:
 
228
                del os.environ['EDITOR']
 
229
            else:
 
230
                os.environ['EDITOR'] = editor
295
231
 
296
232
    def test__create_temp_file_with_commit_template(self):
297
233
        # check that commit template written properly
309
245
        self.assertFileEqual(expected, msgfilename)
310
246
 
311
247
    def test__create_temp_file_with_commit_template_in_unicode_dir(self):
312
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
248
        from bzrlib.tests.test_diff import UnicodeFilename
 
249
        self.requireFeature(UnicodeFilename)
313
250
        if hasattr(self, 'info'):
314
 
            tmpdir = self.info['directory']
315
 
            os.mkdir(tmpdir)
316
 
            # Force the creation of temp file in a directory whose name
317
 
            # requires some encoding support
318
 
            msgeditor._create_temp_file_with_commit_template('infotext',
319
 
                                                             tmpdir=tmpdir)
 
251
            os.mkdir(self.info['directory'])
 
252
            os.chdir(self.info['directory'])
 
253
            msgeditor._create_temp_file_with_commit_template('infotext')
320
254
        else:
321
255
            raise TestNotApplicable('Test run elsewhere with non-ascii data.')
322
256
 
329
263
        self.assertFileEqual('', msgfilename)
330
264
 
331
265
    def test_unsupported_encoding_commit_message(self):
332
 
        self.overrideEnv('LANG', 'C')
333
 
        # LANG env variable has no effect on Windows
334
 
        # but some characters anyway cannot be represented
335
 
        # in default user encoding
336
 
        char = probe_bad_non_ascii(osutils.get_user_encoding())
337
 
        if char is None:
338
 
            raise TestSkipped('Cannot find suitable non-ascii character '
339
 
                'for user_encoding (%s)' % osutils.get_user_encoding())
340
 
 
341
 
        self.make_fake_editor(message=char)
342
 
 
343
 
        working_tree = self.make_uncommitted_tree()
344
 
        self.assertRaises(errors.BadCommitMessageEncoding,
345
 
                          msgeditor.edit_commit_message, '')
346
 
 
347
 
    def test_generate_commit_message_template_no_hooks(self):
348
 
        commit_obj = commit.Commit()
349
 
        self.assertIs(None,
350
 
            msgeditor.generate_commit_message_template(commit_obj))
351
 
 
352
 
    def test_generate_commit_message_template_hook(self):
353
 
        msgeditor.hooks.install_named_hook("commit_message_template",
354
 
                lambda commit_obj, msg: "save me some typing\n", None)
355
 
        commit_obj = commit.Commit()
356
 
        self.assertEquals("save me some typing\n",
357
 
            msgeditor.generate_commit_message_template(commit_obj))
358
 
 
359
 
 
360
 
# GZ 2009-11-17: This wants moving to osutils when the errno checking code is
361
 
class TestPlatformErrnoWorkarounds(TestCaseInTempDir):
362
 
    """Ensuring workarounds enshrined in code actually serve a purpose"""
363
 
 
364
 
    def test_subprocess_call_bad_file(self):
365
 
        if sys.platform != "win32":
366
 
            raise TestNotApplicable("Workarounds for windows only")
367
 
        import subprocess, errno
368
 
        ERROR_BAD_EXE_FORMAT = 193
369
 
        file("textfile.txt", "w").close()
370
 
        e = self.assertRaises(WindowsError, subprocess.call, "textfile.txt")
371
 
        # Python2.4 used the 'winerror' as the errno, which confuses a lot of
372
 
        # our error trapping code. Make sure that we understand the mapping
373
 
        # correctly.
374
 
        if sys.version_info >= (2, 5):
375
 
            self.assertEqual(e.errno, errno.ENOEXEC)
376
 
            self.assertEqual(e.winerror, ERROR_BAD_EXE_FORMAT)
377
 
        else:
378
 
            self.assertEqual(e.errno, ERROR_BAD_EXE_FORMAT)
 
266
        old_env = osutils.set_or_unset_env('LANG', 'C')
 
267
        try:
 
268
            # LANG env variable has no effect on Windows
 
269
            # but some characters anyway cannot be represented
 
270
            # in default user encoding
 
271
            char = probe_bad_non_ascii(bzrlib.user_encoding)
 
272
            if char is None:
 
273
                raise TestSkipped('Cannot find suitable non-ascii character '
 
274
                    'for user_encoding (%s)' % bzrlib.user_encoding)
 
275
 
 
276
            self.make_fake_editor(message=char)
 
277
 
 
278
            working_tree = self.make_uncommitted_tree()
 
279
            self.assertRaises(errors.BadCommitMessageEncoding,
 
280
                              msgeditor.edit_commit_message, '')
 
281
        finally:
 
282
            osutils.set_or_unset_env('LANG', old_env)