Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
# We never capture stderr, to prevent error messages from being eaten.
#
# check:
# True if an error should be raised if the git command finishes with a
# non-zero return code.
#
# Returns a subprocess.CompletedProcess instance.
# TODO: Run once somewhere?
if shutil.which('git') is None:
log.die('Git is not installed or cannot be found')
args = (('git',) +
tuple(_expand_shorthands(project, arg) for arg in cmd.split()) +
tuple(extra_args))
cmd_str = util.quote_sh_list(args)
log.dbg("running '{}'".format(cmd_str), 'in', cwd, level=log.VERBOSE_VERY)
popen = subprocess.Popen(
args, stdout=subprocess.PIPE if capture_stdout else None, cwd=cwd)
stdout, _ = popen.communicate()
dbg_msg = "'{}' in {} finished with exit status {}" \
.format(cmd_str, cwd, popen.returncode)
if capture_stdout:
dbg_msg += " and wrote {} to stdout".format(stdout)
log.dbg(dbg_msg, level=log.VERBOSE_VERY)
if check and popen.returncode:
msg = "Command '{}' failed for {{name_and_path}}".format(cmd_str)
if _error_context_msg:
def check_call(self, cmd):
'''Subclass subprocess.check_call() wrapper.
Subclasses should use this method to run command in a
subprocess and check that it executed correctly, rather than
using subprocess directly, to keep accurate debug logs.
'''
quoted = quote_sh_list(cmd)
if JUST_PRINT:
log.inf(quoted)
return
log.dbg(quoted)
try:
subprocess.check_call(cmd)
except subprocess.CalledProcessError:
raise
def check_call(self, args, cwd=None):
cmd_str = util.quote_sh_list(args)
log.dbg(f"running '{cmd_str}' in {cwd or os.getcwd()}",
level=log.VERBOSE_VERY)
subprocess.check_call(args, cwd=cwd)
def run_cmake(args, quiet=False):
'''Run cmake to (re)generate a build system'''
cmake = shutil.which('cmake')
if cmake is None:
log.die('CMake is not installed or cannot be found; cannot build.')
cmd = [cmake] + args
kwargs = dict()
if quiet:
kwargs['stdout'] = subprocess.DEVNULL
kwargs['stderr'] = subprocess.STDOUT
log.dbg('Running CMake:', cmd, level=log.VERBOSE_VERY)
log.dbg('As command:', quote_sh_list(cmd), level=log.VERBOSE_VERY)
subprocess.check_call(cmd, **kwargs)
if cmake is None and not dry_run:
log.die('CMake is not installed or cannot be found; cannot build.')
_ensure_min_version(cmake, dry_run)
cmd = [cmake] + args
kwargs = dict()
if capture_output:
kwargs['stdout'] = subprocess.PIPE
# CMake sends the output of message() to stderr unless it's STATUS
kwargs['stderr'] = subprocess.STDOUT
if cwd:
kwargs['cwd'] = cwd
if dry_run:
in_cwd = ' (in {})'.format(cwd) if cwd else ''
log.inf('Dry run{}:'.format(in_cwd), quote_sh_list(cmd))
return None
log.dbg('Running CMake:', quote_sh_list(cmd), level=log.VERBOSE_NORMAL)
p = subprocess.Popen(cmd, **kwargs)
out, _ = p.communicate()
if p.returncode == 0:
if out:
return out.decode(sys.getdefaultencoding()).splitlines()
else:
return None
else:
# A real error occurred, raise an exception
raise subprocess.CalledProcessError(p.returncode, p.args)
if cwd is None:
if self.abspath is not None:
cwd = self.abspath
else:
raise ValueError('no abspath; cwd must be given')
elif sys.version_info < (3, 6, 1) and not isinstance(cwd, str):
# Popen didn't accept a PathLike cwd on Windows until
# python v3.7; this was backported onto cpython v3.6.1,
# though. West currently supports "python 3.6", though, so
# in the unlikely event someone is running 3.6.0 on
# Windows, do the right thing.
cwd = os.fspath(cwd)
args = ['git'] + cmd_list + extra_args
cmd_str = util.quote_sh_list(args)
_logger.debug(f"running '{cmd_str}' in {cwd}")
popen = subprocess.Popen(
args, cwd=cwd,
stdout=subprocess.PIPE if capture_stdout else None,
stderr=subprocess.PIPE if capture_stderr else None)
stdout, stderr = popen.communicate()
# We use logger style % formatting here to avoid the
# potentially expensive overhead of formatting long
# stdout/stderr strings if the current log level isn't DEBUG,
# which is the usual case.
_logger.debug('"%s" exit code: %d stdout: %r stderr: %r',
cmd_str, popen.returncode, stdout, stderr)
# We provide a default --version in case the user is just
# messing around and doesn't want to set one. It will be
# overridden if there is a --version in args.tool_args.
sign_base = [tool_path, 'sign',
'--version', '0.0.0+0',
'--align', str(align),
'--header-size', str(vtoff),
'--slot-size', str(size)]
sign_base.extend(args.tool_args)
log.banner('signed binaries:')
if in_bin:
out_bin = args.sbin or str(b / 'zephyr' / 'zephyr.signed.bin')
sign_bin = sign_base + [in_bin, out_bin]
log.inf('bin: {}'.format(out_bin))
log.dbg(quote_sh_list(sign_bin))
subprocess.check_call(sign_bin)
if in_hex:
out_hex = args.shex or str(b / 'zephyr' / 'zephyr.signed.hex')
sign_hex = sign_base + [in_hex, out_hex]
log.inf('hex: {}'.format(out_hex))
log.dbg(quote_sh_list(sign_hex))
subprocess.check_call(sign_hex)
def check_output(self, cmd):
'''Subclass subprocess.check_output() wrapper.
Subclasses should use this method to run command in a
subprocess and check that it executed correctly, rather than
using subprocess directly, to keep accurate debug logs.
'''
quoted = quote_sh_list(cmd)
if JUST_PRINT:
log.inf(quoted)
return b''
log.dbg(quoted)
try:
return subprocess.check_output(cmd)
except subprocess.CalledProcessError:
raise