def run_command()

in builder/core/util.py [0:0]


def run_command(*command, **kwargs):
    if not kwargs.get('quiet', False):
        log_command(*command)
    dryrun = kwargs.get('dryrun', False)
    if dryrun:
        return None
    tries = kwargs.get('retries', 1)
    working_dir = kwargs.get('working_dir', os.getcwd())

    output = None
    while tries > 0:
        tries -= 1
        try:
            cmds = _flatten_command(*command)
            if sys.platform == 'win32':
                cmds = [cmd.encode('ascii', 'ignore').decode()
                        for cmd in cmds]
            cmd = subprocess.list2cmdline(cmds)

            # force the working directory
            cwd = os.getcwd()
            os.chdir(working_dir)

            proc = subprocess.Popen(
                cmd,
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
                shell=True,
                bufsize=0)  # do not buffer output
            with proc:

                # Convert all output to strings, which makes it much easier to both print
                # and process, since all known uses of parsing output want strings anyway
                output = ""
                line = proc.stdout.readline()
                while (line):
                    # ignore weird characters coming back from the shell (colors, etc)
                    if not isinstance(line, str):
                        line = line.decode('ascii', 'ignore')
                    # We're reading in binary mode, so no automatic newline translation
                    if sys.platform == 'win32':
                        line = line.replace('\r\n', '\n')
                    output += line
                    if not kwargs.get('quiet', False):
                        print(line, end='', flush=True)
                    line = proc.stdout.readline()
                proc.wait()

                # restore working directory before exiting the function
                os.chdir(cwd)

                if proc.returncode != 0:
                    raise Exception(
                        'Command exited with code {}:\n{}'.format(proc.returncode, output))

                return ExecResult(proc.returncode, proc.pid, output)

        except Exception as ex:
            print('Failed to run {}: {}'.format(
                ' '.join(_flatten_command(*command)), ex))
            if kwargs.get('check', False) and tries == 0:
                raise
            output = ex
            if tries > 0:
                print('Waiting {} seconds to try again'.format(
                    _retry_wait_secs))
                sleep(_retry_wait_secs)
    return ExecResult(-1, -1, output)