diff --git a/mercurial/utils/procutil.py b/mercurial/utils/procutil.py --- a/mercurial/utils/procutil.py +++ b/mercurial/utils/procutil.py @@ -80,7 +80,7 @@ def make_line_buffered(stream): - if pycompat.ispy3 and not isinstance(stream, io.BufferedIOBase): + if not isinstance(stream, io.BufferedIOBase): # On Python 3, buffered streams can be expected to subclass # BufferedIOBase. This is definitively the case for the streams # initialized by the interpreter. For unbuffered streams, we don't need @@ -121,7 +121,6 @@ def _make_write_all(stream): - assert pycompat.ispy3 if isinstance(stream, WriteAllWrapper): return stream if isinstance(stream, io.BufferedIOBase): @@ -133,52 +132,32 @@ return WriteAllWrapper(stream) -if pycompat.ispy3: - # Python 3 implements its own I/O streams. Unlike stdio of C library, - # sys.stdin/stdout/stderr may be None if underlying fd is closed. - - # TODO: .buffer might not exist if std streams were replaced; we'll need - # a silly wrapper to make a bytes stream backed by a unicode one. +# Python 3 implements its own I/O streams. Unlike stdio of C library, +# sys.stdin/stdout/stderr may be None if underlying fd is closed. - if sys.stdin is None: - stdin = BadFile() - else: - stdin = sys.stdin.buffer - if sys.stdout is None: - stdout = BadFile() - else: - stdout = _make_write_all(sys.stdout.buffer) - if sys.stderr is None: - stderr = BadFile() - else: - stderr = _make_write_all(sys.stderr.buffer) +# TODO: .buffer might not exist if std streams were replaced; we'll need +# a silly wrapper to make a bytes stream backed by a unicode one. - if pycompat.iswindows: - # Work around Windows bugs. - stdout = platform.winstdout(stdout) # pytype: disable=module-attr - stderr = platform.winstdout(stderr) # pytype: disable=module-attr - if isatty(stdout): - # The standard library doesn't offer line-buffered binary streams. - stdout = make_line_buffered(stdout) +if sys.stdin is None: + stdin = BadFile() +else: + stdin = sys.stdin.buffer +if sys.stdout is None: + stdout = BadFile() else: - # Python 2 uses the I/O streams provided by the C library. - stdin = sys.stdin - stdout = sys.stdout - stderr = sys.stderr - if pycompat.iswindows: - # Work around Windows bugs. - stdout = platform.winstdout(stdout) # pytype: disable=module-attr - stderr = platform.winstdout(stderr) # pytype: disable=module-attr - if isatty(stdout): - if pycompat.iswindows: - # The Windows C runtime library doesn't support line buffering. - stdout = make_line_buffered(stdout) - else: - # glibc determines buffering on first write to stdout - if we - # replace a TTY destined stdout with a pipe destined stdout (e.g. - # pager), we want line buffering. - stdout = os.fdopen(stdout.fileno(), 'wb', 1) + stdout = _make_write_all(sys.stdout.buffer) +if sys.stderr is None: + stderr = BadFile() +else: + stderr = _make_write_all(sys.stderr.buffer) +if pycompat.iswindows: + # Work around Windows bugs. + stdout = platform.winstdout(stdout) # pytype: disable=module-attr + stderr = platform.winstdout(stderr) # pytype: disable=module-attr +if isatty(stdout): + # The standard library doesn't offer line-buffered binary streams. + stdout = make_line_buffered(stdout) findexe = platform.findexe _gethgcmd = platform.gethgcmd @@ -704,7 +683,7 @@ else: - def runbgcommandpy3( + def runbgcommand( cmd, env, shell=False, @@ -787,128 +766,3 @@ returncode = p.wait if record_wait is not None: record_wait(returncode) - - def runbgcommandpy2( - cmd, - env, - shell=False, - stdout=None, - stderr=None, - ensurestart=True, - record_wait=None, - stdin_bytes=None, - ): - """Spawn a command without waiting for it to finish. - - - When `record_wait` is not None, the spawned process will not be fully - detached and the `record_wait` argument will be called with a the - `Subprocess.wait` function for the spawned process. This is mostly - useful for developers that need to make sure the spawned process - finished before a certain point. (eg: writing test)""" - if pycompat.isdarwin: - # avoid crash in CoreFoundation in case another thread - # calls gui() while we're calling fork(). - gui() - - # double-fork to completely detach from the parent process - # based on http://code.activestate.com/recipes/278731 - if record_wait is None: - pid = os.fork() - if pid: - if not ensurestart: - # Even though we're not waiting on the child process, - # we still must call waitpid() on it at some point so - # it's not a zombie/defunct. This is especially relevant for - # chg since the parent process won't die anytime soon. - # We use a thread to make the overhead tiny. - def _do_wait(): - os.waitpid(pid, 0) - - t = threading.Thread(target=_do_wait) - t.daemon = True - t.start() - return - # Parent process - (_pid, status) = os.waitpid(pid, 0) - if os.WIFEXITED(status): - returncode = os.WEXITSTATUS(status) - else: - returncode = -(os.WTERMSIG(status)) - if returncode != 0: - # The child process's return code is 0 on success, an errno - # value on failure, or 255 if we don't have a valid errno - # value. - # - # (It would be slightly nicer to return the full exception info - # over a pipe as the subprocess module does. For now it - # doesn't seem worth adding that complexity here, though.) - if returncode == 255: - returncode = errno.EINVAL - raise OSError( - returncode, - b'error running %r: %s' - % (cmd, os.strerror(returncode)), - ) - return - - returncode = 255 - stdin = None - - try: - if record_wait is None: - # Start a new session - os.setsid() - # connect stdin to devnull to make sure the subprocess can't - # muck up that stream for mercurial. - if stdin_bytes is None: - stdin = open(os.devnull, b'r') - else: - stdin = pycompat.unnamedtempfile() - stdin.write(stdin_bytes) - stdin.flush() - stdin.seek(0) - - if stdout is None: - stdout = open(os.devnull, b'w') - if stderr is None: - stderr = open(os.devnull, b'w') - - p = subprocess.Popen( - cmd, - shell=shell, - env=env, - close_fds=True, - stdin=stdin, - stdout=stdout, - stderr=stderr, - ) - if record_wait is not None: - record_wait(p.wait) - returncode = 0 - except EnvironmentError as ex: - returncode = ex.errno & 0xFF - if returncode == 0: - # This shouldn't happen, but just in case make sure the - # return code is never 0 here. - returncode = 255 - except Exception: - returncode = 255 - finally: - # mission accomplished, this child needs to exit and not - # continue the hg process here. - if stdin is not None: - stdin.close() - if record_wait is None: - os._exit(returncode) - - if pycompat.ispy3: - # This branch is more robust, because it avoids running python - # code (hence gc finalizers, like sshpeer.__del__, which - # blocks). But we can't easily do the equivalent in py2, - # because of the lack of start_new_session=True flag. Given - # that the py2 branch should die soon, the short-lived - # duplication seems acceptable. - runbgcommand = runbgcommandpy3 - else: - runbgcommand = runbgcommandpy2