aboutsummaryrefslogtreecommitdiff
path: root/cli/lib/core/tool.py
diff options
context:
space:
mode:
Diffstat (limited to 'cli/lib/core/tool.py')
-rw-r--r--cli/lib/core/tool.py43
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):