summaryrefslogtreecommitdiff
path: root/tools/patman
diff options
context:
space:
mode:
Diffstat (limited to 'tools/patman')
-rw-r--r--tools/patman/checkpatch.py3
-rw-r--r--tools/patman/command.py5
-rw-r--r--tools/patman/gitutil.py3
-rw-r--r--tools/patman/tools.py120
-rw-r--r--tools/patman/tout.py166
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()