On Fri, 2006-11-17 at 15:07 +0100, Tim Lauridsen wrote:
> It sound like a very good idea.
> 
> Maybe i would be an idea to have 2 files.
> transactions-all      : Contain all transaction to processed.
> transactions-done  : Contain all executed transaction.
> 
> 1. Before the transaction processing is started all transaction are 
> written to the transactions-all file.
> 2 . When a transaction is executed it is written to the transaction-done 
> file.
> 3. Delete both files when every transaction is executed.
> 
> If some thing breaks, we just have to compare the 2 files to find out 
> what need to be done.
> 

so this was from a while ago but see the attached patch that does this.

Things I don't like about this:

1. I feel like we're already passing a lot of stuff into the transaction
callback instantiation. Though we will also need a configuration
variable for the location to store these ts files.

2. obviously shoving the list of transaction elements is a bit hurky but
there's no other place other than RIGHT before the transaction runs that
we know it won't be messed with. If we passed the action ts into the
callback object we could built it up internally to the callback which
would be prettier. However, at some point we're dropping in most of the
sub-objects of YumBase() in there. This goes back to #1

if we have a callback instantiation that looks like:

cb = RPMTransaction(self.tsInfo, self.ts,  
       test=False, display=output.YumCliRPMCallBack,
       ts_file_dir=self.conf.yum_persist_dir)

it feels ugly. However that might be the only way to do it.

I'm open to suggestions on making this feel less 'bleah' and in general
improvements on the patch.


Thanks,
-sv

diff --git a/cli.py b/cli.py
index 683fb15..9622634 100644
--- a/cli.py
+++ b/cli.py
@@ -340,7 +340,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
         for feature in ['diskspacecheck']: # more to come, I'm sure
             tsConf[feature] = getattr(self.conf, feature)
         
-        testcb = RPMTransaction(self.tsInfo)
+        testcb = RPMTransaction(self.tsInfo, test=True)
         
         self.initActionTs()
         # save our dsCallback out
diff --git a/rpmUtils/transaction.py b/rpmUtils/transaction.py
index bb481e6..c9e979d 100644
--- a/rpmUtils/transaction.py
+++ b/rpmUtils/transaction.py
@@ -54,6 +54,16 @@ class TransactionWrapper:
             self.ts = None
             self.open = False
 
+    def _return_te_tuples(self):
+        te_tuples = []
+        for te in self:
+            epoch = te.E()
+            if epoch is None:
+                epoch = '0'
+            te_tuples.append((te.N(), te.A(), epoch, te.V(), te.R(), te.Type()))
+        return te_tuples
+        
+        
     def __getattr__(self, attr):
         if attr in self._methods:
             return self.getMethod(attr)
diff --git a/yum/__init__.py b/yum/__init__.py
index 80a9e52..6310740 100644
--- a/yum/__init__.py
+++ b/yum/__init__.py
@@ -566,14 +566,17 @@ class YumBase(depsolve.Depsolve):
         """takes an rpm callback object, performs the transaction"""
 
         self.plugins.run('pretrans')
-
+        # point of no return - shove the list of transaction elements 
+        # into the callback so we have it
+        cb.te_tuples = self.ts._return_te_tuples()
+        
         errors = self.ts.run(cb.callback, '')
         if errors:
             raise Errors.YumBaseError, errors
 
         if not self.conf.keepcache:
             self.cleanUsedHeadersPackages()
-
+        
         self.plugins.run('posttrans')
         
     def excludePackages(self, repo=None):
diff --git a/yum/rpmtrans.py b/yum/rpmtrans.py
index 1c1d1b2..49be1fa 100644
--- a/yum/rpmtrans.py
+++ b/yum/rpmtrans.py
@@ -19,6 +19,7 @@
 import rpm
 import os
 import sys
+import time
 import logging
 from yum.constants import *
 
@@ -87,6 +88,7 @@ class RPMBaseCallback:
 
         
     def errorlog(self, msg):
+        # FIXME this should probably dump to the filelog, too
         print >> sys.stderr, msg
 
     def filelog(self, package, action):
@@ -111,10 +113,10 @@ class SimpleCliCallBack(RPMBaseCallback):
         self.lastpackage = package
 
 class RPMTransaction:
-    def __init__(self, tsInfo, display=NoOutputCallBack):
+    def __init__(self, tsInfo, test=False, display=NoOutputCallBack):
         self.display = display()
         self.tsInfo = tsInfo
-
+        self.test = test
         self.filehandles = {}
         self.total_actions = 0
         self.total_installed = 0
@@ -123,7 +125,27 @@ class RPMTransaction:
         self.total_removed = 0
         self.logger = logging.getLogger('yum.filelogging.RPMInstallCallback')
         self.filelog = False
