annotate mercurial/utils/procutil.py @ 46889:8759e22f1649

procutil: avoid using os.fork() to implement runbgcommand We ran into the following deadlock: - some command creates an ssh peer, then raises without explicitly closing the peer (hg id + extension in our case) - dispatch catches the exception, calls ui.log('commandfinish', ..) (the sshpeer is still not closed), which calls logtoprocess, which calls procutil.runbgcommand. - in the child of runbgcommand's fork(), between the fork and the exec, the opening of file descriptors triggers a gc which runs the destructor for sshpeer, which waits on ssh's stderr being closed, which never happens since ssh's stderr is held open by the parent of the fork where said destructor hasn't run Remotefilelog appears to have a hack around this deadlock as well. I don't know if there's more subtlety to it, because even though the problem is determistic, it is very fragile, so I didn't manage to reduce it. I can imagine three ways of tackling this problem: 1. don't run any python between fork and exec in runbgcommand 2. make the finalizer harmless after the fork 3. close the peer without relying on gc behavior This commit goes with 1, as forking without exec'ing is tricky in general in a language with gc finalizers. And maybe it's better in the presence of rust threads. A future commit will try 2 or 3. Performance wise: at low memory usage, it's an improvement. At higher memory usage, it's about 2x faster than before when ensurestart=True, but 2x slower when ensurestart=False. Not sure if that matters. The reason for that last bit is that the subprocess.Popen always waits for the execve to finish, and at high memory usage, execve is slow because it deallocates the large page table. Numbers and script: before after mem=1.0GB, ensurestart=True 52.1ms 26.0ms mem=1.0GB, ensurestart=False 14.7ms 26.0ms mem=0.5GB, ensurestart=True 23.2ms 11.2ms mem=0.5GB, ensurestart=False 6.2ms 11.3ms mem=0.2GB, ensurestart=True 15.7ms 7.4ms mem=0.2GB, ensurestart=False 4.3ms 8.1ms mem=0.0GB, ensurestart=True 2.3ms 0.7ms mem=0.0GB, ensurestart=False 0.8ms 0.8ms import time for memsize in [1_000_000_000, 500_000_000, 250_000_000, 0]: mem = 'a' * memsize for ensurestart in [True, False]: now = time.time() n = 100 for i in range(n): procutil.runbgcommand([b'true'], {}, ensurestart=ensurestart) after = time.time() ms = (after - now) / float(n) * 1000 print(f'mem={memsize / 1e9:.1f}GB, ensurestart={ensurestart} -> {ms:.1f}ms') Differential Revision: https://phab.mercurial-scm.org/D9019
author Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
date Sun, 13 Sep 2020 22:14:25 -0400
parents d4ba4d51f85f
children 333a2656e981
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
37118
5be286db5fb5 procutil: move process/executable management functions to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37117
diff changeset
1 # procutil.py - utility for managing processes and executable environment
8226
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
2 #
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
3 # Copyright 2005 K. Thananchayan <thananck@yahoo.com>
46819
d4ba4d51f85f contributor: change mentions of mpm to olivia
Raphaël Gomès <rgomes@octobus.net>
parents: 46784
diff changeset
4 # Copyright 2005-2007 Olivia Mackall <olivia@selenic.com>
8226
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
6 #
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
7 # This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9996
diff changeset
8 # GNU General Public License version 2 or any later version.
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
9
37118
5be286db5fb5 procutil: move process/executable management functions to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37117
diff changeset
10 from __future__ import absolute_import
27358
ac839ee45b6a util: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27357
diff changeset
11
37124
6715e8035b4f procutil: introduce context-manager interface for protect/restorestdio
Yuya Nishihara <yuya@tcha.org>
parents: 37123
diff changeset
12 import contextlib
40497
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
13 import errno
36432
1ca4e86c7265 util: handle fileno() on Python 3 throwing io.UnsupportedOperation
Augie Fackler <augie@google.com>
parents: 36422
diff changeset
14 import io
27358
ac839ee45b6a util: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27357
diff changeset
15 import os
ac839ee45b6a util: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27357
diff changeset
16 import signal
ac839ee45b6a util: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27357
diff changeset
17 import subprocess
ac839ee45b6a util: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27357
diff changeset
18 import sys
44781
ed684a82e29b procutil: always waiting on child processes to prevent zombies with 'hg serve'
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 43912
diff changeset
19 import threading
27358
ac839ee45b6a util: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27357
diff changeset
20 import time
3769
96095d9ff1f8 Add encoding detection
Matt Mackall <mpm@selenic.com>
parents: 3767
diff changeset
21
37118
5be286db5fb5 procutil: move process/executable management functions to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37117
diff changeset
22 from ..i18n import _
43089
c59eb1560c44 py3: manually import getattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43085
diff changeset
23 from ..pycompat import (
c59eb1560c44 py3: manually import getattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43085
diff changeset
24 getattr,
c59eb1560c44 py3: manually import getattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43085
diff changeset
25 open,
c59eb1560c44 py3: manually import getattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43085
diff changeset
26 )
37118
5be286db5fb5 procutil: move process/executable management functions to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37117
diff changeset
27
5be286db5fb5 procutil: move process/executable management functions to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37117
diff changeset
28 from .. import (
27358
ac839ee45b6a util: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27357
diff changeset
29 encoding,
ac839ee45b6a util: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27357
diff changeset
30 error,
32367
a9c71d578a1c osutil: switch to policy importer
Yuya Nishihara <yuya@tcha.org>
parents: 32306
diff changeset
31 policy,
28818
6041fb8f2da8 pycompat: add empty and queue to handle py3 divergence
timeless <timeless@mozdev.org>
parents: 28497
diff changeset
32 pycompat,
37083
f99d64e8a4e4 stringutil: move generic string helpers to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37082
diff changeset
33 )
3769
96095d9ff1f8 Add encoding detection
Matt Mackall <mpm@selenic.com>
parents: 3767
diff changeset
34
43671
664e24207728 procutil: move mainfrozen() to new resourceutil.py
Martin von Zweigbergk <martinvonz@google.com>
parents: 43657
diff changeset
35 # Import like this to keep import-checker happy
664e24207728 procutil: move mainfrozen() to new resourceutil.py
Martin von Zweigbergk <martinvonz@google.com>
parents: 43657
diff changeset
36 from ..utils import resourceutil
664e24207728 procutil: move mainfrozen() to new resourceutil.py
Martin von Zweigbergk <martinvonz@google.com>
parents: 43657
diff changeset
37
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43503
diff changeset
38 osutil = policy.importmod('osutil')
32201
4462a981e8df base85: proxy through util module
Yuya Nishihara <yuya@tcha.org>
parents: 32154
diff changeset
39
45042
c88577199023 procutil: split import and reassignment
Manuel Jacob <me@manueljacob.de>
parents: 45041
diff changeset
40 if pycompat.iswindows:
c88577199023 procutil: split import and reassignment
Manuel Jacob <me@manueljacob.de>
parents: 45041
diff changeset
41 from .. import windows as platform
c88577199023 procutil: split import and reassignment
Manuel Jacob <me@manueljacob.de>
parents: 45041
diff changeset
42 else:
c88577199023 procutil: split import and reassignment
Manuel Jacob <me@manueljacob.de>
parents: 45041
diff changeset
43 from .. import posix as platform
c88577199023 procutil: split import and reassignment
Manuel Jacob <me@manueljacob.de>
parents: 45041
diff changeset
44
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
45
30876
3a4c0905f357 util: always force line buffered stdout when stdout is a tty (BC)
Simon Farnsworth <simonfar@fb.com>
parents: 30854
diff changeset
46 def isatty(fp):
3a4c0905f357 util: always force line buffered stdout when stdout is a tty (BC)
Simon Farnsworth <simonfar@fb.com>
parents: 30854
diff changeset
47 try:
3a4c0905f357 util: always force line buffered stdout when stdout is a tty (BC)
Simon Farnsworth <simonfar@fb.com>
parents: 30854
diff changeset
48 return fp.isatty()
3a4c0905f357 util: always force line buffered stdout when stdout is a tty (BC)
Simon Farnsworth <simonfar@fb.com>
parents: 30854
diff changeset
49 except AttributeError:
3a4c0905f357 util: always force line buffered stdout when stdout is a tty (BC)
Simon Farnsworth <simonfar@fb.com>
parents: 30854
diff changeset
50 return False
3a4c0905f357 util: always force line buffered stdout when stdout is a tty (BC)
Simon Farnsworth <simonfar@fb.com>
parents: 30854
diff changeset
51
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
52
46174
a1601ff3877c procutil: introduce pseudo file object that just raises EBADF
Yuya Nishihara <yuya@tcha.org>
parents: 46102
diff changeset
53 class BadFile(io.RawIOBase):
a1601ff3877c procutil: introduce pseudo file object that just raises EBADF
Yuya Nishihara <yuya@tcha.org>
parents: 46102
diff changeset
54 """Dummy file object to simulate closed stdio behavior"""
a1601ff3877c procutil: introduce pseudo file object that just raises EBADF
Yuya Nishihara <yuya@tcha.org>
parents: 46102
diff changeset
55
a1601ff3877c procutil: introduce pseudo file object that just raises EBADF
Yuya Nishihara <yuya@tcha.org>
parents: 46102
diff changeset
56 def readinto(self, b):
a1601ff3877c procutil: introduce pseudo file object that just raises EBADF
Yuya Nishihara <yuya@tcha.org>
parents: 46102
diff changeset
57 raise IOError(errno.EBADF, 'Bad file descriptor')
a1601ff3877c procutil: introduce pseudo file object that just raises EBADF
Yuya Nishihara <yuya@tcha.org>
parents: 46102
diff changeset
58
a1601ff3877c procutil: introduce pseudo file object that just raises EBADF
Yuya Nishihara <yuya@tcha.org>
parents: 46102
diff changeset
59 def write(self, b):
a1601ff3877c procutil: introduce pseudo file object that just raises EBADF
Yuya Nishihara <yuya@tcha.org>
parents: 46102
diff changeset
60 raise IOError(errno.EBADF, 'Bad file descriptor')
a1601ff3877c procutil: introduce pseudo file object that just raises EBADF
Yuya Nishihara <yuya@tcha.org>
parents: 46102
diff changeset
61
a1601ff3877c procutil: introduce pseudo file object that just raises EBADF
Yuya Nishihara <yuya@tcha.org>
parents: 46102
diff changeset
62
45039
2bfbd7d2c204 procutil: define LineBufferedWrapper on all Python versions
Manuel Jacob <me@manueljacob.de>
parents: 45000
diff changeset
63 class LineBufferedWrapper(object):
2bfbd7d2c204 procutil: define LineBufferedWrapper on all Python versions
Manuel Jacob <me@manueljacob.de>
parents: 45000
diff changeset
64 def __init__(self, orig):
2bfbd7d2c204 procutil: define LineBufferedWrapper on all Python versions
Manuel Jacob <me@manueljacob.de>
parents: 45000
diff changeset
65 self.orig = orig
44950
f9734b2d59cc py3: make stdout line-buffered if connected to a TTY
Manuel Jacob <me@manueljacob.de>
parents: 44867
diff changeset
66
45039
2bfbd7d2c204 procutil: define LineBufferedWrapper on all Python versions
Manuel Jacob <me@manueljacob.de>
parents: 45000
diff changeset
67 def __getattr__(self, attr):
2bfbd7d2c204 procutil: define LineBufferedWrapper on all Python versions
Manuel Jacob <me@manueljacob.de>
parents: 45000
diff changeset
68 return getattr(self.orig, attr)
44950
f9734b2d59cc py3: make stdout line-buffered if connected to a TTY
Manuel Jacob <me@manueljacob.de>
parents: 44867
diff changeset
69
45039
2bfbd7d2c204 procutil: define LineBufferedWrapper on all Python versions
Manuel Jacob <me@manueljacob.de>
parents: 45000
diff changeset
70 def write(self, s):
2bfbd7d2c204 procutil: define LineBufferedWrapper on all Python versions
Manuel Jacob <me@manueljacob.de>
parents: 45000
diff changeset
71 orig = self.orig
2bfbd7d2c204 procutil: define LineBufferedWrapper on all Python versions
Manuel Jacob <me@manueljacob.de>
parents: 45000
diff changeset
72 res = orig.write(s)
2bfbd7d2c204 procutil: define LineBufferedWrapper on all Python versions
Manuel Jacob <me@manueljacob.de>
parents: 45000
diff changeset
73 if s.endswith(b'\n'):
2bfbd7d2c204 procutil: define LineBufferedWrapper on all Python versions
Manuel Jacob <me@manueljacob.de>
parents: 45000
diff changeset
74 orig.flush()
2bfbd7d2c204 procutil: define LineBufferedWrapper on all Python versions
Manuel Jacob <me@manueljacob.de>
parents: 45000
diff changeset
75 return res
44950
f9734b2d59cc py3: make stdout line-buffered if connected to a TTY
Manuel Jacob <me@manueljacob.de>
parents: 44867
diff changeset
76
45039
2bfbd7d2c204 procutil: define LineBufferedWrapper on all Python versions
Manuel Jacob <me@manueljacob.de>
parents: 45000
diff changeset
77
2bfbd7d2c204 procutil: define LineBufferedWrapper on all Python versions
Manuel Jacob <me@manueljacob.de>
parents: 45000
diff changeset
78 io.BufferedIOBase.register(LineBufferedWrapper)
44950
f9734b2d59cc py3: make stdout line-buffered if connected to a TTY
Manuel Jacob <me@manueljacob.de>
parents: 44867
diff changeset
79
f9734b2d59cc py3: make stdout line-buffered if connected to a TTY
Manuel Jacob <me@manueljacob.de>
parents: 44867
diff changeset
80
45040
fd205a9c358a procutil: factor out conditional creation of LineBufferedWrapper
Manuel Jacob <me@manueljacob.de>
parents: 45039
diff changeset
81 def make_line_buffered(stream):
fd205a9c358a procutil: factor out conditional creation of LineBufferedWrapper
Manuel Jacob <me@manueljacob.de>
parents: 45039
diff changeset
82 if pycompat.ispy3 and not isinstance(stream, io.BufferedIOBase):
fd205a9c358a procutil: factor out conditional creation of LineBufferedWrapper
Manuel Jacob <me@manueljacob.de>
parents: 45039
diff changeset
83 # On Python 3, buffered streams can be expected to subclass
fd205a9c358a procutil: factor out conditional creation of LineBufferedWrapper
Manuel Jacob <me@manueljacob.de>
parents: 45039
diff changeset
84 # BufferedIOBase. This is definitively the case for the streams
fd205a9c358a procutil: factor out conditional creation of LineBufferedWrapper
Manuel Jacob <me@manueljacob.de>
parents: 45039
diff changeset
85 # initialized by the interpreter. For unbuffered streams, we don't need
fd205a9c358a procutil: factor out conditional creation of LineBufferedWrapper
Manuel Jacob <me@manueljacob.de>
parents: 45039
diff changeset
86 # to emulate line buffering.
fd205a9c358a procutil: factor out conditional creation of LineBufferedWrapper
Manuel Jacob <me@manueljacob.de>
parents: 45039
diff changeset
87 return stream
fd205a9c358a procutil: factor out conditional creation of LineBufferedWrapper
Manuel Jacob <me@manueljacob.de>
parents: 45039
diff changeset
88 if isinstance(stream, LineBufferedWrapper):
fd205a9c358a procutil: factor out conditional creation of LineBufferedWrapper
Manuel Jacob <me@manueljacob.de>
parents: 45039
diff changeset
89 return stream
fd205a9c358a procutil: factor out conditional creation of LineBufferedWrapper
Manuel Jacob <me@manueljacob.de>
parents: 45039
diff changeset
90 return LineBufferedWrapper(stream)
fd205a9c358a procutil: factor out conditional creation of LineBufferedWrapper
Manuel Jacob <me@manueljacob.de>
parents: 45039
diff changeset
91
fd205a9c358a procutil: factor out conditional creation of LineBufferedWrapper
Manuel Jacob <me@manueljacob.de>
parents: 45039
diff changeset
92
45852
b56feaa9b520 chgserver: backport py3 buffered I/O workarounds from procutil
Yuya Nishihara <yuya@tcha.org>
parents: 45786
diff changeset
93 def unwrap_line_buffered(stream):
b56feaa9b520 chgserver: backport py3 buffered I/O workarounds from procutil
Yuya Nishihara <yuya@tcha.org>
parents: 45786
diff changeset
94 if isinstance(stream, LineBufferedWrapper):
b56feaa9b520 chgserver: backport py3 buffered I/O workarounds from procutil
Yuya Nishihara <yuya@tcha.org>
parents: 45786
diff changeset
95 assert not isinstance(stream.orig, LineBufferedWrapper)
b56feaa9b520 chgserver: backport py3 buffered I/O workarounds from procutil
Yuya Nishihara <yuya@tcha.org>
parents: 45786
diff changeset
96 return stream.orig
b56feaa9b520 chgserver: backport py3 buffered I/O workarounds from procutil
Yuya Nishihara <yuya@tcha.org>
parents: 45786
diff changeset
97 return stream
b56feaa9b520 chgserver: backport py3 buffered I/O workarounds from procutil
Yuya Nishihara <yuya@tcha.org>
parents: 45786
diff changeset
98
b56feaa9b520 chgserver: backport py3 buffered I/O workarounds from procutil
Yuya Nishihara <yuya@tcha.org>
parents: 45786
diff changeset
99
45095
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
100 class WriteAllWrapper(object):
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
101 def __init__(self, orig):
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
102 self.orig = orig
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
103
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
104 def __getattr__(self, attr):
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
105 return getattr(self.orig, attr)
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
106
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
107 def write(self, s):
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
108 write1 = self.orig.write
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
109 m = memoryview(s)
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
110 total_to_write = len(s)
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
111 total_written = 0
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
112 while total_written < total_to_write:
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
113 total_written += write1(m[total_written:])
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
114 return total_written
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
115
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
116
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
117 io.IOBase.register(WriteAllWrapper)
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
118
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
119
45103
a5fa2761a6cd procutil: make _make_write_all() function private
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
120 def _make_write_all(stream):
45095
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
121 assert pycompat.ispy3
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
122 if isinstance(stream, WriteAllWrapper):
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
123 return stream
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
124 if isinstance(stream, io.BufferedIOBase):
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
125 # The io.BufferedIOBase.write() contract guarantees that all data is
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
126 # written.
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
127 return stream
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
128 # In general, the write() method of streams is free to write only part of
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
129 # the data.
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
130 return WriteAllWrapper(stream)
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
131
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45094
diff changeset
132
45056
9694895749ad pycompat: remove pycompat.{stdin,stdout,stderr}
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
133 if pycompat.ispy3:
46175
a04c03b0678e procutil: assign pseudo file object if sys.stdout/stderr is missing
Yuya Nishihara <yuya@tcha.org>
parents: 46174
diff changeset
134 # Python 3 implements its own I/O streams. Unlike stdio of C library,
a04c03b0678e procutil: assign pseudo file object if sys.stdout/stderr is missing
Yuya Nishihara <yuya@tcha.org>
parents: 46174
diff changeset
135 # sys.stdin/stdout/stderr may be None if underlying fd is closed.
a04c03b0678e procutil: assign pseudo file object if sys.stdout/stderr is missing
Yuya Nishihara <yuya@tcha.org>
parents: 46174
diff changeset
136
45056
9694895749ad pycompat: remove pycompat.{stdin,stdout,stderr}
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
137 # TODO: .buffer might not exist if std streams were replaced; we'll need
9694895749ad pycompat: remove pycompat.{stdin,stdout,stderr}
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
138 # a silly wrapper to make a bytes stream backed by a unicode one.
46083
81c1f5d1801f procutils: don't try to get `.buffer` if sys.stdin is None
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46030
diff changeset
139
46175
a04c03b0678e procutil: assign pseudo file object if sys.stdout/stderr is missing
Yuya Nishihara <yuya@tcha.org>
parents: 46174
diff changeset
140 if sys.stdin is None:
a04c03b0678e procutil: assign pseudo file object if sys.stdout/stderr is missing
Yuya Nishihara <yuya@tcha.org>
parents: 46174
diff changeset
141 stdin = BadFile()
a04c03b0678e procutil: assign pseudo file object if sys.stdout/stderr is missing
Yuya Nishihara <yuya@tcha.org>
parents: 46174
diff changeset
142 else:
46102
7ce24d3761e8 procutil: don't assign stdin to None, use os.devnull instead
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46083
diff changeset
143 stdin = sys.stdin.buffer
46175
a04c03b0678e procutil: assign pseudo file object if sys.stdout/stderr is missing
Yuya Nishihara <yuya@tcha.org>
parents: 46174
diff changeset
144 if sys.stdout is None:
a04c03b0678e procutil: assign pseudo file object if sys.stdout/stderr is missing
Yuya Nishihara <yuya@tcha.org>
parents: 46174
diff changeset
145 stdout = BadFile()
46102
7ce24d3761e8 procutil: don't assign stdin to None, use os.devnull instead
Pulkit Goyal <7895pulkit@gmail.com>
parents: 46083
diff changeset
146 else:
46175
a04c03b0678e procutil: assign pseudo file object if sys.stdout/stderr is missing
Yuya Nishihara <yuya@tcha.org>
parents: 46174
diff changeset
147 stdout = _make_write_all(sys.stdout.buffer)
a04c03b0678e procutil: assign pseudo file object if sys.stdout/stderr is missing
Yuya Nishihara <yuya@tcha.org>
parents: 46174
diff changeset
148 if sys.stderr is None:
a04c03b0678e procutil: assign pseudo file object if sys.stdout/stderr is missing
Yuya Nishihara <yuya@tcha.org>
parents: 46174
diff changeset
149 stderr = BadFile()
a04c03b0678e procutil: assign pseudo file object if sys.stdout/stderr is missing
Yuya Nishihara <yuya@tcha.org>
parents: 46174
diff changeset
150 else:
a04c03b0678e procutil: assign pseudo file object if sys.stdout/stderr is missing
Yuya Nishihara <yuya@tcha.org>
parents: 46174
diff changeset
151 stderr = _make_write_all(sys.stderr.buffer)
a04c03b0678e procutil: assign pseudo file object if sys.stdout/stderr is missing
Yuya Nishihara <yuya@tcha.org>
parents: 46174
diff changeset
152
45148
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45103
diff changeset
153 if pycompat.iswindows:
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45103
diff changeset
154 # Work around Windows bugs.
46784
65f437c240f2 typing: disable a few errors when accessing Windows specific attributes
Matt Harbison <matt_harbison@yahoo.com>
parents: 46459
diff changeset
155 stdout = platform.winstdout(stdout) # pytype: disable=module-attr
65f437c240f2 typing: disable a few errors when accessing Windows specific attributes
Matt Harbison <matt_harbison@yahoo.com>
parents: 46459
diff changeset
156 stderr = platform.winstdout(stderr) # pytype: disable=module-attr
45093
63196198dbf0 procutil: distribute code for stdout
Manuel Jacob <me@manueljacob.de>
parents: 45082
diff changeset
157 if isatty(stdout):
63196198dbf0 procutil: distribute code for stdout
Manuel Jacob <me@manueljacob.de>
parents: 45082
diff changeset
158 # The standard library doesn't offer line-buffered binary streams.
63196198dbf0 procutil: distribute code for stdout
Manuel Jacob <me@manueljacob.de>
parents: 45082
diff changeset
159 stdout = make_line_buffered(stdout)
45056
9694895749ad pycompat: remove pycompat.{stdin,stdout,stderr}
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
160 else:
45093
63196198dbf0 procutil: distribute code for stdout
Manuel Jacob <me@manueljacob.de>
parents: 45082
diff changeset
161 # Python 2 uses the I/O streams provided by the C library.
45056
9694895749ad pycompat: remove pycompat.{stdin,stdout,stderr}
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
162 stdin = sys.stdin
9694895749ad pycompat: remove pycompat.{stdin,stdout,stderr}
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
163 stdout = sys.stdout
45148
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45103
diff changeset
164 stderr = sys.stderr
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45103
diff changeset
165 if pycompat.iswindows:
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45103
diff changeset
166 # Work around Windows bugs.
46784
65f437c240f2 typing: disable a few errors when accessing Windows specific attributes
Matt Harbison <matt_harbison@yahoo.com>
parents: 46459
diff changeset
167 stdout = platform.winstdout(stdout) # pytype: disable=module-attr
65f437c240f2 typing: disable a few errors when accessing Windows specific attributes
Matt Harbison <matt_harbison@yahoo.com>
parents: 46459
diff changeset
168 stderr = platform.winstdout(stderr) # pytype: disable=module-attr
45093
63196198dbf0 procutil: distribute code for stdout
Manuel Jacob <me@manueljacob.de>
parents: 45082
diff changeset
169 if isatty(stdout):
63196198dbf0 procutil: distribute code for stdout
Manuel Jacob <me@manueljacob.de>
parents: 45082
diff changeset
170 if pycompat.iswindows:
63196198dbf0 procutil: distribute code for stdout
Manuel Jacob <me@manueljacob.de>
parents: 45082
diff changeset
171 # The Windows C runtime library doesn't support line buffering.
63196198dbf0 procutil: distribute code for stdout
Manuel Jacob <me@manueljacob.de>
parents: 45082
diff changeset
172 stdout = make_line_buffered(stdout)
63196198dbf0 procutil: distribute code for stdout
Manuel Jacob <me@manueljacob.de>
parents: 45082
diff changeset
173 else:
63196198dbf0 procutil: distribute code for stdout
Manuel Jacob <me@manueljacob.de>
parents: 45082
diff changeset
174 # glibc determines buffering on first write to stdout - if we
63196198dbf0 procutil: distribute code for stdout
Manuel Jacob <me@manueljacob.de>
parents: 45082
diff changeset
175 # replace a TTY destined stdout with a pipe destined stdout (e.g.
63196198dbf0 procutil: distribute code for stdout
Manuel Jacob <me@manueljacob.de>
parents: 45082
diff changeset
176 # pager), we want line buffering.
63196198dbf0 procutil: distribute code for stdout
Manuel Jacob <me@manueljacob.de>
parents: 45082
diff changeset
177 stdout = os.fdopen(stdout.fileno(), 'wb', 1)
30876
3a4c0905f357 util: always force line buffered stdout when stdout is a tty (BC)
Simon Farnsworth <simonfar@fb.com>
parents: 30854
diff changeset
178
14926
4e7e63fc685a util: eliminate wildcard imports
Adrian Buehlmann <adrian@cadifra.com>
parents: 14918
diff changeset
179
4e7e63fc685a util: eliminate wildcard imports
Adrian Buehlmann <adrian@cadifra.com>
parents: 14918
diff changeset
180 findexe = platform.findexe
37115
49d6ba67c93f util: mark platform-specific gethgcmd() as private
Yuya Nishihara <yuya@tcha.org>
parents: 37099
diff changeset
181 _gethgcmd = platform.gethgcmd
14926
4e7e63fc685a util: eliminate wildcard imports
Adrian Buehlmann <adrian@cadifra.com>
parents: 14918
diff changeset
182 getuser = platform.getuser
28027
14033c5dd261 util: enable getpid to be replaced
timeless <timeless@mozdev.org>
parents: 27785
diff changeset
183 getpid = os.getpid
14926
4e7e63fc685a util: eliminate wildcard imports
Adrian Buehlmann <adrian@cadifra.com>
parents: 14918
diff changeset
184 hidewindow = platform.hidewindow
22245
234e4c24b980 platform: implement readpipe()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 21914
diff changeset
185 readpipe = platform.readpipe
14926
4e7e63fc685a util: eliminate wildcard imports
Adrian Buehlmann <adrian@cadifra.com>
parents: 14918
diff changeset
186 setbinary = platform.setbinary
4e7e63fc685a util: eliminate wildcard imports
Adrian Buehlmann <adrian@cadifra.com>
parents: 14918
diff changeset
187 setsignalhandler = platform.setsignalhandler
4e7e63fc685a util: eliminate wildcard imports
Adrian Buehlmann <adrian@cadifra.com>
parents: 14918
diff changeset
188 shellquote = platform.shellquote
36415
0cb09c322647 util: factor out shellsplit() function
Yuya Nishihara <yuya@tcha.org>
parents: 36362
diff changeset
189 shellsplit = platform.shellsplit
14926
4e7e63fc685a util: eliminate wildcard imports
Adrian Buehlmann <adrian@cadifra.com>
parents: 14918
diff changeset
190 spawndetached = platform.spawndetached
4e7e63fc685a util: eliminate wildcard imports
Adrian Buehlmann <adrian@cadifra.com>
parents: 14918
diff changeset
191 sshargs = platform.sshargs
4e7e63fc685a util: eliminate wildcard imports
Adrian Buehlmann <adrian@cadifra.com>
parents: 14918
diff changeset
192 testpid = platform.testpid
14912
ec46a7da9f2c util: move windows and posix wildcard imports to begin of file
Adrian Buehlmann <adrian@cadifra.com>
parents: 14911
diff changeset
193
32208
d74b0cff94a9 osutil: proxy through util (and platform) modules (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32201
diff changeset
194 try:
d74b0cff94a9 osutil: proxy through util (and platform) modules (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32201
diff changeset
195 setprocname = osutil.setprocname
d74b0cff94a9 osutil: proxy through util (and platform) modules (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32201
diff changeset
196 except AttributeError:
d74b0cff94a9 osutil: proxy through util (and platform) modules (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32201
diff changeset
197 pass
35460
8652ab4046e4 osutil: add a function to unblock signals
Jun Wu <quark@fb.com>
parents: 35145
diff changeset
198 try:
8652ab4046e4 osutil: add a function to unblock signals
Jun Wu <quark@fb.com>
parents: 35145
diff changeset
199 unblocksignal = osutil.unblocksignal
8652ab4046e4 osutil: add a function to unblock signals
Jun Wu <quark@fb.com>
parents: 35145
diff changeset
200 except AttributeError:
8652ab4046e4 osutil: add a function to unblock signals
Jun Wu <quark@fb.com>
parents: 35145
diff changeset
201 pass
32208
d74b0cff94a9 osutil: proxy through util (and platform) modules (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32201
diff changeset
202
34646
238abf65a8ad codemod: use pycompat.isposix
Jun Wu <quark@fb.com>
parents: 34645
diff changeset
203 closefds = pycompat.isposix
10197
29e3c4a7699b subrepo: normalize svn output line-endings
Patrick Mezard <pmezard@gmail.com>
parents: 9996
diff changeset
204
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
205
37460
a6c6b7beb025 procutil: unify platform.explainexit()
Yuya Nishihara <yuya@tcha.org>
parents: 37459
diff changeset
206 def explainexit(code):
37463
bbd240f81ac5 procutil: make explainexit() simply return a message (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37462
diff changeset
207 """return a message describing a subprocess status
37460
a6c6b7beb025 procutil: unify platform.explainexit()
Yuya Nishihara <yuya@tcha.org>
parents: 37459
diff changeset
208 (codes from kill are negative - not os.system/wait encoding)"""
a6c6b7beb025 procutil: unify platform.explainexit()
Yuya Nishihara <yuya@tcha.org>
parents: 37459
diff changeset
209 if code >= 0:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
210 return _(b"exited with status %d") % code
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
211 return _(b"killed by signal %d") % -code
37460
a6c6b7beb025 procutil: unify platform.explainexit()
Yuya Nishihara <yuya@tcha.org>
parents: 37459
diff changeset
212
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
213
37459
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
214 class _pfile(object):
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
215 """File-like wrapper for a stream opened by subprocess.Popen()"""
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
216
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
217 def __init__(self, proc, fp):
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
218 self._proc = proc
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
219 self._fp = fp
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
220
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
221 def close(self):
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
222 # unlike os.popen(), this returns an integer in subprocess coding
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
223 self._fp.close()
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
224 return self._proc.wait()
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
225
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
226 def __iter__(self):
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
227 return iter(self._fp)
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
228
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
229 def __getattr__(self, attr):
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
230 return getattr(self._fp, attr)
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
231
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
232 def __enter__(self):
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
233 return self
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
234
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
235 def __exit__(self, exc_type, exc_value, exc_tb):
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
236 self.close()
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
237
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
238
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
239 def popen(cmd, mode=b'rb', bufsize=-1):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
240 if mode == b'rb':
37459
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
241 return _popenreader(cmd, bufsize)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
242 elif mode == b'wb':
37459
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
243 return _popenwriter(cmd, bufsize)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
244 raise error.ProgrammingError(b'unsupported mode: %r' % mode)
37459
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
245
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
246
37459
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
247 def _popenreader(cmd, bufsize):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
248 p = subprocess.Popen(
44867
8e8fd938ca07 cleanup: eliminate procutil.quotecommand()
Manuel Jacob <me@manueljacob.de>
parents: 44812
diff changeset
249 tonativestr(cmd),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
250 shell=True,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
251 bufsize=bufsize,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
252 close_fds=closefds,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
253 stdout=subprocess.PIPE,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
254 )
37459
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
255 return _pfile(p, p.stdout)
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
256
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
257
37459
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
258 def _popenwriter(cmd, bufsize):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
259 p = subprocess.Popen(
44867
8e8fd938ca07 cleanup: eliminate procutil.quotecommand()
Manuel Jacob <me@manueljacob.de>
parents: 44812
diff changeset
260 tonativestr(cmd),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
261 shell=True,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
262 bufsize=bufsize,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
263 close_fds=closefds,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
264 stdin=subprocess.PIPE,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
265 )
37459
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
266 return _pfile(p, p.stdin)
90c5ca718781 procutil: rewrite popen() as a subprocess.Popen wrapper (issue4746) (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37220
diff changeset
267
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
268
37464
632b92899203 procutil: drop unused 'newlines' option from popen*() (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37463
diff changeset
269 def popen2(cmd, env=None):
9089
8ec39725d966 util: remove unused bufsize argument
Martin Geisler <mg@lazybytes.net>
parents: 9084
diff changeset
270 # Setting bufsize to -1 lets the system decide the buffer size.
8ec39725d966 util: remove unused bufsize argument
Martin Geisler <mg@lazybytes.net>
parents: 9084
diff changeset
271 # The default for bufsize is 0, meaning unbuffered. This leads to
8ec39725d966 util: remove unused bufsize argument
Martin Geisler <mg@lazybytes.net>
parents: 9084
diff changeset
272 # poor performance on Mac OS X: http://bugs.python.org/issue4194
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
273 p = subprocess.Popen(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
274 tonativestr(cmd),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
275 shell=True,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
276 bufsize=-1,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
277 close_fds=closefds,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
278 stdin=subprocess.PIPE,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
279 stdout=subprocess.PIPE,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
280 env=tonativeenv(env),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
281 )
8280
0b02d98d44d0 util: always use subprocess
Martin Geisler <mg@lazybytes.net>
parents: 8257
diff changeset
282 return p.stdin, p.stdout
10197
29e3c4a7699b subrepo: normalize svn output line-endings
Patrick Mezard <pmezard@gmail.com>
parents: 9996
diff changeset
283
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
284
37464
632b92899203 procutil: drop unused 'newlines' option from popen*() (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37463
diff changeset
285 def popen3(cmd, env=None):
632b92899203 procutil: drop unused 'newlines' option from popen*() (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37463
diff changeset
286 stdin, stdout, stderr, p = popen4(cmd, env)
18759
9baf4330d88f sshpeer: store subprocess so it cleans up correctly
Durham Goode <durham@fb.com>
parents: 18736
diff changeset
287 return stdin, stdout, stderr
9baf4330d88f sshpeer: store subprocess so it cleans up correctly
Durham Goode <durham@fb.com>
parents: 18736
diff changeset
288
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
289
37464
632b92899203 procutil: drop unused 'newlines' option from popen*() (API)
Yuya Nishihara <yuya@tcha.org>
parents: 37463
diff changeset
290 def popen4(cmd, env=None, bufsize=-1):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
291 p = subprocess.Popen(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
292 tonativestr(cmd),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
293 shell=True,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
294 bufsize=bufsize,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
295 close_fds=closefds,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
296 stdin=subprocess.PIPE,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
297 stdout=subprocess.PIPE,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
298 stderr=subprocess.PIPE,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
299 env=tonativeenv(env),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
300 )
18759
9baf4330d88f sshpeer: store subprocess so it cleans up correctly
Durham Goode <durham@fb.com>
parents: 18736
diff changeset
301 return p.stdin, p.stdout, p.stderr, p
7106
4674706b5b95 python2.6: use subprocess if available
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6884
diff changeset
302
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
303
1293
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
304 def pipefilter(s, cmd):
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
305 '''filter string S through command CMD, returning its output'''
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
306 p = subprocess.Popen(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
307 tonativestr(cmd),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
308 shell=True,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
309 close_fds=closefds,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
310 stdin=subprocess.PIPE,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
311 stdout=subprocess.PIPE,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
312 )
8302
d2ad8c066676 util: simplify pipefilter and avoid subprocess race
Martin Geisler <mg@lazybytes.net>
parents: 8299
diff changeset
313 pout, perr = p.communicate(s)
d2ad8c066676 util: simplify pipefilter and avoid subprocess race
Martin Geisler <mg@lazybytes.net>
parents: 8299
diff changeset
314 return pout
419
28511fc21073 [PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff changeset
315
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
316
1293
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
317 def tempfilter(s, cmd):
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45852
diff changeset
318 """filter string S through a pair of temporary files with CMD.
1293
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
319 CMD is used as a template to create the real command to be run,
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
320 with the strings INFILE and OUTFILE replaced by the real names of
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45852
diff changeset
321 the temporary files generated."""
1293
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
322 inname, outname = None, None
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
323 try:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
324 infd, inname = pycompat.mkstemp(prefix=b'hg-filter-in-')
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43503
diff changeset
325 fp = os.fdopen(infd, 'wb')
1293
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
326 fp.write(s)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
327 fp.close()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
328 outfd, outname = pycompat.mkstemp(prefix=b'hg-filter-out-')
1293
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
329 os.close(outfd)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
330 cmd = cmd.replace(b'INFILE', inname)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
331 cmd = cmd.replace(b'OUTFILE', outname)
37461
538353b80676 procutil: fix error message of tempfile filter
Yuya Nishihara <yuya@tcha.org>
parents: 37460
diff changeset
332 code = system(cmd)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
333 if pycompat.sysplatform == b'OpenVMS' and code & 1:
4720
72fb6f10fac1 OpenVMS patches
Jean-Francois PIERONNE <jf.pieronne@laposte.net>
parents: 4708
diff changeset
334 code = 0
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
335 if code:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
336 raise error.Abort(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
337 _(b"command '%s' failed: %s") % (cmd, explainexit(code))
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
338 )
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
339 with open(outname, b'rb') as fp:
37117
e7b517809ebc util: stop using readfile() in tempfilter()
Yuya Nishihara <yuya@tcha.org>
parents: 37116
diff changeset
340 return fp.read()
1293
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
341 finally:
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
342 try:
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
343 if inname:
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
344 os.unlink(inname)
14004
97ed99d1f419 eliminate various naked except clauses
Idan Kamara <idankk86@gmail.com>
parents: 13985
diff changeset
345 except OSError:
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
346 pass
1293
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
347 try:
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
348 if outname:
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
349 os.unlink(outname)
14004
97ed99d1f419 eliminate various naked except clauses
Idan Kamara <idankk86@gmail.com>
parents: 13985
diff changeset
350 except OSError:
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10264
diff changeset
351 pass
1293
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
352
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
353
37116
7ccc9b8aca4c util: mark filtertable as private constant
Yuya Nishihara <yuya@tcha.org>
parents: 37115
diff changeset
354 _filtertable = {
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
355 b'tempfile:': tempfilter,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
356 b'pipe:': pipefilter,
37116
7ccc9b8aca4c util: mark filtertable as private constant
Yuya Nishihara <yuya@tcha.org>
parents: 37115
diff changeset
357 }
1293
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
358
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
359
1293
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
360 def filter(s, cmd):
43787
be8552f25cab cleanup: fix docstring formatting
Matt Harbison <matt_harbison@yahoo.com>
parents: 43671
diff changeset
361 """filter a string through a command that transforms its input to its
be8552f25cab cleanup: fix docstring formatting
Matt Harbison <matt_harbison@yahoo.com>
parents: 43671
diff changeset
362 output"""
43106
d783f945a701 py3: finish porting iteritems() to pycompat and remove source transformer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43096
diff changeset
363 for name, fn in pycompat.iteritems(_filtertable):
1293
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
364 if cmd.startswith(name):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
365 return fn(s, cmd[len(name) :].lstrip())
1293
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
366 return pipefilter(s, cmd)
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
367
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
368
22632
db15bb2d6323 util: move _hgexecutable a few lines, closer to where it is used
Mads Kiilerich <madski@unity3d.com>
parents: 22245
diff changeset
369 _hgexecutable = None
db15bb2d6323 util: move _hgexecutable a few lines, closer to where it is used
Mads Kiilerich <madski@unity3d.com>
parents: 22245
diff changeset
370
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
371
5062
3d35c8cb5eb4 Simplify/correct finding the hg executable (fixes issue644)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4832
diff changeset
372 def hgexecutable():
3d35c8cb5eb4 Simplify/correct finding the hg executable (fixes issue644)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4832
diff changeset
373 """return location of the 'hg' executable.
3d35c8cb5eb4 Simplify/correct finding the hg executable (fixes issue644)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4832
diff changeset
374
3d35c8cb5eb4 Simplify/correct finding the hg executable (fixes issue644)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4832
diff changeset
375 Defaults to $HG or 'hg' in the search path.
3d35c8cb5eb4 Simplify/correct finding the hg executable (fixes issue644)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4832
diff changeset
376 """
3d35c8cb5eb4 Simplify/correct finding the hg executable (fixes issue644)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4832
diff changeset
377 if _hgexecutable is None:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
378 hg = encoding.environ.get(b'HG')
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43503
diff changeset
379 mainmod = sys.modules['__main__']
6500
a3175cd7dbec Tidy code, fix typo
Bryan O'Sullivan <bos@serpentine.com>
parents: 6499
diff changeset
380 if hg:
14229
85fd8402cbc4 rename util.set_hgexecutable to _sethgexecutable
Adrian Buehlmann <adrian@cadifra.com>
parents: 14228
diff changeset
381 _sethgexecutable(hg)
43671
664e24207728 procutil: move mainfrozen() to new resourceutil.py
Martin von Zweigbergk <martinvonz@google.com>
parents: 43657
diff changeset
382 elif resourceutil.mainfrozen():
43657
38387f9e4d22 py3: use native string for 'macosx_app'
Martin von Zweigbergk <martinvonz@google.com>
parents: 43656
diff changeset
383 if getattr(sys, 'frozen', None) == 'macosx_app':
27765
f1fb93eebb1d util: adjust hgexecutable() to handle frozen Mercurial on OS X
Matt Harbison <matt_harbison@yahoo.com>
parents: 27764
diff changeset
384 # Env variable set by py2app
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
385 _sethgexecutable(encoding.environ[b'EXECUTABLEPATH'])
27765
f1fb93eebb1d util: adjust hgexecutable() to handle frozen Mercurial on OS X
Matt Harbison <matt_harbison@yahoo.com>
parents: 27764
diff changeset
386 else:
30669
10b17ed9b591 py3: replace sys.executable with pycompat.sysexecutable
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30642
diff changeset
387 _sethgexecutable(pycompat.sysexecutable)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
388 elif (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
389 not pycompat.iswindows
43656
47d983f0af65 py3: drop an unnecessary fsencode() before comparing with constant
Martin von Zweigbergk <martinvonz@google.com>
parents: 43655
diff changeset
390 and os.path.basename(getattr(mainmod, '__file__', '')) == 'hg'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
391 ):
31074
2912b06905dc py3: use pycompat.fsencode() to convert __file__ to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30988
diff changeset
392 _sethgexecutable(pycompat.fsencode(mainmod.__file__))
6499
479847ccabe0 Added hgexecutable support for py2exe/frozen scripts
"Paul Moore <p.f.moore@gmail.com>"
parents: 5659
diff changeset
393 else:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
394 _sethgexecutable(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
395 findexe(b'hg') or os.path.basename(pycompat.sysargv[0])
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
396 )
5062
3d35c8cb5eb4 Simplify/correct finding the hg executable (fixes issue644)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4832
diff changeset
397 return _hgexecutable
4686
849f011dbf79 Remember path to 'hg' executable and pass to external tools and hooks as $HG.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4673
diff changeset
398
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
399
14229
85fd8402cbc4 rename util.set_hgexecutable to _sethgexecutable
Adrian Buehlmann <adrian@cadifra.com>
parents: 14228
diff changeset
400 def _sethgexecutable(path):
5062
3d35c8cb5eb4 Simplify/correct finding the hg executable (fixes issue644)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4832
diff changeset
401 """set location of the 'hg' executable"""
4686
849f011dbf79 Remember path to 'hg' executable and pass to external tools and hooks as $HG.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4673
diff changeset
402 global _hgexecutable
5062
3d35c8cb5eb4 Simplify/correct finding the hg executable (fixes issue644)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4832
diff changeset
403 _hgexecutable = path
4686
849f011dbf79 Remember path to 'hg' executable and pass to external tools and hooks as $HG.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4673
diff changeset
404
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
405
36793
eca1051e6c22 util: add public isstdin/isstdout() functions
Yuya Nishihara <yuya@tcha.org>
parents: 36791
diff changeset
406 def _testfileno(f, stdf):
26450
1138e1d05207 util.system: compare fileno to see if it needs stdout redirection
Yuya Nishihara <yuya@tcha.org>
parents: 26392
diff changeset
407 fileno = getattr(f, 'fileno', None)
36432
1ca4e86c7265 util: handle fileno() on Python 3 throwing io.UnsupportedOperation
Augie Fackler <augie@google.com>
parents: 36422
diff changeset
408 try:
36793
eca1051e6c22 util: add public isstdin/isstdout() functions
Yuya Nishihara <yuya@tcha.org>
parents: 36791
diff changeset
409 return fileno and fileno() == stdf.fileno()
36432
1ca4e86c7265 util: handle fileno() on Python 3 throwing io.UnsupportedOperation
Augie Fackler <augie@google.com>
parents: 36422
diff changeset
410 except io.UnsupportedOperation:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
411 return False # fileno() raised UnsupportedOperation
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
412
26450
1138e1d05207 util.system: compare fileno to see if it needs stdout redirection
Yuya Nishihara <yuya@tcha.org>
parents: 26392
diff changeset
413
36793
eca1051e6c22 util: add public isstdin/isstdout() functions
Yuya Nishihara <yuya@tcha.org>
parents: 36791
diff changeset
414 def isstdin(f):
eca1051e6c22 util: add public isstdin/isstdout() functions
Yuya Nishihara <yuya@tcha.org>
parents: 36791
diff changeset
415 return _testfileno(f, sys.__stdin__)
eca1051e6c22 util: add public isstdin/isstdout() functions
Yuya Nishihara <yuya@tcha.org>
parents: 36791
diff changeset
416
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
417
36793
eca1051e6c22 util: add public isstdin/isstdout() functions
Yuya Nishihara <yuya@tcha.org>
parents: 36791
diff changeset
418 def isstdout(f):
eca1051e6c22 util: add public isstdin/isstdout() functions
Yuya Nishihara <yuya@tcha.org>
parents: 36791
diff changeset
419 return _testfileno(f, sys.__stdout__)
eca1051e6c22 util: add public isstdin/isstdout() functions
Yuya Nishihara <yuya@tcha.org>
parents: 36791
diff changeset
420
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
421
37123
0216232f21ab procutil: move protectio/restoreio from commandserver
Yuya Nishihara <yuya@tcha.org>
parents: 37118
diff changeset
422 def protectstdio(uin, uout):
37220
7f78de1c93aa procutil: redirect ui.fout to stderr while stdio is protected
Yuya Nishihara <yuya@tcha.org>
parents: 37219
diff changeset
423 """Duplicate streams and redirect original if (uin, uout) are stdio
7f78de1c93aa procutil: redirect ui.fout to stderr while stdio is protected
Yuya Nishihara <yuya@tcha.org>
parents: 37219
diff changeset
424
7f78de1c93aa procutil: redirect ui.fout to stderr while stdio is protected
Yuya Nishihara <yuya@tcha.org>
parents: 37219
diff changeset
425 If uin is stdin, it's redirected to /dev/null. If uout is stdout, it's
7f78de1c93aa procutil: redirect ui.fout to stderr while stdio is protected
Yuya Nishihara <yuya@tcha.org>
parents: 37219
diff changeset
426 redirected to stderr so the output is still readable.
37123
0216232f21ab procutil: move protectio/restoreio from commandserver
Yuya Nishihara <yuya@tcha.org>
parents: 37118
diff changeset
427
0216232f21ab procutil: move protectio/restoreio from commandserver
Yuya Nishihara <yuya@tcha.org>
parents: 37118
diff changeset
428 Returns (fin, fout) which point to the original (uin, uout) fds, but
0216232f21ab procutil: move protectio/restoreio from commandserver
Yuya Nishihara <yuya@tcha.org>
parents: 37118
diff changeset
429 may be copy of (uin, uout). The returned streams can be considered
0216232f21ab procutil: move protectio/restoreio from commandserver
Yuya Nishihara <yuya@tcha.org>
parents: 37118
diff changeset
430 "owned" in that print(), exec(), etc. never reach to them.
0216232f21ab procutil: move protectio/restoreio from commandserver
Yuya Nishihara <yuya@tcha.org>
parents: 37118
diff changeset
431 """
0216232f21ab procutil: move protectio/restoreio from commandserver
Yuya Nishihara <yuya@tcha.org>
parents: 37118
diff changeset
432 uout.flush()
37219
ac71cbad5da3 procutil: unroll uin/uout loop in protectstdio()
Yuya Nishihara <yuya@tcha.org>
parents: 37124
diff changeset
433 fin, fout = uin, uout
39807
e5724be689b3 procutil: compare fd number to see if stdio protection is needed (issue5992)
Yuya Nishihara <yuya@tcha.org>
parents: 38526
diff changeset
434 if _testfileno(uin, stdin):
37219
ac71cbad5da3 procutil: unroll uin/uout loop in protectstdio()
Yuya Nishihara <yuya@tcha.org>
parents: 37124
diff changeset
435 newfd = os.dup(uin.fileno())
37220
7f78de1c93aa procutil: redirect ui.fout to stderr while stdio is protected
Yuya Nishihara <yuya@tcha.org>
parents: 37219
diff changeset
436 nullfd = os.open(os.devnull, os.O_RDONLY)
37219
ac71cbad5da3 procutil: unroll uin/uout loop in protectstdio()
Yuya Nishihara <yuya@tcha.org>
parents: 37124
diff changeset
437 os.dup2(nullfd, uin.fileno())
37220
7f78de1c93aa procutil: redirect ui.fout to stderr while stdio is protected
Yuya Nishihara <yuya@tcha.org>
parents: 37219
diff changeset
438 os.close(nullfd)
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43503
diff changeset
439 fin = os.fdopen(newfd, 'rb')
39807
e5724be689b3 procutil: compare fd number to see if stdio protection is needed (issue5992)
Yuya Nishihara <yuya@tcha.org>
parents: 38526
diff changeset
440 if _testfileno(uout, stdout):
37219
ac71cbad5da3 procutil: unroll uin/uout loop in protectstdio()
Yuya Nishihara <yuya@tcha.org>
parents: 37124
diff changeset
441 newfd = os.dup(uout.fileno())
37220
7f78de1c93aa procutil: redirect ui.fout to stderr while stdio is protected
Yuya Nishihara <yuya@tcha.org>
parents: 37219
diff changeset
442 os.dup2(stderr.fileno(), uout.fileno())
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43503
diff changeset
443 fout = os.fdopen(newfd, 'wb')
37219
ac71cbad5da3 procutil: unroll uin/uout loop in protectstdio()
Yuya Nishihara <yuya@tcha.org>
parents: 37124
diff changeset
444 return fin, fout
37123
0216232f21ab procutil: move protectio/restoreio from commandserver
Yuya Nishihara <yuya@tcha.org>
parents: 37118
diff changeset
445
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
446
37123
0216232f21ab procutil: move protectio/restoreio from commandserver
Yuya Nishihara <yuya@tcha.org>
parents: 37118
diff changeset
447 def restorestdio(uin, uout, fin, fout):
0216232f21ab procutil: move protectio/restoreio from commandserver
Yuya Nishihara <yuya@tcha.org>
parents: 37118
diff changeset
448 """Restore (uin, uout) streams from possibly duplicated (fin, fout)"""
0216232f21ab procutil: move protectio/restoreio from commandserver
Yuya Nishihara <yuya@tcha.org>
parents: 37118
diff changeset
449 uout.flush()
0216232f21ab procutil: move protectio/restoreio from commandserver
Yuya Nishihara <yuya@tcha.org>
parents: 37118
diff changeset
450 for f, uif in [(fin, uin), (fout, uout)]:
0216232f21ab procutil: move protectio/restoreio from commandserver
Yuya Nishihara <yuya@tcha.org>
parents: 37118
diff changeset
451 if f is not uif:
0216232f21ab procutil: move protectio/restoreio from commandserver
Yuya Nishihara <yuya@tcha.org>
parents: 37118
diff changeset
452 os.dup2(f.fileno(), uif.fileno())
0216232f21ab procutil: move protectio/restoreio from commandserver
Yuya Nishihara <yuya@tcha.org>
parents: 37118
diff changeset
453 f.close()
0216232f21ab procutil: move protectio/restoreio from commandserver
Yuya Nishihara <yuya@tcha.org>
parents: 37118
diff changeset
454
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
455
30736
d9e5b0aeeb90 util: extract the logic calculating environment variables
Jun Wu <quark@fb.com>
parents: 30669
diff changeset
456 def shellenviron(environ=None):
d9e5b0aeeb90 util: extract the logic calculating environment variables
Jun Wu <quark@fb.com>
parents: 30669
diff changeset
457 """return environ with optional override, useful for shelling out"""
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
458
30736
d9e5b0aeeb90 util: extract the logic calculating environment variables
Jun Wu <quark@fb.com>
parents: 30669
diff changeset
459 def py2shell(val):
43787
be8552f25cab cleanup: fix docstring formatting
Matt Harbison <matt_harbison@yahoo.com>
parents: 43671
diff changeset
460 """convert python object into string that is useful to shell"""
30736
d9e5b0aeeb90 util: extract the logic calculating environment variables
Jun Wu <quark@fb.com>
parents: 30669
diff changeset
461 if val is None or val is False:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
462 return b'0'
30736
d9e5b0aeeb90 util: extract the logic calculating environment variables
Jun Wu <quark@fb.com>
parents: 30669
diff changeset
463 if val is True:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
464 return b'1'
36418
d26b0bedfaa4 util: use pycompat.bytestr() instead of str()
Augie Fackler <augie@google.com>
parents: 36415
diff changeset
465 return pycompat.bytestr(val)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
466
30736
d9e5b0aeeb90 util: extract the logic calculating environment variables
Jun Wu <quark@fb.com>
parents: 30669
diff changeset
467 env = dict(encoding.environ)
d9e5b0aeeb90 util: extract the logic calculating environment variables
Jun Wu <quark@fb.com>
parents: 30669
diff changeset
468 if environ:
43106
d783f945a701 py3: finish porting iteritems() to pycompat and remove source transformer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43096
diff changeset
469 env.update((k, py2shell(v)) for k, v in pycompat.iteritems(environ))
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
470 env[b'HG'] = hgexecutable()
30736
d9e5b0aeeb90 util: extract the logic calculating environment variables
Jun Wu <quark@fb.com>
parents: 30669
diff changeset
471 return env
d9e5b0aeeb90 util: extract the logic calculating environment variables
Jun Wu <quark@fb.com>
parents: 30669
diff changeset
472
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
473
38491
72286f9e324f procutil: add a shim for translating shell commands to native commands
Matt Harbison <matt_harbison@yahoo.com>
parents: 38454
diff changeset
474 if pycompat.iswindows:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
475
38491
72286f9e324f procutil: add a shim for translating shell commands to native commands
Matt Harbison <matt_harbison@yahoo.com>
parents: 38454
diff changeset
476 def shelltonative(cmd, env):
43478
54f4d094bab1 procutil: suppress pytype warnings around windows-only attributes
Augie Fackler <augie@google.com>
parents: 43165
diff changeset
477 return platform.shelltocmdexe( # pytype: disable=module-attr
54f4d094bab1 procutil: suppress pytype warnings around windows-only attributes
Augie Fackler <augie@google.com>
parents: 43165
diff changeset
478 cmd, shellenviron(env)
54f4d094bab1 procutil: suppress pytype warnings around windows-only attributes
Augie Fackler <augie@google.com>
parents: 43165
diff changeset
479 )
39662
50f46b771921 py3: partially fix pager spawning on Windows
Matt Harbison <matt_harbison@yahoo.com>
parents: 38526
diff changeset
480
50f46b771921 py3: partially fix pager spawning on Windows
Matt Harbison <matt_harbison@yahoo.com>
parents: 38526
diff changeset
481 tonativestr = encoding.strfromlocal
38491
72286f9e324f procutil: add a shim for translating shell commands to native commands
Matt Harbison <matt_harbison@yahoo.com>
parents: 38454
diff changeset
482 else:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
483
38491
72286f9e324f procutil: add a shim for translating shell commands to native commands
Matt Harbison <matt_harbison@yahoo.com>
parents: 38454
diff changeset
484 def shelltonative(cmd, env):
72286f9e324f procutil: add a shim for translating shell commands to native commands
Matt Harbison <matt_harbison@yahoo.com>
parents: 38454
diff changeset
485 return cmd
72286f9e324f procutil: add a shim for translating shell commands to native commands
Matt Harbison <matt_harbison@yahoo.com>
parents: 38454
diff changeset
486
39662
50f46b771921 py3: partially fix pager spawning on Windows
Matt Harbison <matt_harbison@yahoo.com>
parents: 38526
diff changeset
487 tonativestr = pycompat.identity
50f46b771921 py3: partially fix pager spawning on Windows
Matt Harbison <matt_harbison@yahoo.com>
parents: 38526
diff changeset
488
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
489
39662
50f46b771921 py3: partially fix pager spawning on Windows
Matt Harbison <matt_harbison@yahoo.com>
parents: 38526
diff changeset
490 def tonativeenv(env):
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45852
diff changeset
491 """convert the environment from bytes to strings suitable for Popen(), etc."""
39662
50f46b771921 py3: partially fix pager spawning on Windows
Matt Harbison <matt_harbison@yahoo.com>
parents: 38526
diff changeset
492 return pycompat.rapply(tonativestr, env)
50f46b771921 py3: partially fix pager spawning on Windows
Matt Harbison <matt_harbison@yahoo.com>
parents: 38526
diff changeset
493
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
494
31108
3f8f53190d6a chg: deduplicate error handling of ui.system()
Yuya Nishihara <yuya@tcha.org>
parents: 31074
diff changeset
495 def system(cmd, environ=None, cwd=None, out=None):
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45852
diff changeset
496 """enhanced shell command execution.
1882
c0320567931f merge util.esystem and util.system.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1880
diff changeset
497 run with environment maybe modified, maybe in different dir.
508
42a660abaf75 [PATCH] Harden os.system
mpm@selenic.com
parents: 464
diff changeset
498
11469
c37f35d7f2f5 http: deliver hook output to client
Maxim Khitrov <mkhitrov@gmail.com>
parents: 11297
diff changeset
499 if out is specified, it is assumed to be a file-like object that has a
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45852
diff changeset
500 write() method. stdout and stderr will be redirected to out."""
13439
d724a69309e0 util: flush stdout before calling external processes
Mads Kiilerich <mads@kiilerich.com>
parents: 13400
diff changeset
501 try:
30473
39d13b8c101d py3: bulk replace sys.stdin/out/err by util's
Yuya Nishihara <yuya@tcha.org>
parents: 30472
diff changeset
502 stdout.flush()
13439
d724a69309e0 util: flush stdout before calling external processes
Mads Kiilerich <mads@kiilerich.com>
parents: 13400
diff changeset
503 except Exception:
d724a69309e0 util: flush stdout before calling external processes
Mads Kiilerich <mads@kiilerich.com>
parents: 13400
diff changeset
504 pass
32886
19b0fd4b5570 plan9: drop py26 hacks
Matt Harbison <matt_harbison@yahoo.com>
parents: 32816
diff changeset
505 env = shellenviron(environ)
36793
eca1051e6c22 util: add public isstdin/isstdout() functions
Yuya Nishihara <yuya@tcha.org>
parents: 36791
diff changeset
506 if out is None or isstdout(out):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
507 rc = subprocess.call(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
508 tonativestr(cmd),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
509 shell=True,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
510 close_fds=closefds,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
511 env=tonativeenv(env),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
512 cwd=pycompat.rapply(tonativestr, cwd),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
513 )
11469
c37f35d7f2f5 http: deliver hook output to client
Maxim Khitrov <mkhitrov@gmail.com>
parents: 11297
diff changeset
514 else:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
515 proc = subprocess.Popen(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
516 tonativestr(cmd),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
517 shell=True,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
518 close_fds=closefds,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
519 env=tonativeenv(env),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
520 cwd=pycompat.rapply(tonativestr, cwd),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
521 stdout=subprocess.PIPE,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
522 stderr=subprocess.STDOUT,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
523 )
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
524 for line in iter(proc.stdout.readline, b''):
32886
19b0fd4b5570 plan9: drop py26 hacks
Matt Harbison <matt_harbison@yahoo.com>
parents: 32816
diff changeset
525 out.write(line)
19b0fd4b5570 plan9: drop py26 hacks
Matt Harbison <matt_harbison@yahoo.com>
parents: 32816
diff changeset
526 proc.wait()
19b0fd4b5570 plan9: drop py26 hacks
Matt Harbison <matt_harbison@yahoo.com>
parents: 32816
diff changeset
527 rc = proc.returncode
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
528 if pycompat.sysplatform == b'OpenVMS' and rc & 1:
32886
19b0fd4b5570 plan9: drop py26 hacks
Matt Harbison <matt_harbison@yahoo.com>
parents: 32816
diff changeset
529 rc = 0
9517
4368f582c806 util.system: Use subprocess instead of os.system
Mads Kiilerich <mads@kiilerich.com>
parents: 9508
diff changeset
530 return rc
1880
05c7d75be925 fix broken environment save/restore when a hook runs.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
531
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
532
43912
a89381e04c58 procutil: try and avoid angering CoreFoundation on macOS
Augie Fackler <augie@google.com>
parents: 43862
diff changeset
533 _is_gui = None
a89381e04c58 procutil: try and avoid angering CoreFoundation on macOS
Augie Fackler <augie@google.com>
parents: 43862
diff changeset
534
a89381e04c58 procutil: try and avoid angering CoreFoundation on macOS
Augie Fackler <augie@google.com>
parents: 43862
diff changeset
535
a89381e04c58 procutil: try and avoid angering CoreFoundation on macOS
Augie Fackler <augie@google.com>
parents: 43862
diff changeset
536 def _gui():
6007
090b1a665901 filemerge: add config item for GUI tools
Matt Mackall <mpm@selenic.com>
parents: 6006
diff changeset
537 '''Are we running in a GUI?'''
34647
dacfcdd8b94e codemod: use pycompat.isdarwin
Jun Wu <quark@fb.com>
parents: 34646
diff changeset
538 if pycompat.isdarwin:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
539 if b'SSH_CONNECTION' in encoding.environ:
13734
16118b4859a1 util: add Mac-specific check whether we're in a GUI session (issue2553)
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13439
diff changeset
540 # handle SSH access to a box where the user is logged in
16118b4859a1 util: add Mac-specific check whether we're in a GUI session (issue2553)
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13439
diff changeset
541 return False
16118b4859a1 util: add Mac-specific check whether we're in a GUI session (issue2553)
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13439
diff changeset
542 elif getattr(osutil, 'isgui', None):
16118b4859a1 util: add Mac-specific check whether we're in a GUI session (issue2553)
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13439
diff changeset
543 # check if a CoreGraphics session is available
16118b4859a1 util: add Mac-specific check whether we're in a GUI session (issue2553)
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13439
diff changeset
544 return osutil.isgui()
16118b4859a1 util: add Mac-specific check whether we're in a GUI session (issue2553)
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13439
diff changeset
545 else:
16118b4859a1 util: add Mac-specific check whether we're in a GUI session (issue2553)
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13439
diff changeset
546 # pure build; use a safe default
16118b4859a1 util: add Mac-specific check whether we're in a GUI session (issue2553)
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13439
diff changeset
547 return True
16118b4859a1 util: add Mac-specific check whether we're in a GUI session (issue2553)
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13439
diff changeset
548 else:
46459
128a17d8436f procutil: extend gui test to detect wayland session (issue6479)
Yuya Nishihara <yuya@tcha.org>
parents: 46175
diff changeset
549 return (
128a17d8436f procutil: extend gui test to detect wayland session (issue6479)
Yuya Nishihara <yuya@tcha.org>
parents: 46175
diff changeset
550 pycompat.iswindows
128a17d8436f procutil: extend gui test to detect wayland session (issue6479)
Yuya Nishihara <yuya@tcha.org>
parents: 46175
diff changeset
551 or encoding.environ.get(b"DISPLAY")
128a17d8436f procutil: extend gui test to detect wayland session (issue6479)
Yuya Nishihara <yuya@tcha.org>
parents: 46175
diff changeset
552 or encoding.environ.get(b"WAYLAND_DISPLAY")
128a17d8436f procutil: extend gui test to detect wayland session (issue6479)
Yuya Nishihara <yuya@tcha.org>
parents: 46175
diff changeset
553 )
6007
090b1a665901 filemerge: add config item for GUI tools
Matt Mackall <mpm@selenic.com>
parents: 6006
diff changeset
554
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
555
43912
a89381e04c58 procutil: try and avoid angering CoreFoundation on macOS
Augie Fackler <augie@google.com>
parents: 43862
diff changeset
556 def gui():
a89381e04c58 procutil: try and avoid angering CoreFoundation on macOS
Augie Fackler <augie@google.com>
parents: 43862
diff changeset
557 global _is_gui
a89381e04c58 procutil: try and avoid angering CoreFoundation on macOS
Augie Fackler <augie@google.com>
parents: 43862
diff changeset
558 if _is_gui is None:
a89381e04c58 procutil: try and avoid angering CoreFoundation on macOS
Augie Fackler <augie@google.com>
parents: 43862
diff changeset
559 _is_gui = _gui()
a89381e04c58 procutil: try and avoid angering CoreFoundation on macOS
Augie Fackler <augie@google.com>
parents: 43862
diff changeset
560 return _is_gui
a89381e04c58 procutil: try and avoid angering CoreFoundation on macOS
Augie Fackler <augie@google.com>
parents: 43862
diff changeset
561
a89381e04c58 procutil: try and avoid angering CoreFoundation on macOS
Augie Fackler <augie@google.com>
parents: 43862
diff changeset
562
10239
8e4be44a676f Find right hg command for detached process
Patrick Mezard <pmezard@gmail.com>
parents: 10199
diff changeset
563 def hgcmd():
8e4be44a676f Find right hg command for detached process
Patrick Mezard <pmezard@gmail.com>
parents: 10199
diff changeset
564 """Return the command used to execute current hg
8e4be44a676f Find right hg command for detached process
Patrick Mezard <pmezard@gmail.com>
parents: 10199
diff changeset
565
8e4be44a676f Find right hg command for detached process
Patrick Mezard <pmezard@gmail.com>
parents: 10199
diff changeset
566 This is different from hgexecutable() because on Windows we want
8e4be44a676f Find right hg command for detached process
Patrick Mezard <pmezard@gmail.com>
parents: 10199
diff changeset
567 to avoid things opening new shell windows like batch files, so we
8e4be44a676f Find right hg command for detached process
Patrick Mezard <pmezard@gmail.com>
parents: 10199
diff changeset
568 get either the python call or current executable.
8e4be44a676f Find right hg command for detached process
Patrick Mezard <pmezard@gmail.com>
parents: 10199
diff changeset
569 """
43671
664e24207728 procutil: move mainfrozen() to new resourceutil.py
Martin von Zweigbergk <martinvonz@google.com>
parents: 43657
diff changeset
570 if resourceutil.mainfrozen():
43657
38387f9e4d22 py3: use native string for 'macosx_app'
Martin von Zweigbergk <martinvonz@google.com>
parents: 43656
diff changeset
571 if getattr(sys, 'frozen', None) == 'macosx_app':
27766
198f78a52a2f util: adjust hgcmd() to handle frozen Mercurial on OS X
Matt Harbison <matt_harbison@yahoo.com>
parents: 27765
diff changeset
572 # Env variable set by py2app
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
573 return [encoding.environ[b'EXECUTABLEPATH']]
27766
198f78a52a2f util: adjust hgcmd() to handle frozen Mercurial on OS X
Matt Harbison <matt_harbison@yahoo.com>
parents: 27765
diff changeset
574 else:
30669
10b17ed9b591 py3: replace sys.executable with pycompat.sysexecutable
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30642
diff changeset
575 return [pycompat.sysexecutable]
37115
49d6ba67c93f util: mark platform-specific gethgcmd() as private
Yuya Nishihara <yuya@tcha.org>
parents: 37099
diff changeset
576 return _gethgcmd()
10344
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
577
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
578
10344
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
579 def rundetached(args, condfn):
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
580 """Execute the argument list in a detached process.
10422
600142e7a028 util: fix trailing whitespace found by check-code
Augie Fackler <durin42@gmail.com>
parents: 10344
diff changeset
581
10344
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
582 condfn is a callable which is called repeatedly and should return
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
583 True once the child process is known to have started successfully.
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
584 At this point, the child process PID is returned. If the child
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
585 process fails to start or finishes before condfn() evaluates to
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
586 True, return -1.
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
587 """
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
588 # Windows case is easier because the child process is either
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
589 # successfully starting and validating the condition or exiting
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
590 # on failure. We just poll on its PID. On Unix, if the child
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
591 # process fails to start, it will be left in a zombie state until
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
592 # the parent wait on it, which we cannot do since we expect a long
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
593 # running process on success. Instead we listen for SIGCHLD telling
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
594 # us our child process terminated.
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
595 terminated = set()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
596
10344
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
597 def handler(signum, frame):
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
598 terminated.add(os.wait())
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
599
10344
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
600 prevhandler = None
14968
b7dbe957585c util: use safehasattr or getattr instead of hasattr
Augie Fackler <durin42@gmail.com>
parents: 14942
diff changeset
601 SIGCHLD = getattr(signal, 'SIGCHLD', None)
b7dbe957585c util: use safehasattr or getattr instead of hasattr
Augie Fackler <durin42@gmail.com>
parents: 14942
diff changeset
602 if SIGCHLD is not None:
b7dbe957585c util: use safehasattr or getattr instead of hasattr
Augie Fackler <durin42@gmail.com>
parents: 14942
diff changeset
603 prevhandler = signal.signal(SIGCHLD, handler)
10344
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
604 try:
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
605 pid = spawndetached(args)
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
606 while not condfn():
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
607 if (pid in terminated or not testpid(pid)) and not condfn():
10344
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
608 return -1
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
609 time.sleep(0.1)
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
610 return pid
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
611 finally:
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
612 if prevhandler is not None:
9501cde4c034 util: make spawndetached() handle subprocess early terminations
Patrick Mezard <pmezard@gmail.com>
parents: 10282
diff changeset
613 signal.signal(signal.SIGCHLD, prevhandler)
38526
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
614
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
615
38526
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
616 @contextlib.contextmanager
41076
8ecb17b7f432 procutil: correct spelling of uninterruptable -> uninterruptible
Kyle Lippincott <spectral@google.com>
parents: 40712
diff changeset
617 def uninterruptible(warn):
38526
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
618 """Inhibit SIGINT handling on a region of code.
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
619
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
620 Note that if this is called in a non-main thread, it turns into a no-op.
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
621
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
622 Args:
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
623 warn: A callable which takes no arguments, and returns True if the
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
624 previous signal handling should be restored.
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
625 """
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
626
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
627 oldsiginthandler = [signal.getsignal(signal.SIGINT)]
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
628 shouldbail = []
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
629
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
630 def disabledsiginthandler(*args):
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
631 if warn():
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
632 signal.signal(signal.SIGINT, oldsiginthandler[0])
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
633 del oldsiginthandler[0]
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
634 shouldbail.append(True)
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
635
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
636 try:
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
637 try:
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
638 signal.signal(signal.SIGINT, disabledsiginthandler)
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
639 except ValueError:
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
640 # wrong thread, oh well, we tried
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
641 del oldsiginthandler[0]
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
642 yield
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
643 finally:
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
644 if oldsiginthandler:
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
645 signal.signal(signal.SIGINT, oldsiginthandler[0])
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
646 if shouldbail:
313a940d49a3 ui: add an uninterruptable context manager that can block SIGINT
Augie Fackler <augie@google.com>
parents: 38525
diff changeset
647 raise KeyboardInterrupt
40497
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
648
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
649
40497
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
650 if pycompat.iswindows:
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
651 # no fork on Windows, but we can create a detached process
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
652 # https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863.aspx
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
653 # No stdlib constant exists for this value
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
654 DETACHED_PROCESS = 0x00000008
40536
1d3bed7d2923 procutil: import concerns about creationflags on Windows from D1701
Boris Feld <boris.feld@octobus.net>
parents: 40498
diff changeset
655 # Following creation flags might create a console GUI window.
1d3bed7d2923 procutil: import concerns about creationflags on Windows from D1701
Boris Feld <boris.feld@octobus.net>
parents: 40498
diff changeset
656 # Using subprocess.CREATE_NEW_CONSOLE might helps.
1d3bed7d2923 procutil: import concerns about creationflags on Windows from D1701
Boris Feld <boris.feld@octobus.net>
parents: 40498
diff changeset
657 # See https://phab.mercurial-scm.org/D1701 for discussion
43478
54f4d094bab1 procutil: suppress pytype warnings around windows-only attributes
Augie Fackler <augie@google.com>
parents: 43165
diff changeset
658 _creationflags = (
54f4d094bab1 procutil: suppress pytype warnings around windows-only attributes
Augie Fackler <augie@google.com>
parents: 43165
diff changeset
659 DETACHED_PROCESS
54f4d094bab1 procutil: suppress pytype warnings around windows-only attributes
Augie Fackler <augie@google.com>
parents: 43165
diff changeset
660 | subprocess.CREATE_NEW_PROCESS_GROUP # pytype: disable=module-attr
54f4d094bab1 procutil: suppress pytype warnings around windows-only attributes
Augie Fackler <augie@google.com>
parents: 43165
diff changeset
661 )
40497
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
662
42496
ca1014ad3de4 procutil: allow callers of runbgcommand to assume the process starts
Augie Fackler <augie@google.com>
parents: 41832
diff changeset
663 def runbgcommand(
43848
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
664 script,
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
665 env,
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
666 shell=False,
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
667 stdout=None,
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
668 stderr=None,
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
669 ensurestart=True,
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
670 record_wait=None,
45786
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
671 stdin_bytes=None,
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
672 ):
40497
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
673 '''Spawn a command without waiting for it to finish.'''
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
674 # we can't use close_fds *and* redirect stdin. I'm not sure that we
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
675 # need to because the detached process has no console connection.
45786
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
676
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
677 try:
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
678 stdin = None
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
679 if stdin_bytes is not None:
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
680 stdin = pycompat.unnamedtempfile()
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
681 stdin.write(stdin_bytes)
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
682 stdin.flush()
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
683 stdin.seek(0)
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
684
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
685 p = subprocess.Popen(
46030
2cf61e66c6d0 merge with stable
Augie Fackler <augie@google.com>
parents: 45942 46019
diff changeset
686 pycompat.rapply(tonativestr, script),
45786
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
687 shell=shell,
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
688 env=tonativeenv(env),
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
689 close_fds=True,
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
690 creationflags=_creationflags,
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
691 stdin=stdin,
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
692 stdout=stdout,
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
693 stderr=stderr,
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
694 )
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
695 if record_wait is not None:
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
696 record_wait(p.wait)
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
697 finally:
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
698 if stdin is not None:
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
699 stdin.close()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
700
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
701
40497
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
702 else:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
703
46889
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
704 def runbgcommandpy3(
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
705 cmd,
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
706 env,
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
707 shell=False,
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
708 stdout=None,
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
709 stderr=None,
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
710 ensurestart=True,
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
711 record_wait=None,
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
712 stdin_bytes=None,
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
713 ):
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
714 """Spawn a command without waiting for it to finish.
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
715
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
716
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
717 When `record_wait` is not None, the spawned process will not be fully
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
718 detached and the `record_wait` argument will be called with a the
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
719 `Subprocess.wait` function for the spawned process. This is mostly
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
720 useful for developers that need to make sure the spawned process
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
721 finished before a certain point. (eg: writing test)"""
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
722 if pycompat.isdarwin:
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
723 # avoid crash in CoreFoundation in case another thread
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
724 # calls gui() while we're calling fork().
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
725 gui()
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
726
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
727 if shell:
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
728 script = cmd
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
729 else:
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
730 if isinstance(cmd, bytes):
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
731 cmd = [cmd]
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
732 script = b' '.join(shellquote(x) for x in cmd)
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
733 if record_wait is None:
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
734 # double-fork to completely detach from the parent process
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
735 script = b'( %s ) &' % script
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
736 start_new_session = True
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
737 else:
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
738 start_new_session = False
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
739 ensurestart = True
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
740
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
741 try:
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
742 if stdin_bytes is None:
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
743 stdin = subprocess.DEVNULL
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
744 else:
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
745 stdin = pycompat.unnamedtempfile()
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
746 stdin.write(stdin_bytes)
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
747 stdin.flush()
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
748 stdin.seek(0)
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
749 if stdout is None:
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
750 stdout = subprocess.DEVNULL
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
751 if stderr is None:
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
752 stderr = subprocess.DEVNULL
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
753
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
754 p = subprocess.Popen(
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
755 script,
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
756 shell=True,
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
757 env=env,
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
758 close_fds=True,
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
759 stdin=stdin,
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
760 stdout=stdout,
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
761 stderr=stderr,
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
762 start_new_session=start_new_session,
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
763 )
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
764 except Exception:
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
765 if record_wait is not None:
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
766 record_wait(255)
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
767 raise
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
768 finally:
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
769 if stdin_bytes is not None:
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
770 stdin.close()
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
771 if not ensurestart:
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
772 # Even though we're not waiting on the child process,
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
773 # we still must call waitpid() on it at some point so
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
774 # it's not a zombie/defunct. This is especially relevant for
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
775 # chg since the parent process won't die anytime soon.
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
776 # We use a thread to make the overhead tiny.
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
777 t = threading.Thread(target=lambda: p.wait)
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
778 t.daemon = True
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
779 t.start()
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
780 else:
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
781 returncode = p.wait
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
782 if record_wait is not None:
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
783 record_wait(returncode)
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
784
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
785 def runbgcommandpy2(
43848
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
786 cmd,
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
787 env,
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
788 shell=False,
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
789 stdout=None,
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
790 stderr=None,
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
791 ensurestart=True,
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
792 record_wait=None,
45786
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
793 stdin_bytes=None,
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
794 ):
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45852
diff changeset
795 """Spawn a command without waiting for it to finish.
43848
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
796
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
797
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
798 When `record_wait` is not None, the spawned process will not be fully
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
799 detached and the `record_wait` argument will be called with a the
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
800 `Subprocess.wait` function for the spawned process. This is mostly
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
801 useful for developers that need to make sure the spawned process
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45852
diff changeset
802 finished before a certain point. (eg: writing test)"""
43912
a89381e04c58 procutil: try and avoid angering CoreFoundation on macOS
Augie Fackler <augie@google.com>
parents: 43862
diff changeset
803 if pycompat.isdarwin:
a89381e04c58 procutil: try and avoid angering CoreFoundation on macOS
Augie Fackler <augie@google.com>
parents: 43862
diff changeset
804 # avoid crash in CoreFoundation in case another thread
a89381e04c58 procutil: try and avoid angering CoreFoundation on macOS
Augie Fackler <augie@google.com>
parents: 43862
diff changeset
805 # calls gui() while we're calling fork().
a89381e04c58 procutil: try and avoid angering CoreFoundation on macOS
Augie Fackler <augie@google.com>
parents: 43862
diff changeset
806 gui()
a89381e04c58 procutil: try and avoid angering CoreFoundation on macOS
Augie Fackler <augie@google.com>
parents: 43862
diff changeset
807
40497
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
808 # double-fork to completely detach from the parent process
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
809 # based on http://code.activestate.com/recipes/278731
43848
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
810 if record_wait is None:
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
811 pid = os.fork()
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
812 if pid:
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
813 if not ensurestart:
44781
ed684a82e29b procutil: always waiting on child processes to prevent zombies with 'hg serve'
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 43912
diff changeset
814 # Even though we're not waiting on the child process,
ed684a82e29b procutil: always waiting on child processes to prevent zombies with 'hg serve'
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 43912
diff changeset
815 # we still must call waitpid() on it at some point so
ed684a82e29b procutil: always waiting on child processes to prevent zombies with 'hg serve'
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 43912
diff changeset
816 # it's not a zombie/defunct. This is especially relevant for
ed684a82e29b procutil: always waiting on child processes to prevent zombies with 'hg serve'
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 43912
diff changeset
817 # chg since the parent process won't die anytime soon.
ed684a82e29b procutil: always waiting on child processes to prevent zombies with 'hg serve'
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 43912
diff changeset
818 # We use a thread to make the overhead tiny.
ed684a82e29b procutil: always waiting on child processes to prevent zombies with 'hg serve'
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 43912
diff changeset
819 def _do_wait():
ed684a82e29b procutil: always waiting on child processes to prevent zombies with 'hg serve'
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 43912
diff changeset
820 os.waitpid(pid, 0)
44812
79f6f856c53f formatting: add missing newline
Raphaël Gomès <rgomes@octobus.net>
parents: 44781
diff changeset
821
44978
95c672c07116 procutil: make recent fix for zombies compatible with py2
Martin von Zweigbergk <martinvonz@google.com>
parents: 44919
diff changeset
822 t = threading.Thread(target=_do_wait)
95c672c07116 procutil: make recent fix for zombies compatible with py2
Martin von Zweigbergk <martinvonz@google.com>
parents: 44919
diff changeset
823 t.daemon = True
95c672c07116 procutil: make recent fix for zombies compatible with py2
Martin von Zweigbergk <martinvonz@google.com>
parents: 44919
diff changeset
824 t.start()
43848
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
825 return
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
826 # Parent process
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
827 (_pid, status) = os.waitpid(pid, 0)
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
828 if os.WIFEXITED(status):
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
829 returncode = os.WEXITSTATUS(status)
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
830 else:
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
831 returncode = -(os.WTERMSIG(status))
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
832 if returncode != 0:
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
833 # The child process's return code is 0 on success, an errno
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
834 # value on failure, or 255 if we don't have a valid errno
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
835 # value.
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
836 #
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
837 # (It would be slightly nicer to return the full exception info
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
838 # over a pipe as the subprocess module does. For now it
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
839 # doesn't seem worth adding that complexity here, though.)
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
840 if returncode == 255:
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
841 returncode = errno.EINVAL
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
842 raise OSError(
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
843 returncode,
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
844 b'error running %r: %s'
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
845 % (cmd, os.strerror(returncode)),
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
846 )
42496
ca1014ad3de4 procutil: allow callers of runbgcommand to assume the process starts
Augie Fackler <augie@google.com>
parents: 41832
diff changeset
847 return
40497
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
848
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
849 returncode = 255
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
850 try:
43848
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
851 if record_wait is None:
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
852 # Start a new session
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
853 os.setsid()
45786
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
854 # connect stdin to devnull to make sure the subprocess can't
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
855 # muck up that stream for mercurial.
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
856 if stdin_bytes is None:
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
857 stdin = open(os.devnull, b'r')
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
858 else:
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
859 stdin = pycompat.unnamedtempfile()
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
860 stdin.write(stdin_bytes)
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
861 stdin.flush()
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
862 stdin.seek(0)
40497
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
863
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
864 if stdout is None:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
865 stdout = open(os.devnull, b'w')
40497
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
866 if stderr is None:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
867 stderr = open(os.devnull, b'w')
40497
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
868
43848
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
869 p = subprocess.Popen(
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
870 cmd,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
871 shell=shell,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
872 env=env,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
873 close_fds=True,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
874 stdin=stdin,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
875 stdout=stdout,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
876 stderr=stderr,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
877 )
43848
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
878 if record_wait is not None:
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
879 record_wait(p.wait)
40497
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
880 returncode = 0
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
881 except EnvironmentError as ex:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
882 returncode = ex.errno & 0xFF
40497
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
883 if returncode == 0:
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
884 # This shouldn't happen, but just in case make sure the
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
885 # return code is never 0 here.
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
886 returncode = 255
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
887 except Exception:
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
888 returncode = 255
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
889 finally:
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
890 # mission accomplished, this child needs to exit and not
3fbfbc8c9f82 remotefilelog: transplant runbgcommand to procutil
Augie Fackler <augie@google.com>
parents: 39840
diff changeset
891 # continue the hg process here.
45786
37c65704869d procutil: allow to specify arbitrary stdin bytes to runbgcommand
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45148
diff changeset
892 stdin.close()
43848
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
893 if record_wait is None:
15a6c6783060 procutil: add a option to not fully detach background process
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43165
diff changeset
894 os._exit(returncode)
46889
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
895
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
896 if pycompat.ispy3:
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
897 # This branch is more robust, because it avoids running python
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
898 # code (hence gc finalizers, like sshpeer.__del__, which
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
899 # blocks). But we can't easily do the equivalent in py2,
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
900 # because of the lack of start_new_session=True flag. Given
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
901 # that the py2 branch should die soon, the short-lived
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
902 # duplication seems acceptable.
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
903 runbgcommand = runbgcommandpy3
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
904 else:
8759e22f1649 procutil: avoid using os.fork() to implement runbgcommand
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46819
diff changeset
905 runbgcommand = runbgcommandpy2