From: Zac Medico Date: Sat, 15 Dec 2007 00:32:56 +0000 (-0000) Subject: Save QA output so that it can be conveniently displayed X-Git-Tag: v2.1.4~107 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=76b4466b91e7d1eec138ba6881b8cf32840d426e;p=portage.git Save QA output so that it can be conveniently displayed in $EDITOR while the user creates a commit message. Otherwise, the user would not be able to see this output once the editor has taken over the screen. Output is done through a formatter object where it is captured for later use. A file-like object that behaves something like the portage.output.colorize() function is used to transfor style identifiers from the formatter framework into actual console codes. (trunk r8925) svn path=/main/branches/2.1.2/; revision=8926 --- diff --git a/bin/repoman b/bin/repoman index ec3f99ceb..05ccecf19 100755 --- a/bin/repoman +++ b/bin/repoman @@ -8,6 +8,7 @@ # that last one is tricky because multiple profiles need to be checked. import errno +import formatter from itertools import izip import os import sys @@ -21,6 +22,11 @@ try: except ImportError: import pickle +try: + import cStringIO as StringIO +except ImportError: + import StringIO + if not hasattr(__builtins__, "set"): from sets import Set as set @@ -321,13 +327,15 @@ def editor_is_executable(editor): return find_binary(filename) is not None return os.access(filename, os.X_OK) and os.path.isfile(filename) -def get_commit_message_with_editor(editor): +def get_commit_message_with_editor(editor, message=None): """ Execute editor with a temporary file as it's argument and return the file content afterwards. @param editor: An EDITOR value from the environment @type: string + @param message: An iterable of lines to show in the editor. + @type: iterable @rtype: string or None @returns: A string on success or None if an error occurs. """ @@ -337,6 +345,10 @@ def get_commit_message_with_editor(editor): os.write(fd, "\n# Please enter the commit message " + \ "for your changes.\n# (Comment lines starting " + \ "with '#' will not be included)\n") + if message: + os.write(fd, "#\n") + for line in message: + os.write(fd, "#" + line) os.close(fd) retval = os.system(editor + " '%s'" % filename) if not (os.WIFEXITED(retval) and os.WEXITSTATUS(retval) == os.EX_OK): @@ -371,6 +383,58 @@ def get_commit_message_with_stdin(): commitmessage = "".join(commitmessage) return commitmessage +class ConsoleStyleFile(object): + """ + A file-like object that behaves something like the + portage.output.colorize() function. Style identifiers + passed in via the new_styles() method will be used to + apply console codes to output. + """ + from output import codes as _codes + def __init__(self, f): + self._file = f + self._styles = None + self.write_listener = None + + def new_styles(self, styles): + self._styles = styles + + def write(self, s): + if self._styles: + for style in self._styles: + self._file.write(self._codes[style]) + self._file.write(s) + self._file.write(self._codes["reset"]) + else: + self._file.write(s) + if self.write_listener: + self.write_listener.write(s) + + def writelines(self, lines): + for s in lines: + self.write(s) + + def flush(self): + self._file.flush() + + def close(self): + self._file.close() + +class StyleWriter(formatter.DumbWriter): + """ + This is just a DumbWriter with a hook in the new_styles() method + that passes a styles tuple as a single argument to a callable + style_listener attribute. + """ + def __init__(self, **kwargs): + formatter.DumbWriter.__init__(self, **kwargs) + self.style_listener = None + + def new_styles(self, styles): + formatter.DumbWriter.new_styles(self, styles) + if self.style_listener: + self.style_listener(styles) + def last(): try: #Retrieve and unpickle stats and fails from saved files @@ -1784,6 +1848,19 @@ dofail=0 dowarn=0 #dofull will be set if we should print a "repoman full" informational message dofull=0 + +# Save QA output so that it can be conveniently displayed +# in $EDITOR while the user creates a commit message. +# Otherwise, the user would not be able to see this output +# once the editor has taken over the screen. +qa_output = StringIO.StringIO() +style_file = ConsoleStyleFile(sys.stdout) +style_file.write_listener = qa_output +console_writer = StyleWriter(file=style_file, maxcol=9999) +console_writer.style_listener = style_file.new_styles + +f = formatter.AbstractFormatter(console_writer) + for x in qacats: if not isCvs and x.find("notadded") != -1: stats[x] = 0 @@ -1793,23 +1870,36 @@ for x in qacats: dofail=1 else: continue - print " "+x.ljust(30), + f.add_literal_data(" "+x.ljust(30)) if stats[x]==0: - print green(`stats[x]`) + f.push_style("green") + f.add_literal_data(str(stats[x])) + f.pop_style() + f.add_line_break() continue elif x in qawarnings: - print yellow(`stats[x]`) + f.push_style("yellow") else: - print red(`stats[x]`) + f.push_style("red") + f.add_literal_data(str(stats[x])) + f.pop_style() + f.add_line_break() if mymode!="full": if stats[x]<12: for y in fails[x]: - print " "+y + f.add_literal_data(" "+y) + f.add_line_break() else: dofull=1 else: for y in fails[x]: - print " "+y + f.add_literal_data(" "+y) + f.add_line_break() + +style_file.flush() +del console_writer, f, style_file +qa_output = qa_output.getvalue() +qa_output = qa_output.splitlines(True) def grouplist(mylist,seperator="/"): """(list,seperator="/") -- Takes a list of elements; groups them into @@ -1975,12 +2065,8 @@ else: try: editor = os.environ.get("EDITOR") if editor and editor_is_executable(editor): - # Prompt the user before letting the editor - # take over the screen so there is an - # opportunity to review any QA warnings. - print "Press \"Enter\" to launch the editor for a commit message, or Ctrl-c to abort." - sys.stdin.readline() - commitmessage = get_commit_message_with_editor(editor) + commitmessage = get_commit_message_with_editor( + editor, message=qa_output) else: commitmessage = get_commit_message_with_stdin() except KeyboardInterrupt: