10d24de9dSSimon Glass# Copyright (c) 2011 The Chromium OS Authors. 20d24de9dSSimon Glass# 30d24de9dSSimon Glass# See file CREDITS for list of people who contributed to this 40d24de9dSSimon Glass# project. 50d24de9dSSimon Glass# 60d24de9dSSimon Glass# This program is free software; you can redistribute it and/or 70d24de9dSSimon Glass# modify it under the terms of the GNU General Public License as 80d24de9dSSimon Glass# published by the Free Software Foundation; either version 2 of 90d24de9dSSimon Glass# the License, or (at your option) any later version. 100d24de9dSSimon Glass# 110d24de9dSSimon Glass# This program is distributed in the hope that it will be useful, 120d24de9dSSimon Glass# but WITHOUT ANY WARRANTY; without even the implied warranty of 130d24de9dSSimon Glass# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 140d24de9dSSimon Glass# GNU General Public License for more details. 150d24de9dSSimon Glass# 160d24de9dSSimon Glass# You should have received a copy of the GNU General Public License 170d24de9dSSimon Glass# along with this program; if not, write to the Free Software 180d24de9dSSimon Glass# Foundation, Inc., 59 Temple Place, Suite 330, Boston, 190d24de9dSSimon Glass# MA 02111-1307 USA 200d24de9dSSimon Glass# 210d24de9dSSimon Glass 220d24de9dSSimon Glassimport os 23*a10fd93cSSimon Glassimport cros_subprocess 240d24de9dSSimon Glass 250d24de9dSSimon Glass"""Shell command ease-ups for Python.""" 260d24de9dSSimon Glass 27*a10fd93cSSimon Glassclass CommandResult: 28*a10fd93cSSimon Glass """A class which captures the result of executing a command. 29*a10fd93cSSimon Glass 30*a10fd93cSSimon Glass Members: 31*a10fd93cSSimon Glass stdout: stdout obtained from command, as a string 32*a10fd93cSSimon Glass stderr: stderr obtained from command, as a string 33*a10fd93cSSimon Glass return_code: Return code from command 34*a10fd93cSSimon Glass exception: Exception received, or None if all ok 35*a10fd93cSSimon Glass """ 36*a10fd93cSSimon Glass def __init__(self): 37*a10fd93cSSimon Glass self.stdout = None 38*a10fd93cSSimon Glass self.stderr = None 39*a10fd93cSSimon Glass self.return_code = None 40*a10fd93cSSimon Glass self.exception = None 41*a10fd93cSSimon Glass 42*a10fd93cSSimon Glass 43*a10fd93cSSimon Glassdef RunPipe(pipe_list, infile=None, outfile=None, 44*a10fd93cSSimon Glass capture=False, capture_stderr=False, oneline=False, 45*a10fd93cSSimon Glass cwd=None, **kwargs): 460d24de9dSSimon Glass """ 470d24de9dSSimon Glass Perform a command pipeline, with optional input/output filenames. 480d24de9dSSimon Glass 49*a10fd93cSSimon Glass Args: 50*a10fd93cSSimon Glass pipe_list: List of command lines to execute. Each command line is 51*a10fd93cSSimon Glass piped into the next, and is itself a list of strings. For 52*a10fd93cSSimon Glass example [ ['ls', '.git'] ['wc'] ] will pipe the output of 53*a10fd93cSSimon Glass 'ls .git' into 'wc'. 54*a10fd93cSSimon Glass infile: File to provide stdin to the pipeline 55*a10fd93cSSimon Glass outfile: File to store stdout 56*a10fd93cSSimon Glass capture: True to capture output 57*a10fd93cSSimon Glass capture_stderr: True to capture stderr 58*a10fd93cSSimon Glass oneline: True to strip newline chars from output 59*a10fd93cSSimon Glass kwargs: Additional keyword arguments to cros_subprocess.Popen() 60*a10fd93cSSimon Glass Returns: 61*a10fd93cSSimon Glass CommandResult object 620d24de9dSSimon Glass """ 63*a10fd93cSSimon Glass result = CommandResult() 640d24de9dSSimon Glass last_pipe = None 65*a10fd93cSSimon Glass pipeline = list(pipe_list) 660d24de9dSSimon Glass while pipeline: 670d24de9dSSimon Glass cmd = pipeline.pop(0) 680d24de9dSSimon Glass if last_pipe is not None: 690d24de9dSSimon Glass kwargs['stdin'] = last_pipe.stdout 700d24de9dSSimon Glass elif infile: 710d24de9dSSimon Glass kwargs['stdin'] = open(infile, 'rb') 720d24de9dSSimon Glass if pipeline or capture: 73*a10fd93cSSimon Glass kwargs['stdout'] = cros_subprocess.PIPE 740d24de9dSSimon Glass elif outfile: 750d24de9dSSimon Glass kwargs['stdout'] = open(outfile, 'wb') 76*a10fd93cSSimon Glass if capture_stderr: 77*a10fd93cSSimon Glass kwargs['stderr'] = cros_subprocess.PIPE 780d24de9dSSimon Glass 79*a10fd93cSSimon Glass try: 80*a10fd93cSSimon Glass last_pipe = cros_subprocess.Popen(cmd, cwd=cwd, **kwargs) 81*a10fd93cSSimon Glass except Exception, err: 82*a10fd93cSSimon Glass result.exception = err 83*a10fd93cSSimon Glass print 'exception', pipe_list, err 84*a10fd93cSSimon Glass raise Exception("Error running '%s': %s" % (pipe_list, str)) 850d24de9dSSimon Glass 860d24de9dSSimon Glass if capture: 87*a10fd93cSSimon Glass result.stdout, result.stderr, result.combined = ( 88*a10fd93cSSimon Glass last_pipe.CommunicateFilter(None)) 89*a10fd93cSSimon Glass if result.stdout and oneline: 90*a10fd93cSSimon Glass result.output = result.stdout.rstrip('\r\n') 91*a10fd93cSSimon Glass result.return_code = last_pipe.wait() 920d24de9dSSimon Glass else: 93*a10fd93cSSimon Glass result.return_code = os.waitpid(last_pipe.pid, 0)[1] 94*a10fd93cSSimon Glass if result.return_code: 95*a10fd93cSSimon Glass raise Exception("Error running '%s'" % pipe_list) 96*a10fd93cSSimon Glass return result 970d24de9dSSimon Glass 980d24de9dSSimon Glassdef Output(*cmd): 99*a10fd93cSSimon Glass return RunPipe([cmd], capture=True).stdout 1000d24de9dSSimon Glass 101*a10fd93cSSimon Glassdef OutputOneLine(*cmd, **kwargs): 102*a10fd93cSSimon Glass return (RunPipe([cmd], capture=True, oneline=True, 103*a10fd93cSSimon Glass **kwargs).stdout.strip()) 1040d24de9dSSimon Glass 1050d24de9dSSimon Glassdef Run(*cmd, **kwargs): 106*a10fd93cSSimon Glass return RunPipe([cmd], **kwargs).stdout 1070d24de9dSSimon Glass 1080d24de9dSSimon Glassdef RunList(cmd): 109*a10fd93cSSimon Glass return RunPipe([cmd], capture=True).stdout 110*a10fd93cSSimon Glass 111*a10fd93cSSimon Glassdef StopAll(): 112*a10fd93cSSimon Glass cros_subprocess.stay_alive = False 113