diff options
Diffstat (limited to 'tools/patman')
-rw-r--r-- | tools/patman/checkpatch.py | 3 | ||||
-rw-r--r-- | tools/patman/command.py | 5 | ||||
-rw-r--r-- | tools/patman/gitutil.py | 3 | ||||
-rw-r--r-- | tools/patman/tools.py | 120 | ||||
-rw-r--r-- | tools/patman/tout.py | 166 |
5 files changed, 293 insertions, 4 deletions
diff --git a/tools/patman/checkpatch.py b/tools/patman/checkpatch.py index 34a3bd2..3eef6de 100644 --- a/tools/patman/checkpatch.py +++ b/tools/patman/checkpatch.py @@ -63,7 +63,8 @@ def CheckPatch(fname, verbose=False): result.problems = [] chk = FindCheckPatch() item = {} - result.stdout = command.Output(chk, '--no-tree', fname) + result.stdout = command.Output(chk, '--no-tree', fname, + raise_on_error=False) #pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE) #stdout, stderr = pipe.communicate() diff --git a/tools/patman/command.py b/tools/patman/command.py index d586f11..d1f0ca5 100644 --- a/tools/patman/command.py +++ b/tools/patman/command.py @@ -104,8 +104,9 @@ def RunPipe(pipe_list, infile=None, outfile=None, raise Exception("Error running '%s'" % user_pipestr) return result -def Output(*cmd): - return RunPipe([cmd], capture=True, raise_on_error=False).stdout +def Output(*cmd, **kwargs): + raise_on_error = kwargs.get('raise_on_error', True) + return RunPipe([cmd], capture=True, raise_on_error=raise_on_error).stdout def OutputOneLine(*cmd, **kwargs): raise_on_error = kwargs.pop('raise_on_error', True) diff --git a/tools/patman/gitutil.py b/tools/patman/gitutil.py index e088bae..bb7c9e0 100644 --- a/tools/patman/gitutil.py +++ b/tools/patman/gitutil.py @@ -391,7 +391,8 @@ def EmailPatches(series, cover_fname, args, dry_run, raise_on_error, cc_fname, """ to = BuildEmailList(series.get('to'), '--to', alias, raise_on_error) if not to: - git_config_to = command.Output('git', 'config', 'sendemail.to') + git_config_to = command.Output('git', 'config', 'sendemail.to', + raise_on_error=False) if not git_config_to: print ("No recipient.\n" "Please add something like this to a commit\n" diff --git a/tools/patman/tools.py b/tools/patman/tools.py new file mode 100644 index 0000000..ba24853 --- /dev/null +++ b/tools/patman/tools.py @@ -0,0 +1,120 @@ +# +# Copyright (c) 2016 Google, Inc +# +# SPDX-License-Identifier: GPL-2.0+ +# + +import os +import shutil +import tempfile + +import tout + +outdir = None +indirs = None +preserve_outdir = False + +def PrepareOutputDir(dirname, preserve=False): + """Select an output directory, ensuring it exists. + + This either creates a temporary directory or checks that the one supplied + by the user is valid. For a temporary directory, it makes a note to + remove it later if required. + + Args: + dirname: a string, name of the output directory to use to store + intermediate and output files. If is None - create a temporary + directory. + preserve: a Boolean. If outdir above is None and preserve is False, the + created temporary directory will be destroyed on exit. + + Raises: + OSError: If it cannot create the output directory. + """ + global outdir, preserve_outdir + + preserve_outdir = dirname or preserve + if dirname: + outdir = dirname + if not os.path.isdir(outdir): + try: + os.makedirs(outdir) + except OSError as err: + raise CmdError("Cannot make output directory '%s': '%s'" % + (outdir, err.strerror)) + tout.Debug("Using output directory '%s'" % outdir) + else: + outdir = tempfile.mkdtemp(prefix='binman.') + tout.Debug("Using temporary directory '%s'" % outdir) + +def _RemoveOutputDir(): + global outdir + + shutil.rmtree(outdir) + tout.Debug("Deleted temporary directory '%s'" % outdir) + outdir = None + +def FinaliseOutputDir(): + global outdir, preserve_outdir + + """Tidy up: delete output directory if temporary and not preserved.""" + if outdir and not preserve_outdir: + _RemoveOutputDir() + +def GetOutputFilename(fname): + """Return a filename within the output directory. + + Args: + fname: Filename to use for new file + + Returns: + The full path of the filename, within the output directory + """ + return os.path.join(outdir, fname) + +def _FinaliseForTest(): + """Remove the output directory (for use by tests)""" + global outdir + + if outdir: + _RemoveOutputDir() + +def SetInputDirs(dirname): + """Add a list of input directories, where input files are kept. + + Args: + dirname: a list of paths to input directories to use for obtaining + files needed by binman to place in the image. + """ + global indir + + indir = dirname + tout.Debug("Using input directories %s" % indir) + +def GetInputFilename(fname): + """Return a filename for use as input. + + Args: + fname: Filename to use for new file + + Returns: + The full path of the filename, within the input directory + """ + if not indir: + return fname + for dirname in indir: + pathname = os.path.join(dirname, fname) + if os.path.exists(pathname): + return pathname + + raise ValueError("Filename '%s' not found in input path (%s)" % + (fname, ','.join(indir))) + +def Align(pos, align): + if align: + mask = align - 1 + pos = (pos + mask) & ~mask + return pos + +def NotPowerOfTwo(num): + return num and (num & (num - 1)) diff --git a/tools/patman/tout.py b/tools/patman/tout.py new file mode 100644 index 0000000..c5fbd80 --- /dev/null +++ b/tools/patman/tout.py @@ -0,0 +1,166 @@ +# Copyright (c) 2016 Google, Inc +# +# SPDX-License-Identifier: GPL-2.0+ +# +# Terminal output logging. +# + +import sys + +import terminal + +# Output verbosity levels that we support +ERROR = 0 +WARNING = 1 +NOTICE = 2 +INFO = 3 +DEBUG = 4 + +""" +This class handles output of progress and other useful information +to the user. It provides for simple verbosity level control and can +output nothing but errors at verbosity zero. + +The idea is that modules set up an Output object early in their years and pass +it around to other modules that need it. This keeps the output under control +of a single class. + +Public properties: + verbose: Verbosity level: 0=silent, 1=progress, 3=full, 4=debug +""" +def __enter__(): + return + +def __exit__(unused1, unused2, unused3): + """Clean up and remove any progress message.""" + ClearProgress() + return False + +def UserIsPresent(): + """This returns True if it is likely that a user is present. + + Sometimes we want to prompt the user, but if no one is there then this + is a waste of time, and may lock a script which should otherwise fail. + + Returns: + True if it thinks the user is there, and False otherwise + """ + return stdout_is_tty and verbose > 0 + +def ClearProgress(): + """Clear any active progress message on the terminal.""" + if verbose > 0 and stdout_is_tty: + _stdout.write('\r%s\r' % (" " * len (_progress))) + _stdout.flush() + +def Progress(msg, warning=False, trailer='...'): + """Display progress information. + + Args: + msg: Message to display. + warning: True if this is a warning.""" + ClearProgress() + if verbose > 0: + _progress = msg + trailer + if stdout_is_tty: + col = _color.YELLOW if warning else _color.GREEN + _stdout.write('\r' + _color.Color(col, _progress)) + _stdout.flush() + else: + _stdout.write(_progress + '\n') + +def _Output(level, msg, color=None): + """Output a message to the terminal. + + Args: + level: Verbosity level for this message. It will only be displayed if + this as high as the currently selected level. + msg; Message to display. + error: True if this is an error message, else False. + """ + if verbose >= level: + ClearProgress() + if color: + msg = _color.Color(color, msg) + _stdout.write(msg + '\n') + +def DoOutput(level, msg): + """Output a message to the terminal. + + Args: + level: Verbosity level for this message. It will only be displayed if + this as high as the currently selected level. + msg; Message to display. + """ + _Output(level, msg) + +def Error(msg): + """Display an error message + + Args: + msg; Message to display. + """ + _Output(0, msg, _color.RED) + +def Warning(msg): + """Display a warning message + + Args: + msg; Message to display. + """ + _Output(1, msg, _color.YELLOW) + +def Notice(msg): + """Display an important infomation message + + Args: + msg; Message to display. + """ + _Output(2, msg) + +def Info(msg): + """Display an infomation message + + Args: + msg; Message to display. + """ + _Output(3, msg) + +def Debug(msg): + """Display a debug message + + Args: + msg; Message to display. + """ + _Output(4, msg) + +def UserOutput(msg): + """Display a message regardless of the current output level. + + This is used when the output was specifically requested by the user. + Args: + msg; Message to display. + """ + _Output(0, msg) + +def Init(_verbose=WARNING, stdout=sys.stdout): + """Initialize a new output object. + + Args: + verbose: Verbosity level (0-4). + stdout: File to use for stdout. + """ + global verbose, _progress, _color, _stdout, stdout_is_tty + + verbose = _verbose + _progress = '' # Our last progress message + _color = terminal.Color() + _stdout = stdout + + # TODO(sjg): Move this into Chromite libraries when we have them + stdout_is_tty = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty() + +def Uninit(): + ClearProgress() + +Init() |