~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_msgeditor.py

  • Committer: Alexander Belchenko
  • Date: 2007-11-02 05:12:17 UTC
  • mto: This revision was merged to the branch mainline in revision 2957.
  • Revision ID: bialix@ukr.net-20071102051217-5ebfnblbcihhut5g
John's review

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,
30
28
    )
 
29
from bzrlib.branch import Branch
 
30
from bzrlib.config import ensure_config_dir_exists, config_filename
31
31
from bzrlib.msgeditor import (
32
32
    make_commit_message_template_encoded,
33
33
    edit_commit_message_encoded
34
34
)
35
35
from bzrlib.tests import (
36
 
    features,
37
 
    TestCaseInTempDir,
 
36
    probe_bad_non_ascii,
38
37
    TestCaseWithTransport,
39
 
    TestNotApplicable,
40
38
    TestSkipped,
41
 
    multiply_tests,
42
 
    probe_bad_non_ascii,
43
 
    split_suite_by_re,
44
39
    )
45
 
from bzrlib.tests.EncodingAdapter import encoding_scenarios
46
40
from bzrlib.trace import mutter
47
41
 
48
42
 
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
43
class MsgEditorTest(TestCaseWithTransport):
57
44
 
58
45
    def make_uncommitted_tree(self):
67
54
                "filesystem encoding %s" % sys.getfilesystemencoding())
68
55
        working_tree.add(filename)
69
56
        return working_tree
70
 
 
 
57
    
71
58
    def test_commit_template(self):
72
59
        """Test building a commit message template"""
73
60
        working_tree = self.make_uncommitted_tree()
79
66
  hell\u00d8
80
67
""")
81
68
 
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
69
    def test_commit_template_encoded(self):
113
70
        """Test building a commit message template"""
114
71
        working_tree = self.make_uncommitted_tree()
139
96
  hell\u00d8
140
97
""".encode('utf8') in template)
141
98
 
142
 
    def make_do_nothing_editor(self, basename='fed'):
 
99
    def test_run_editor(self):
143
100
        if sys.platform == "win32":
144
 
            name = basename + '.bat'
145
 
            f = file(name, 'w')
 
101
            f = file('fed.bat', 'w')
146
102
            f.write('@rem dummy fed')
147
103
            f.close()
148
 
            return name
 
104
            os.environ['BZR_EDITOR'] = 'fed.bat'
149
105
        else:
150
 
            name = basename + '.sh'
151
 
            f = file(name, 'wb')
 
106
            f = file('fed.sh', 'wb')
152
107
            f.write('#!/bin/sh\n')
153
108
            f.close()
154
 
            os.chmod(name, 0755)
155
 
            return './' + name
 
109
            os.chmod('fed.sh', 0755)
 
110
            os.environ['BZR_EDITOR'] = './fed.sh'
156
111
 
157
 
    def test_run_editor(self):
158
 
        self.overrideEnv('BZR_EDITOR', self.make_do_nothing_editor())
159
112
        self.assertEqual(True, msgeditor._run_editor(''),
160
113
                         'Unable to run dummy fake editor')
161
114
 
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
115
    def make_fake_editor(self, message='test message from fed\\n'):
172
116
        """Set up environment so that an editor will be a known script.
173
117
 
198
142
"%s" fed.py %%1
199
143
""" % sys.executable)
200
144
            f.close()
201
 
            self.overrideEnv('BZR_EDITOR', 'fed.bat')
 
145
            os.environ['BZR_EDITOR'] = 'fed.bat'
202
146
        else:
203
147
            # [non-win32] make python script executable and set BZR_EDITOR
204
148
            os.chmod('fed.py', 0755)
205
 
            self.overrideEnv('BZR_EDITOR', './fed.py')
 
149
            os.environ['BZR_EDITOR'] = './fed.py'
206
150
 
207
151
    def test_edit_commit_message(self):
208
152
        working_tree = self.make_uncommitted_tree()
237
181
        working_tree = self.make_uncommitted_tree()
238
182
 
239
183
        if sys.platform == 'win32':
