in build/fbcode_builder/getdeps/runcmd.py [0:0]
def _run_cmd(cmd, env, cwd, allow_fail, log_fn) -> int:
log_fn("---\n")
try:
cmd_str = " \\\n+ ".join(shellquote(arg) for arg in cmd)
except TypeError:
# eg: one of the elements is None
raise RunCommandError("problem quoting cmd: %r" % cmd)
if env:
assert isinstance(env, Env)
_print_env_diff(env, log_fn)
# Convert from our Env type to a regular dict.
# This is needed because python3 looks up b'PATH' and 'PATH'
# and emits an error if both are present. In our Env type
# we'll return the same value for both requests, but we don't
# have duplicate potentially conflicting values which is the
# spirit of the check.
env = dict(env.items())
if cwd:
log_fn("+ cd %s && \\\n" % shellquote(cwd))
# Our long path escape sequence may confuse cmd.exe, so if the cwd
# is short enough, strip that off.
if is_windows() and (len(cwd) < 250) and cwd.startswith("\\\\?\\"):
cwd = cwd[4:]
log_fn("+ %s\n" % cmd_str)
isinteractive = os.isatty(sys.stdout.fileno())
if isinteractive:
stdout = None
sys.stdout.buffer.flush()
else:
stdout = subprocess.PIPE
try:
p = subprocess.Popen(
cmd, env=env, cwd=cwd, stdout=stdout, stderr=subprocess.STDOUT
)
except (TypeError, ValueError, OSError) as exc:
log_fn("error running `%s`: %s" % (cmd_str, exc))
raise RunCommandError(
"%s while running `%s` with env=%r\nos.environ=%r"
% (str(exc), cmd_str, env, os.environ)
)
if not isinteractive:
_pipe_output(p, log_fn)
p.wait()
if p.returncode != 0 and not allow_fail:
raise subprocess.CalledProcessError(p.returncode, cmd)
return p.returncode