Rev 3911: Improve error handling in msgeditor._run_editor. (Andrew Bennetts) in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Fri Dec 19 06:56:55 GMT 2008


At file:///home/pqm/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 3911
revision-id: pqm at pqm.ubuntu.com-20081219065652-z3g78j4hrvdnf8bj
parent: pqm at pqm.ubuntu.com-20081217102138-pz7pfli9o3k50zq7
parent: andrew.bennetts at canonical.com-20081219061459-a6gcn8lwzweor8ri
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Fri 2008-12-19 06:56:52 +0000
message:
  Improve error handling in msgeditor._run_editor. (Andrew Bennetts)
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/msgeditor.py            msgeditor.py-20050901111708-ef6d8de98f5d8f2f
  bzrlib/tests/test_msgeditor.py test_msgeditor.py-20051202041359-920315ec6011ee51
    ------------------------------------------------------------
    revno: 3910.1.4
    revision-id: andrew.bennetts at canonical.com-20081219061459-a6gcn8lwzweor8ri
    parent: andrew.bennetts at canonical.com-20081219061228-jnw1n111u3impfi0
    committer: Andrew Bennetts <andrew.bennetts at canonical.com>
    branch nick: msgeditor-failure-handling
    timestamp: Fri 2008-12-19 17:14:59 +1100
    message:
      Add NEWS entry.
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
    ------------------------------------------------------------
    revno: 3910.1.3
    revision-id: andrew.bennetts at canonical.com-20081219061228-jnw1n111u3impfi0
    parent: andrew.bennetts at canonical.com-20081218025154-xwjqtnbpa619pakv
    committer: Andrew Bennetts <andrew.bennetts at canonical.com>
    branch nick: msgeditor-failure-handling
    timestamp: Fri 2008-12-19 17:12:28 +1100
    message:
      Tweak warning slightly.
    modified:
      bzrlib/msgeditor.py            msgeditor.py-20050901111708-ef6d8de98f5d8f2f
      bzrlib/tests/test_msgeditor.py test_msgeditor.py-20051202041359-920315ec6011ee51
    ------------------------------------------------------------
    revno: 3910.1.2
    revision-id: andrew.bennetts at canonical.com-20081218025154-xwjqtnbpa619pakv
    parent: andrew.bennetts at canonical.com-20081217234306-uiz0pumfeaemy9ky
    committer: Andrew Bennetts <andrew.bennetts at canonical.com>
    branch nick: msgeditor-failure-handling
    timestamp: Thu 2008-12-18 13:51:54 +1100
    message:
      Fix thinko.
    modified:
      bzrlib/msgeditor.py            msgeditor.py-20050901111708-ef6d8de98f5d8f2f
    ------------------------------------------------------------
    revno: 3910.1.1
    revision-id: andrew.bennetts at canonical.com-20081217234306-uiz0pumfeaemy9ky
    parent: pqm at pqm.ubuntu.com-20081217102138-pz7pfli9o3k50zq7
    committer: Andrew Bennetts <andrew.bennetts at canonical.com>
    branch nick: msgeditor-failure-handling
    timestamp: Thu 2008-12-18 10:43:06 +1100
    message:
      Improve error handling in msgeditor._run_editor.
    modified:
      bzrlib/msgeditor.py            msgeditor.py-20050901111708-ef6d8de98f5d8f2f
      bzrlib/tests/test_msgeditor.py test_msgeditor.py-20051202041359-920315ec6011ee51
