repo2docker/repo2docker/utils.py

54 wiersze
1.4 KiB
Python
Czysty Zwykły widok Historia

from contextlib import contextmanager
from functools import partial
import shutil
import subprocess
def execute_cmd(cmd, capture=False, **kwargs):
"""
Call given command, yielding output line by line if capture=True
"""
if capture:
kwargs['stdout'] = subprocess.PIPE
kwargs['stderr'] = subprocess.STDOUT
proc = subprocess.Popen(cmd, **kwargs)
if not capture:
2017-05-24 23:42:25 +00:00
# not capturing output, let the subprocesses talk directly to the terminal
ret = proc.wait()
if ret != 0:
raise subprocess.CalledProcessError(ret, cmd)
return
2017-05-24 23:42:25 +00:00
# Capture output for logging.
# Each line will be yielded as text.
# This should behave the same as .readline(), but splits on `\r` OR `\n`,
# not just `\n`.
buf = []
def flush():
line = b''.join(buf).decode('utf8', 'replace')
buf[:] = []
return line
c_last = ''
try:
for c in iter(partial(proc.stdout.read, 1), b''):
if c_last == b'\r' and buf and c != b'\n':
yield flush()
buf.append(c)
if c == b'\n':
yield flush()
c_last = c
finally:
ret = proc.wait()
if ret != 0:
raise subprocess.CalledProcessError(ret, cmd)
@contextmanager
def maybe_cleanup(path, cleanup=False):
yield
if cleanup:
shutil.rmtree(path, ignore_errors=True)