mirror of
https://github.com/facebook/sapling.git
synced 2024-10-05 14:28:17 +03:00
fbcode_builder: getdeps: add run_cmd() function
Summary: This runs a command, raising an exception if it exits with a non-zero error status. It prints out the arguments in a mostly copy-and-pasteable form, with PATH-like env vars pretty printed to make it easier to see what is being invoked; here's an example of how cmake is being invoked later in this stack: ``` --- + CMAKE_PREFIX_PATH=\ + /data/users/wez/scratch/dataZusersZwezZfbsource/fbcode_builder_getdeps/installed/ninja-5d7ec7:\ + /data/users/wez/scratch/dataZusersZwezZfbsource/fbcode_builder_getdeps/installed/cmake-91dc9a:\ + PKG_CONFIG_PATH=\ + /data/users/wez/scratch/dataZusersZwezZfbsource/fbcode_builder_getdeps/installed/ninja-5d7ec7/lib/pkgconfig:\ + /data/users/wez/scratch/dataZusersZwezZfbsource/fbcode_builder_getdeps/installed/cmake-91dc9a/lib/pkgconfig:\ + cd /data/users/wez/scratch/dataZusersZwezZfbsource/fbcode_builder_getdeps/build/zstd-470344 && \ + cmake configure /data/users/wez/scratch/dataZusersZwezZfbsource/fbcode_builder_getdeps/repos/github.com-facebook-zstd.git/build/cmake -DCMAKE_INST ALL_PREFIX=/data/users/wez/scratch/dataZusersZwezZfbsource/fbcode_builder_getdeps/installed/zstd-470344 -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=R elWithDebInfo -G Ninja ``` Reviewed By: simpkins Differential Revision: D14690999 fbshipit-source-id: cdb0c681c7dfdfdc6e8c96bf4830bfbcf666411b
This commit is contained in:
parent
0bc46905d0
commit
3d0d9e6d53
87
build/fbcode_builder/getdeps/runcmd.py
Normal file
87
build/fbcode_builder/getdeps/runcmd.py
Normal file
@ -0,0 +1,87 @@
|
||||
# Copyright (c) 2019-present, Facebook, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This source code is licensed under the BSD-style license found in the
|
||||
# LICENSE file in the root directory of this source tree. An additional grant
|
||||
# of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from .envfuncs import Env
|
||||
from .platform import is_windows
|
||||
|
||||
|
||||
try:
|
||||
from shlex import quote as shellquote
|
||||
except ImportError:
|
||||
from pipes import quote as shellquote
|
||||
|
||||
|
||||
class RunCommandError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def _print_env_diff(env):
|
||||
current_keys = set(os.environ.keys())
|
||||
wanted_env = set(env.keys())
|
||||
|
||||
unset_keys = current_keys.difference(wanted_env)
|
||||
for k in sorted(unset_keys):
|
||||
print("+ unset %s" % k)
|
||||
|
||||
added_keys = wanted_env.difference(current_keys)
|
||||
for k in wanted_env.intersection(current_keys):
|
||||
if os.environ[k] != env[k]:
|
||||
added_keys.add(k)
|
||||
|
||||
for k in sorted(added_keys):
|
||||
if ("PATH" in k) and (os.pathsep in env[k]):
|
||||
print("+ %s=\\" % k)
|
||||
for elem in env[k].split(os.pathsep):
|
||||
print("+ %s%s\\" % (shellquote(elem), os.pathsep))
|
||||
else:
|
||||
print("+ %s=%s \\" % (k, shellquote(env[k])))
|
||||
|
||||
|
||||
def run_cmd(cmd, env=None, cwd=None, allow_fail=False):
|
||||
print("---")
|
||||
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)
|
||||
|
||||
# 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:
|
||||
print("+ cd %s && \\" % 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:]
|
||||
|
||||
print("+ %s" % cmd_str)
|
||||
|
||||
if allow_fail:
|
||||
return subprocess.call(cmd, env=env, cwd=cwd)
|
||||
|
||||
try:
|
||||
return subprocess.check_call(cmd, env=env, cwd=cwd)
|
||||
except (TypeError, ValueError, OSError) as exc:
|
||||
raise RunCommandError(
|
||||
"%s while running `%s` with env=%r\nos.environ=%r"
|
||||
% (str(exc), cmd_str, env, os.environ)
|
||||
)
|
Loading…
Reference in New Issue
Block a user