=== modified file 'NEWS'
--- a/NEWS	2008-12-17 10:21:38 +0000
+++ b/NEWS	2008-12-19 06:14:59 +0000
@@ -56,6 +56,10 @@
     * Give proper error message for diff with non-existent dotted revno.
       (Marius Kruger, #301969)
 
+    * Handle EACCES (permission denied) errors when launching a message
+      editor, and emit warnings when a configured editor cannot be
+      started. (Andrew Bennetts)
+
     * Preserve transport decorators while following redirections.
       (Vincent Ladeuil, #245964, #270863)
 

=== modified file 'bzrlib/msgeditor.py'
--- a/bzrlib/msgeditor.py	2008-11-11 00:46:06 +0000
+++ b/bzrlib/msgeditor.py	2008-12-19 06:12:28 +0000
@@ -26,45 +26,52 @@
 from bzrlib import (
     config,
     osutils,
+    trace,
     )
 from bzrlib.errors import BzrError, BadCommitMessageEncoding
 from bzrlib.hooks import Hooks
-from bzrlib.trace import warning, mutter
 
 
 def _get_editor():
     """Return a sequence of possible editor binaries for the current platform"""
     try:
-        yield os.environ["BZR_EDITOR"]
+        yield os.environ["BZR_EDITOR"], '$BZR_EDITOR'
     except KeyError:
         pass
 
     e = config.GlobalConfig().get_editor()
     if e is not None:
-        yield e
+        yield e, config.config_filename()
         
     for varname in 'VISUAL', 'EDITOR':
         if varname in os.environ:
-            yield os.environ[varname]
+            yield os.environ[varname], '$' + varname
 
     if sys.platform == 'win32':
         for editor in 'wordpad.exe', 'notepad.exe':
-            yield editor
+            yield editor, None
     else:
         for editor in ['/usr/bin/editor', 'vi', 'pico', 'nano', 'joe']:
-            yield editor
+            yield editor, None
 
 
 def _run_editor(filename):
     """Try to execute an editor to edit the commit message."""
-    for e in _get_editor():
-        edargs = e.split(' ')
+    for candidate, candidate_source in _get_editor():
+        edargs = candidate.split(' ')
         try:
             ## mutter("trying editor: %r", (edargs +[filename]))
             x = call(edargs + [filename])
         except OSError, e:
             # We're searching for an editor, so catch safe errors and continue
-            if e.errno in (errno.ENOENT, ):
+            if e.errno in (errno.ENOENT, errno.EACCES):
+                if candidate_source is not None:
+                    # We tried this editor because some user configuration (an
+                    # environment variable or config file) said to try it.  Let
+                    # the user know their configuration is broken.
+                    trace.warning(
+                        'Could not start editor "%s" (specified by %s): %s\n'
+                        % (candidate, candidate_source, str(e)))
                 continue
             raise
         if x == 0:
@@ -183,7 +190,8 @@
             try:
                 os.unlink(msgfilename)
             except IOError, e:
-                warning("failed to unlink %s: %s; ignored", msgfilename, e)
+                trace.warning(
+                    "failed to unlink %s: %s; ignored", msgfilename, e)
 
 
 def _create_temp_file_with_commit_template(infotext,

=== modified file 'bzrlib/tests/test_msgeditor.py'
--- a/bzrlib/tests/test_msgeditor.py	2008-11-10 22:42:21 +0000
+++ b/bzrlib/tests/test_msgeditor.py	2008-12-19 06:12:28 +0000
@@ -26,6 +26,7 @@
     msgeditor,
     osutils,
     tests,
+    trace,
     )
 from bzrlib.branch import Branch
 from bzrlib.config import ensure_config_dir_exists, config_filename
@@ -110,19 +111,21 @@
   hell\u00d8
 """.encode('utf8') in template)
 
-    def test_run_editor(self):
+    def make_do_nothing_editor(self):
         if sys.platform == "win32":
             f = file('fed.bat', 'w')
             f.write('@rem dummy fed')
             f.close()
-            os.environ['BZR_EDITOR'] = 'fed.bat'
+            return 'fed.bat'
         else:
             f = file('fed.sh', 'wb')
             f.write('#!/bin/sh\n')
             f.close()
             os.chmod('fed.sh', 0755)
-            os.environ['BZR_EDITOR'] = './fed.sh'
+            return './fed.sh'
 
+    def test_run_editor(self):
+        os.environ['BZR_EDITOR'] = self.make_do_nothing_editor()
         self.assertEqual(True, msgeditor._run_editor(''),
                          'Unable to run dummy fake editor')
 
@@ -217,6 +220,7 @@
             f.close()
 
             editors = list(msgeditor._get_editor())
+            editors = [editor for (editor, cfg_src) in editors]
 
             self.assertEqual(['bzr_editor', 'config_editor', 'visual',
                               'editor'], editors[:4])
@@ -242,6 +246,29 @@
             else:
                 os.environ['EDITOR'] = editor
 
+    def test__run_editor_EACCES(self):
+        """If running a configured editor raises EACESS, the user is warned."""
+        os.environ['BZR_EDITOR'] = 'eacces.py'
+        f = file('eacces.py', 'wb')
+        f.write('# Not a real editor')
+        f.close()
+        # Make the fake editor unreadable (and unexecutable)
+        os.chmod('eacces.py', 0)
+        # Set $EDITOR so that _run_editor will terminate before trying real
+        # editors.
+        os.environ['EDITOR'] = self.make_do_nothing_editor()
+        # Call _run_editor, capturing mutter.warning calls.
+        warnings = []
+        def warning(*args):
+            warnings.append(args[0] % args[1:])
+        _warning = trace.warning
+        trace.warning = warning
+        try:
+            msgeditor._run_editor('')
+        finally:
+            trace.warning = _warning
+        self.assertStartsWith(warnings[0], 'Could not start editor "eacces.py"')
+
     def test__create_temp_file_with_commit_template(self):
         # check that commit template written properly
         # and has platform native line-endings (CRLF on win32)




More information about the bazaar-commits mailing list