With the new transaction handling stuff, we can actually start to get to
where grabbing the output of scriptlets is pretty doable so that it can
be more easily consumed by tools sitting on top of yum.  

anaconda has been redirecting the bits to a file roughly forever (and
thus, that's the API that rpm exposes).  So we can use a pipe with only
minimal pain.  This adds a new scriptout() method that callbacks can
implement to get the output on a per-package basis.  I've made it so the
command-line can have the same behavior it's always had.  Graphical
callers can then grab to show the errors later.

Thoughts?

Jeremy
diff --git a/output.py b/output.py
index 0f5eb5a..a6f001f 100644
--- a/output.py
+++ b/output.py
@@ -495,6 +495,11 @@ class YumCliRPMCallBack(RPMBaseCallback):
                 self.lastmsg = msg
             if te_current == te_total:
                 print " "
+
+    def scriptout(self, package, msgs):
+        if msgs:
+            sys.stdout.write(msgs)
+            sys.stdout.flush()
         
     def _makefmt(self, percent, ts_current, ts_total, progress = True):
         l = len(str(ts_total))
diff --git a/yum/rpmtrans.py b/yum/rpmtrans.py
index f77400e..4804141 100644
--- a/yum/rpmtrans.py
+++ b/yum/rpmtrans.py
@@ -18,6 +18,7 @@
 
 import rpm
 import os
+import fcntl
 import time
 import logging
 import types
@@ -42,6 +43,12 @@ class NoOutputCallBack:
         # this is where a progress bar would be called
         
         pass
+
+    def scriptout(self, package, msgs):
+        """package is the package.  msgs is the messages that were
+        output (if any)."""
+        pass
+
     def errorlog(self, msg):
         """takes a simple error msg string"""
         
@@ -87,7 +94,11 @@ class RPMBaseCallback:
         """
         raise NotImplementedError()
 
-        
+    def scriptout(self, package, msgs):
+        """package is the package.  msgs is the messages that were
+        output (if any)."""
+        pass
+
     def errorlog(self, msg):
         # FIXME this should probably dump to the filelog, too
         print >> sys.stderr, msg
@@ -113,6 +124,10 @@ class SimpleCliCallBack(RPMBaseCallback):
         self.lastmsg = msg
         self.lastpackage = package
 
+    def scriptout(self, package, msgs):
+        if msgs:
+            print msgs,
+
 class RPMTransaction:
     def __init__(self, base, test=False, display=NoOutputCallBack):
         if not callable(display):
@@ -130,7 +145,44 @@ class RPMTransaction:
         self.total_removed = 0
         self.logger = logging.getLogger('yum.filelogging.RPMInstallCallback')
         self.filelog = False
-    
+
+        self._setupOutputLogging()
+
+    def _setupOutputLogging(self):
+        # UGLY... set up the transaction to record output from scriptlets
+        (r, w) = os.pipe()
+        # need fd objects, and read should be non-blocking
+        self._readpipe = os.fdopen(r, 'r')
+        fcntl.fcntl(self._readpipe.fileno(), fcntl.F_SETFL,
+                    fcntl.fcntl(self._readpipe.fileno(),
+                                fcntl.F_GETFL) | os.O_NONBLOCK)
+        self._writepipe = os.fdopen(w, 'w')
+        self.base.ts.ts.scriptFd = self._writepipe.fileno()
+        rpm.setVerbosity(rpm.RPMLOG_INFO)
+        rpm.setLogFile(self._writepipe)
+
+    def _shutdownOutputLogging(self):
+        # reset rpm bits from reording output
+        rpm.setVerbosity(rpm.RPMLOG_NOTICE)
+        rpm.setLogFile(sys.stderr)
+        try:
+            del self.base.ts
+        except:
+            pass
+        try:
+            self._writepipe.close()
+        except:
+            pass
+
+    def _scriptOutput(self):
+        try:
+            out = self._readpipe.read()
+            return out
+        except IOError:
+            pass
+
+    def __del__(self):
+        self._shutdownOutputLogging()
         
     def _dopkgtup(self, hdr):
         tmpepoch = hdr['epoch']
@@ -318,6 +370,7 @@ class RPMTransaction:
             txmbrs = self.base.tsInfo.getMembers(pkgtup=pkgtup)
             for txmbr in txmbrs:
                 self.display.filelog(txmbr.po, txmbr.output_state)
+                self.display.scriptout(txmbr.po, self._scriptOutput())
                 self.ts_done(txmbr.po, txmbr.output_state)
                 
                 
@@ -355,6 +408,7 @@ class RPMTransaction:
         
         self.display.event(h, action, 100, 100, self.complete_actions,
                             self.total_actions)
+        self.display.scriptout(h, self._scriptOutput())
         
         if self.test: return # and we're done
         self.ts_done(h, action)
_______________________________________________
Yum-devel mailing list
[email protected]
https://lists.dulug.duke.edu/mailman/listinfo/yum-devel

Reply via email to