[PATCH 1 of 2 V2] py3: partially fix pager spawning on Windows

Matt Harbison mharbison72 at gmail.com
Mon Sep 17 05:15:16 UTC 2018


# HG changeset patch
# User Matt Harbison <matt_harbison at yahoo.com>
# Date 1537032701 14400
#      Sat Sep 15 13:31:41 2018 -0400
# Node ID 91531f9754a5f032fa635dc506091f23519bfdc3
# Parent  8bfbb25859f1455e908b8cff52d7ef30339a3db8
py3: partially fix pager spawning on Windows

Previously, spinning up the pager crashed because the command and environment
was in bytes.  (See also 543a788eea2d.)  Now it aborts with an invalid handle:

    $ HGMODULEPOLICY=py py -3 ../hg --traceback --config extensions.evolve=!
    Traceback (most recent call last):
    File "c:\Users\Matt\projects\hg\mercurial\ui.py", line 967, in _write
      self.fout.write(''.join(msgs))
    File "c:\Users\Matt\projects\hg\mercurial\windows.py", line 173, in write
      self.fp.write(s[start:end])
    OSError: [WinError 6] The handle is invalid

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
      File "c:\Users\Matt\projects\hg\mercurial\scmutil.py", line 164, in callcatch
        return func()
      File "c:\Users\Matt\projects\hg\mercurial\dispatch.py", line 350, in _runcatchfunc
        return _dispatch(req)
      File "c:\Users\Matt\projects\hg\mercurial\dispatch.py", line 930, in _dispatch
        return commands.help_(ui, 'shortlist')
      File "c:\Users\Matt\projects\hg\mercurial\commands.py", line 2930, in help_
        ui.write(formatted)
      File "c:\Users\Matt\projects\hg\mercurial\ui.py", line 948, in write
        self._writenobuf(*args, **opts)
      File "c:\Users\Matt\projects\hg\mercurial\ui.py", line 960, in _writenobuf
        self._write(*msgs, **opts)
      File "c:\Users\Matt\projects\hg\mercurial\ui.py", line 969, in _write
        raise error.StdioError(err)
    mercurial.error.StdioError: [Errno 9] The handle is invalid
    abort: The handle is invalid

The interesting bit here is that the abort message is marked with ANSI color,
but the OSError is not.

diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -1130,10 +1130,10 @@ class ui(object):
 
         try:
             pager = subprocess.Popen(
-                command, shell=shell, bufsize=-1,
+                procutil.tonativestr(command), shell=shell, bufsize=-1,
                 close_fds=procutil.closefds, stdin=subprocess.PIPE,
                 stdout=procutil.stdout, stderr=procutil.stderr,
-                env=procutil.shellenviron(env))
+                env=procutil.tonativeenv(procutil.shellenviron(env)))
         except OSError as e:
             if e.errno == errno.ENOENT and not shell:
                 self.warn(_("missing pager command '%s', skipping pager\n")
diff --git a/mercurial/utils/procutil.py b/mercurial/utils/procutil.py
--- a/mercurial/utils/procutil.py
+++ b/mercurial/utils/procutil.py
@@ -320,10 +320,19 @@ def shellenviron(environ=None):
 if pycompat.iswindows:
     def shelltonative(cmd, env):
         return platform.shelltocmdexe(cmd, shellenviron(env))
+
+    tonativestr = encoding.strfromlocal
 else:
     def shelltonative(cmd, env):
         return cmd
 
+    tonativestr = pycompat.identity
+
+def tonativeenv(env):
+    '''convert the environment from bytes to strings suitable for Popen(), etc.
+    '''
+    return pycompat.rapply(tonativestr, env)
+
 def system(cmd, environ=None, cwd=None, out=None):
     '''enhanced shell command execution.
     run with environment maybe modified, maybe in different dir.


More information about the Mercurial-devel mailing list