~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_msgeditor.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2008-03-16 16:58:03 UTC
  • mfrom: (3224.3.1 news-typo)
  • Revision ID: pqm@pqm.ubuntu.com-20080316165803-tisoc9mpob9z544o
(Matt Nordhoff) Trivial NEWS typo fix

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