~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_msgeditor.py

  • Committer: John Arbash Meinel
  • Author(s): Mark Hammond
  • Date: 2008-09-09 17:02:21 UTC
  • mto: This revision was merged to the branch mainline in revision 3697.
  • Revision ID: john@arbash-meinel.com-20080909170221-svim3jw2mrz0amp3
An updated transparent icon for bzr.

Show diffs side-by-side

added added

removed removed

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