diff options
Diffstat (limited to 'cli/lib/core/tool.py')
-rw-r--r-- | cli/lib/core/tool.py | 43 |
1 files changed, 38 insertions, 5 deletions
diff --git a/cli/lib/core/tool.py b/cli/lib/core/tool.py index 939827e..699dbef 100644 --- a/cli/lib/core/tool.py +++ b/cli/lib/core/tool.py @@ -132,15 +132,20 @@ class ToolWrapper(object): def exists(self): return os.path.isfile(self._tool_path) - def run(self, arg_array=None): + def run(self, arg_array=None, piped=False): """Executes the tool and blocks until completion. Args: arg_array: list of string arguments to pass to the tool. + piped: If true, send stdout and stderr to pipes. Raises: ExecuteError: if execution fails. ReturnError: if execution returns a non-0 exit code. + + Returns: + (out, err): The output to stdout and stderr of the called tool. + Will both be None if piped=False. """ # Remove -- passthrough indicator from arg_array. if arg_array and arg_array[0] == '--': @@ -150,21 +155,33 @@ class ToolWrapper(object): if self._cwd: self.environment['PWD'] = os.path.abspath(self._cwd) + stdout = None + stderr = None + if piped: + stdout = subprocess.PIPE + stderr = subprocess.PIPE + try: - ret = subprocess.call([self._tool_path] + (arg_array or []), - env=self.environment, shell=False, cwd=self._cwd) + tool_process = subprocess.Popen([self._tool_path] + (arg_array or []), + env=self.environment, shell=False, + cwd=self._cwd, stdout=stdout, + stderr=stderr) + (out, err) = tool_process.communicate() except OSError as e: # Catch and re-raise so we can include the tool path in the message. raise ExecuteError('"{}": {} [{}]'.format( self._tool_path, e.errno, e.strerror)) # Exiting via signal gives negative return codes. + ret = tool_process.returncode if ret < 0: # Return the normal shell exit mask for being signaled. ret = 128 - ret if ret != 0: - raise ReturnError('"{}": {}'.format(self._tool_path, ret), errno=ret) + raise ReturnError('"{}": {} ({})'.format(self._tool_path, ret, err), + errno=ret) + return (out, err) class HostToolWrapper(ToolWrapper): """Wraps a tool from out/host/<arch>/bin/.""" @@ -194,7 +211,23 @@ class HostToolRunner(object): def run(self, path, args): host_tool = HostToolWrapper(path, self._build_out) - host_tool.run(args) + return host_tool.run(args) + + +class PathToolWrapper(ToolWrapper): + """Wraps a tool expected to be in the user PATH.""" + + def __init__(self, program, env=None): + super(PathToolWrapper, self).__init__(program, env) + self.add_caller_env_path() + + +class PathToolRunner(object): + """Serves as a PathToolWrapper factory.""" + + def run(self, path, args): + path_tool = PathToolWrapper(path) + return path_tool.run(args) class ProvisionDeviceTool(ToolWrapper): |