240
 
            editor = 'cmd.exe /c del'
 
184
            os.environ['BZR_EDITOR'] = 'cmd.exe /c del'
241
185
        else:
242
 
            editor = 'rm'
243
 
        self.overrideEnv('BZR_EDITOR', editor)
 
186
            os.environ['BZR_EDITOR'] = 'rm'
244
187
 
245
188
        self.assertRaises((IOError, OSError), msgeditor.edit_commit_message, '')
246
189
 
247
190
    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
 
191
        # Test that _get_editor can return a decent list of items
 
192
        bzr_editor = os.environ.get('BZR_EDITOR')
 
193
        visual = os.environ.get('VISUAL')
 
194
        editor = os.environ.get('EDITOR')
288
195
        try:
289
 
            msgeditor._run_editor('')
 
196
            os.environ['BZR_EDITOR'] = 'bzr_editor'
 
197
            os.environ['VISUAL'] = 'visual'
 
198
            os.environ['EDITOR'] = 'editor'
 
199
 
 
200
            ensure_config_dir_exists()
 
201
            f = open(config_filename(), 'wb')
 
202
            f.write('editor = config_editor\n')
 
203
            f.close()
 
204
 
 
205
            editors = list(msgeditor._get_editor())
 
206
 
 
207
            self.assertEqual(['bzr_editor', 'config_editor', 'visual',
 
208
                              'editor'], editors[:4])
 
209
 
 
210
            if sys.platform == 'win32':
 
211
                self.assertEqual(['wordpad.exe', 'notepad.exe'], editors[4:])
 
212
            else:
 
213
                self.assertEqual(['/usr/bin/editor', 'vi', 'pico', 'nano',
 
214
                                  'joe'], editors[4:])
 
215
 
290
216
        finally:
291
 
            trace.warning = _warning
292
 
        self.assertStartsWith(warnings[0], 'Could not start editor "eacces.py"')
 
217
            # Restore the environment
 
218
            if bzr_editor is None:
 
219
                del os.environ['BZR_EDITOR']
 
220
            else:
 
221
                os.environ['BZR_EDITOR'] = bzr_editor
 
222
            if visual is None:
 
223
                del os.environ['VISUAL']
 
224
            else:
 
225
                os.environ['VISUAL'] = visual
 
226
            if editor is None:
 
227
                del os.environ['EDITOR']
 
228
            else:
 
229
                os.environ['EDITOR'] = editor
293
230
 
294
231
    def test__create_temp_file_with_commit_template(self):
295
232
        # check that commit template written properly
306
243
                                    'infotext'])
307
244
        self.assertFileEqual(expected, msgfilename)
308
245
 
309
 
    def test__create_temp_file_with_commit_template_in_unicode_dir(self):
310
 
        self.requireFeature(features.UnicodeFilenameFeature)
311
 
        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)
318
 
        else:
319
 
            raise TestNotApplicable('Test run elsewhere with non-ascii data.')
320
 
 
321
246
    def test__create_temp_file_with_empty_commit_template(self):
322
247
        # empty file
323
248
        create_file = msgeditor._create_temp_file_with_commit_template
327
252
        self.assertFileEqual('', msgfilename)
328
253
 
329
254
    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)
 
255
        old_env = osutils.set_or_unset_env('LANG', 'C')
 
256
        try:
 
257
            # LANG env variable has no effect on Windows
 
258
            # but some characters anyway cannot be represented
 
259
            # in default user encoding
 
260
            char = probe_bad_non_ascii(bzrlib.user_encoding)
 
261
            if char is None:
 
262
                raise TestSkipped('Cannot find suitable non-ascii character '
 
263
                    'for user_encoding (%s)' % bzrlib.user_encoding)
 
264
 
 
265
            self.make_fake_editor(message=char)
 
266
 
 
267
            working_tree = self.make_uncommitted_tree()
 
268
            self.assertRaises(errors.BadCommitMessageEncoding,
 
269
                              msgeditor.edit_commit_message, '')
 
270
        finally:
 
271
            osutils.set_or_unset_env('LANG', old_env)