~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_msgeditor.py

  • Committer: John Arbash Meinel
  • Date: 2008-08-28 20:13:31 UTC
  • mfrom: (3658 +trunk)
  • mto: This revision was merged to the branch mainline in revision 3688.
  • Revision ID: john@arbash-meinel.com-20080828201331-dqffxf54l2heokll
Merge bzr.dev 3658

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
28
    tests,
30
 
    trace,
31
29
    )
 
30
from bzrlib.branch import Branch
 
31
from bzrlib.config import ensure_config_dir_exists, config_filename
32
32
from bzrlib.msgeditor import (
33
33
    make_commit_message_template_encoded,
34
34
    edit_commit_message_encoded
35
35
)
36
36
from bzrlib.tests import (
37
 
    features,
38
 
    TestCaseInTempDir,
 
37
    iter_suite_tests,
 
38
    probe_bad_non_ascii,
 
39
    split_suite_by_re,
39
40
    TestCaseWithTransport,
40
41
    TestNotApplicable,
41
42
    TestSkipped,
42
 
    multiply_tests,
43
 
    probe_bad_non_ascii,
44
 
    split_suite_by_re,
45
43
    )
46
 
from bzrlib.tests.EncodingAdapter import encoding_scenarios
 
44
from bzrlib.tests.EncodingAdapter import EncodingTestAdapter
47
45
from bzrlib.trace import mutter
48
46
 
49
47
 
51
49
    """Parameterize the test for tempfile creation with different encodings."""
52
50
    to_adapt, result = split_suite_by_re(standard_tests,
53
51
        "test__create_temp_file_with_commit_template_in_unicode_dir")
54
 
    return multiply_tests(to_adapt, encoding_scenarios, result)
 
52
    for test in iter_suite_tests(to_adapt):
 
53
        result.addTests(EncodingTestAdapter().adapt(test))
 
54
    return result
55
55
 
56
56
 
57
57
class MsgEditorTest(TestCaseWithTransport):
68
68
                "filesystem encoding %s" % sys.getfilesystemencoding())
69
69
        working_tree.add(filename)
70
70
        return working_tree
71
 
 
 
71
    
72
72
    def test_commit_template(self):
73
73
        """Test building a commit message template"""
74
74
        working_tree = self.make_uncommitted_tree()
80
80
  hell\u00d8
81
81
""")
82
82
 
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
83
    def test_commit_template_encoded(self):
116
84
        """Test building a commit message template"""
117
85
        working_tree = self.make_uncommitted_tree()
142
110
  hell\u00d8
143
111
""".encode('utf8') in template)
144
112
 
145
 
    def make_do_nothing_editor(self, basename='fed'):
 
113
    def test_run_editor(self):
146
114
        if sys.platform == "win32":
147
 
            name = basename + '.bat'
148
 
            f = file(name, 'w')
 
115
            f = file('fed.bat', 'w')
149
116
            f.write('@rem dummy fed')
150
117
            f.close()
151
 
            return name
 
118
            os.environ['BZR_EDITOR'] = 'fed.bat'
152
119
        else:
153
 
            name = basename + '.sh'
154
 
            f = file(name, 'wb')
 
120
            f = file('fed.sh', 'wb')
155
121
            f.write('#!/bin/sh\n')
156
122
            f.close()
157
 
            os.chmod(name, 0755)
158
 
            return './' + name
 
123
            os.chmod('fed.sh', 0755)
 
124
            os.environ['BZR_EDITOR'] = './fed.sh'
159
125
 
160
 
    def test_run_editor(self):
161
 
        self.overrideEnv('BZR_EDITOR', self.make_do_nothing_editor())
162
126
        self.assertEqual(True, msgeditor._run_editor(''),
163
127
                         'Unable to run dummy fake editor')
164
128
 
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
129
    def make_fake_editor(self, message='test message from fed\\n'):
175
130
        """Set up environment so that an editor will be a known script.
176
131
 
201
156
"%s" fed.py %%1
202
157
""" % sys.executable)
203
158
            f.close()
204
 
            self.overrideEnv('BZR_EDITOR', 'fed.bat')
 
159
            os.environ['BZR_EDITOR'] = 'fed.bat'
205
160
        else:
206
161
            # [non-win32] make python script executable and set BZR_EDITOR
207
162
            os.chmod('fed.py', 0755)
208
 
            self.overrideEnv('BZR_EDITOR', './fed.py')
 
163
            os.environ['BZR_EDITOR'] = './fed.py'
209
164
 
210
165
    def test_edit_commit_message(self):
211
166
        working_tree = self.make_uncommitted_tree()
240
195
        working_tree = self.make_uncommitted_tree()
241
196
 
242
197
        if sys.platform == 'win32':
243
 
            editor = 'cmd.exe /c del'
 
198
            os.environ['BZR_EDITOR'] = 'cmd.exe /c del'
244
199
        else:
245
 
            editor = 'rm'
246
 
        self.overrideEnv('BZR_EDITOR', editor)
 
200
            os.environ['BZR_EDITOR'] = 'rm'
247
201
 
248
202
        self.assertRaises((IOError, OSError), msgeditor.edit_commit_message, '')
249
203
 
250
204
    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
 
205
        # Test that _get_editor can return a decent list of items
 
206
        bzr_editor = os.environ.get('BZR_EDITOR')
 
207
        visual = os.environ.get('VISUAL')
 
208
        editor = os.environ.get('EDITOR')
291
209
        try:
292
 
            msgeditor._run_editor('')
 
210
            os.environ['BZR_EDITOR'] = 'bzr_editor'
 
211
            os.environ['VISUAL'] = 'visual'
 
212
            os.environ['EDITOR'] = 'editor'
 
213
 
 
214
            ensure_config_dir_exists()
 
215
            f = open(config_filename(), 'wb')
 
216
            f.write('editor = config_editor\n')
 
217
            f.close()
 
218
 
 
219
            editors = list(msgeditor._get_editor())
 
220
 
 
221
            self.assertEqual(['bzr_editor', 'config_editor', 'visual',
 
222
                              'editor'], editors[:4])
 
223
 
 
224
            if sys.platform == 'win32':
 
225
                self.assertEqual(['wordpad.exe', 'notepad.exe'], editors[4:])
 
226
            else:
 
227
                self.assertEqual(['/usr/bin/editor', 'vi', 'pico', 'nano',
 
228
                                  'joe'], editors[4:])
 
229
 
293
230
        finally:
294
 
            trace.warning = _warning
295
 
        self.assertStartsWith(warnings[0], 'Could not start editor "eacces.py"')
 
231
            # Restore the environment
 
232
            if bzr_editor is None:
 
233
                del os.environ['BZR_EDITOR']
 
234
            else:
 
235
                os.environ['BZR_EDITOR'] = bzr_editor
 
236
            if visual is None:
 
237
                del os.environ['VISUAL']
 
238
            else:
 
239
                os.environ['VISUAL'] = visual
 
240
            if editor is None:
 
241
                del os.environ['EDITOR']
 
242
            else:
 
243
                os.environ['EDITOR'] = editor
296
244
 
297
245
    def test__create_temp_file_with_commit_template(self):
298
246
        # check that commit template written properly
310
258
        self.assertFileEqual(expected, msgfilename)
311
259
 
312
260
    def test__create_temp_file_with_commit_template_in_unicode_dir(self):
313
 
        self.requireFeature(features.UnicodeFilenameFeature)
 
261
        self.requireFeature(tests.UnicodeFilenameFeature)
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)