-
+    
+    def _manip_te_tuples(self):
+        # TEST TEST TEST REMOVE ME FIXME XXXX TEST TEST
+        # need a config variable to put this somewhere sensible
+        tsfn = '/tmp/ts-all.%s' % time.time()
+        fo = open(tsfn, 'w')
+        for (n,a,e,v,r,t) in self.te_tuples:
+            if t == 1:
+                te_type = 'install'
+            if t == 2:
+                te_type = 'erase'
+                
+            msg = "%s %s:%s-%s-%s.%s\n" % (te_type, e,n,v,r,a)
+            fo.write(msg)
+        
+        fo.close()
+        #TEST TEST TEST REMOVE ME
+        # this is mostly to deal with the erasure callback giving us crap to
+        # work with
+        self.remaining_te = self.te_tuples
+        
     def _dopkgtup(self, hdr):
         tmpepoch = hdr['epoch']
         if tmpepoch is None: epoch = '0'
@@ -136,6 +158,16 @@ class RPMTransaction:
           hdr['release'], hdr['arch'])
 
         return handle
+    
+    def tslog(self, msg):
+        
+        if not self.test:
+            if not hasattr(self, '_tslog'):
+                # FIXME - need a config location to put these files
+                te_fn = '/tmp/ts-done.%s' % time.time()
+                self._tslog = open(te_fn, 'w')
+            self._tslog.write(msg)
+            self._tslog.flush()
         
     def callback( self, what, bytes, total, h, user ):
         if what == rpm.RPMCALLBACK_TRANS_START:
@@ -171,11 +203,16 @@ class RPMTransaction:
     def _transStart(self, bytes, total, h):
         if bytes == 6:
             self.total_actions = total
-    
+            if self.test: return
+            # things to do for non-test
+            self._manip_te_tuples()
+
     def _transProgress(self, bytes, total, h):
         pass
+        
     def _transStop(self, bytes, total, h):
         pass
+
     def _instOpenFile(self, bytes, total, h):
         self.lastmsg = None
         hdr = None
@@ -190,6 +227,7 @@ class RPMTransaction:
             return fd
         else:
             self.display.errorlog("Error: No Header to INST_OPEN_FILE")
+            
     def _instCloseFile(self, bytes, total, h):
         hdr = None
         if h is not None:
@@ -197,11 +235,18 @@ class RPMTransaction:
             handle = self._makeHandle(hdr)
             os.close(self.filehandles[handle])
             fd = 0
-
+            if self.test: return
+            
             pkgtup = self._dopkgtup(hdr)
             txmbrs = self.tsInfo.getMembers(pkgtup=pkgtup)
             for txmbr in txmbrs:
                 self.display.filelog(txmbr.po, txmbr.output_state)
+                (n,a,e,v,r) = pkgtup
+                msg = 'install %s:%s-%s-%s.%s\n' % (e,n,v,r,a)
+                self.tslog(msg)
+                self.remaining_te.pop(0)
+                
+                
     
     def _instProgress(self, bytes, total, h):
         if h is not None:
@@ -221,7 +266,7 @@ class RPMTransaction:
                                 self.complete_actions, self.total_actions)
     def _unInstStart(self, bytes, total, h):
         pass
-
+        
     def _unInstProgress(self, bytes, total, h):
         pass
     
@@ -233,10 +278,23 @@ class RPMTransaction:
             action = TS_ERASE
         else:
             action = TS_UPDATED                    
-            
+        
         self.display.event(h, action, 100, 100, self.complete_actions,
                             self.total_actions)
-
+        
+        if self.test: return # and we're done
+        
+        (n,a,e,v,r,t) = self.remaining_te[0]
+        if t != 2:
+            print 'the hell? not an erasure?'
+        if n != h:
+            print 'the hell %s != %s' % (h, n)
+        
+        # hope springs eternal that this isn't wrong
+        msg = 'erase %s:%s-%s-%s.%s\n' % (e,n,v,r,a)
+        self.tslog(msg)
+        self.remaining_te.pop(0)
+        
     def _rePackageStart(self, bytes, total, h):
         pass
         
@@ -251,7 +309,8 @@ class RPMTransaction:
         pkgtup = self._dopkgtup(hdr)
         txmbrs = self.tsInfo.getMembers(pkgtup=pkgtup)
         for txmbr in txmbrs:
-            self.display.errorlog("Error in cpio payload of rpm package %s" % txmbr.po)
+            msg = "Error in cpio payload of rpm package %s" % txmbr.po
+            self.display.errorlog(msg)
             # FIXME - what else should we do here? raise a failure and abort?
     
     def _unpackError(self, bytes, total, h):
@@ -259,7 +318,8 @@ class RPMTransaction:
         pkgtup = self._dopkgtup(hdr)
         txmbrs = self.tsInfo.getMembers(pkgtup=pkgtup)
         for txmbr in txmbrs:
-            self.display.errorlog("Error unpacking rpm package %s" % txmbr.po)
+            msg = "Error unpacking rpm package %s" % txmbr.po
+            self.display.errorlog(msg)
             # FIXME - should we raise? I need a test case pkg to see what the
             # right behavior should be
                 
_______________________________________________
Yum-devel mailing list
[email protected]
https://lists.dulug.duke.edu/mailman/listinfo/yum-devel

Reply via email to