aboutsummaryrefslogtreecommitdiffstats
path: root/MgaRepo/util.py
diff options
context:
space:
mode:
Diffstat (limited to 'MgaRepo/util.py')
-rw-r--r--MgaRepo/util.py139
1 files changed, 78 insertions, 61 deletions
diff --git a/MgaRepo/util.py b/MgaRepo/util.py
index 538eae8..64faaa1 100644
--- a/MgaRepo/util.py
+++ b/MgaRepo/util.py
@@ -2,6 +2,7 @@
from MgaRepo import Error, config
+import shlex
import subprocess
import getpass
import sys
@@ -11,73 +12,89 @@ import select
from io import StringIO
import httplib2
-# Our own version of commands' commands_exec(). We have a commands
-# module directory, so we can't import Python's standard module
-
-# Our own version of commands' getstatusoutput(). We have a commands
-# module directory, so we can't import Python's standard module
-def commands_getstatusoutput(cmd):
- """Return (status, output) of executing cmd in a shell."""
- pipe = subprocess.Popen('{ ' + cmd + '; } 2>&1', stdin = subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines = True, shell = True)
- of = pipe.stdout.fileno()
- text = ''
- pipe.stdin.close()
- while True:
- text += os.read(of,8192).decode('utf8')
- status = pipe.poll()
- if status is not None or text == '':
- break
- if text[-1:] == '\n': text = text[:-1]
- return status, text
+class CommandError(Error):
+ def __init__(self, cmdline, status, output):
+ self.cmdline = cmdline
+ self.status = status
+ self.output = output
+
+ def __str__(self):
+ return "command failed: %s\n%s\n" % (self.cmdline, self.output)
def execcmd(*cmd, **kwargs):
- cmdstr = " ".join(cmd)
- verbose = config.getbool("global", "verbose", 0)
- if kwargs.get('info') :
- prefix='LANGUAGE=C LC_TIME=C '
- else:
- prefix='LANG=C LANGUAGE=C LC_ALL=C '
- if verbose:
- print(prefix + cmdstr)
- if kwargs.get("show"):
- if kwargs.get("geterr"):
- err = StringIO()
- pstdin = kwargs.get("stdin") if kwargs.get("stdin") else None
- p = subprocess.Popen(prefix + cmdstr, shell=True,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE,
- stdin=pstdin)
- of = p.stdout.fileno()
- ef = p.stderr.fileno()
- while True:
- r,w,x = select.select((of,ef), (), ())
- odata = None
- if of in r:
- odata = (os.read(of, 8192)).decode('utf8')
- sys.stdout.write(odata)
- edata = None
- if ef in r:
- edata = (os.read(ef, 8192)).decode('utf8')
- err.write(edata)
- sys.stderr.write(edata)
-
- status = p.poll()
- if status is not None and odata == '' and edata == '':
- break
- output = err.getvalue()
+ assert (kwargs.get("collecterr") and kwargs.get("show")) or not kwargs.get("collecterr"), \
+ ("execcmd is implemented to handle collecterr=True only if show=True")
+ # split command args
+ if isinstance(cmd[0], str):
+ if len(cmd) is 1:
+ cmdargs = shlex.split(cmd[0])
else:
- status = os.system(cmdstr)
- output = ""
+ cmdargs = cmd[:]
else:
- status, output = commands_getstatusoutput(prefix + cmdstr)
- if status != 0 and not kwargs.get("noerror"):
- if kwargs.get("cleanerr") and not verbose:
- raise Error(output)
+ cmdargs = cmd[0][:]
+
+ stdout = None
+ stderr = None
+ env = {}
+ env.update(os.environ)
+ if kwargs.get("info") or not kwargs.get("show") or (kwargs.get("show") and kwargs.get("collecterr")):
+ if kwargs.get("info"):
+ env.update({"LANGUAGE": "C", "LC_TIME": "C"})
+ else:
+ env.update({"LANG": "C", "LANGUAGE": "C", "LC_ALL": "C"})
+ stdout = subprocess.PIPE
+ if kwargs.get("collecterr"):
+ stderr = subprocess.PIPE
else:
- raise Error("command failed: %s\n%s\n" % (cmdstr, output))
+ stderr = subprocess.STDOUT
+
+ verbose = config.getbool("global", "verbose", 0)
if verbose:
- print(output)
- sys.stdout.write(output)
- return status, output
+ print("cmd: " + str(cmd).lstrip("(").rstrip(")").replace("', '", "' '"))
+
+ proc = subprocess.Popen(cmdargs, shell=False, stdout=stdout,
+ stderr=stderr, env=env)
+
+ output = ""
+
+ if kwargs.get("show") and kwargs.get("collecterr"):
+ error = StringIO()
+ wl = []
+ outfd = proc.stdout.fileno()
+ errfd = proc.stderr.fileno()
+ rl = [outfd, errfd]
+ xl = wl
+ while proc.poll() is None:
+ mrl, _, _ = select.select(rl, wl, xl, 0.5)
+ for fd in mrl:
+ data = os.read(fd, 8192).decode('utf8')
+ if fd == errfd:
+ error.write(data)
+ sys.stderr.write(data)
+ else:
+ sys.stdout.write(data)
+ output = error.getvalue()
+ else:
+ # Make sure to avoid buffer getting full.
+ # Otherwise if ie. using proc.wait() both python
+ # and the process will just hang
+ while proc.poll() is None:
+ if proc.stdout is not None:
+ output += proc.stdout.read(8192).decode('utf8')
+ # Make sure that we've emptied the buffer entirely
+ if proc.stdout is not None:
+ output += proc.stdout.read().decode('utf8')
+
+ if kwargs.get("strip", True):
+ output = output.rstrip()
+
+ if (not kwargs.get("noerror")) and proc.returncode != 0:
+ if kwargs.get("cleanerr"):
+ msg = output
+ cmdline = subprocess.list2cmdline(cmdargs)
+ raise CommandError(cmdline, proc.returncode, output)
+
+ return proc.returncode, output
def get_output_exec(cmdstr):
output = StringIO()