py3: partially fix pager spawning on Windows
authorMatt Harbison <matt_harbison@yahoo.com>
Sat, 15 Sep 2018 13:31:41 -0400
changeset 39662 50f46b771921
parent 39661 8bfbb25859f1
child 39663 b6fa1f628bbe
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.
mercurial/ui.py
mercurial/utils/procutil.py
--- a/mercurial/ui.py	Sat Sep 15 10:35:00 2018 +0900
+++ b/mercurial/ui.py	Sat Sep 15 13:31:41 2018 -0400
@@ -1130,10 +1130,10 @@
 
         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")
--- a/mercurial/utils/procutil.py	Sat Sep 15 10:35:00 2018 +0900
+++ b/mercurial/utils/procutil.py	Sat Sep 15 13:31:41 2018 -0400
@@ -320,10 +320,19 @@
 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.