[yum-git] test/transactiontests.py yum/depsolve.py yum/__init__.py yum/transactioninfo.py

Florian Festi ffesti at linux.duke.edu
Wed Jun 4 07:38:12 UTC 2008


 test/transactiontests.py |    8 +--
 yum/__init__.py          |  110 +++++++++++++++++++++++------------------------
 yum/depsolve.py          |   27 +++++------
 yum/transactioninfo.py   |   91 +++++++++++++++++++++++++++++---------
 4 files changed, 142 insertions(+), 94 deletions(-)

New commits:
commit ca31584860a944d18095e9684e3672e4ee6e52d8
Author: Florian Festi <ffesti at redhat.com>
Date:   Mon Feb 18 13:33:47 2008 +0100

    Introduce AdditionResult class
    to report back the results of TransactionInfo.add*

diff --git a/test/transactiontests.py b/test/transactiontests.py
index 74a7666..724012f 100644
--- a/test/transactiontests.py
+++ b/test/transactiontests.py
@@ -48,7 +48,7 @@ class TransactionDataTests(unittest.TestCase):
         
     def testRemove(self):
         ''' test remove from transaction '''
-        txmbr = self.tsInfo.addInstall(self.foo1)
+        txmbr = self.tsInfo.addInstall(self.foo1).primary
         self.tsInfo.addInstall(self.bar2)
         self.tsInfo.remove(self.bar2.pkgtup)
         self.dumpTsInfo()
@@ -60,7 +60,7 @@ class TransactionDataTests(unittest.TestCase):
         txmbr2 = self.tsInfo.addUpdate(self.foogui2,self.foogui1)
         txmbr3 = self.tsInfo.getMembers(self.foogui1.pkgtup)[0]
         self.dumpTsInfo()
-        self.assertResult([txmbr1,txmbr2,txmbr3])
+        self.assertResult([txmbr1.primary,txmbr2.primary,txmbr3])
 
     def testGetFromTransaction(self):
         ''' test getting from Transaction '''
@@ -105,8 +105,8 @@ class TransactionDataTests(unittest.TestCase):
 
     def testAddUpdatesAndObsoletes(self):
         ''' test addUpdated,addObsoleted'''
-        txmbr1 = self.tsInfo.addUpdated(self.foo1,self.foo2)
-        txmbr2 = self.tsInfo.addObsoleted(self.bar1,self.bar2)
+        txmbr1 = self.tsInfo.addUpdated(self.foo1,self.foo2).primary
+        txmbr2 = self.tsInfo.addObsoleted(self.bar1,self.bar2).primary
         self.dumpTsInfo()
         self.assertResult([txmbr1,txmbr2])
         txmbr = self.tsInfo.getMembersWithState(output_states=[TS_UPDATED])[0]
diff --git a/yum/__init__.py b/yum/__init__.py
index 35b44d4..e26cd1d 100644
--- a/yum/__init__.py
+++ b/yum/__init__.py
@@ -2184,19 +2184,22 @@ class YumBase(depsolve.Depsolve):
         #  - better error handling/reporting
 
 
-        tx_return = []
+        result = transactioninfo.AdditionResult()
         for po in pkgs:
             if self.tsInfo.exists(pkgtup=po.pkgtup):
-                if self.tsInfo.getMembersWithState(po.pkgtup, TS_INSTALL_STATES):
+                found = False
+                for txmbr in self.tsInfo.getMembersWithState(po.pkgtup, TS_INSTALL_STATES):
+                    found = True
                     self.verbose_logger.log(logginglevels.DEBUG_1,
                         _('Package: %s  - already in transaction set'), po)
-                    tx_return.extend(self.tsInfo.getMembers(pkgtup=po.pkgtup))
+                    result.addMember(txmbr) # XXX ERASE members???
+                if found:
                     continue
             
             # make sure this shouldn't be passed to update:
             if self.up.updating_dict.has_key(po.pkgtup):
-                txmbrs = self.update(po=po)
-                tx_return.extend(txmbrs)
+                res = self.update(po=po)
+                result.add(res)
                 continue
             
             # make sure it's not already installed
@@ -2210,8 +2213,8 @@ class YumBase(depsolve.Depsolve):
             if self.rpmdb.contains(name=po.name, arch=po.arch) and not self.allowedMultipleInstalls(po):
                 if not self.tsInfo.getMembersWithState(po.pkgtup, TS_REMOVE_STATES):
                     self.verbose_logger.warning(_('Package matching %s already installed. Checking for update.'), po)            
-                    txmbrs = self.update(po=po)
-                    tx_return.extend(txmbrs)
+                    res = self.update(po=po)
+                    result.add(res)
                     continue
 
             # make sure we're not installing a package which is obsoleted by something
@@ -2222,13 +2225,13 @@ class YumBase(depsolve.Depsolve):
                 obsoleting_pkg = self.getPackageObject(obsoleting)
                 self.verbose_logger.warning(_('Package %s is obsoleted by %s, trying to install %s instead'),
                     po.name, obsoleting_pkg.name, obsoleting_pkg)               
-                self.install(po=obsoleting_pkg)
+                self.install(po=obsoleting_pkg) # XXX result???
                 continue
                 
-            txmbr = self.tsInfo.addInstall(po)
-            tx_return.append(txmbr)
+            res = self.tsInfo.addInstall(po)
+            result.add(res)
         
-        return tx_return
+        return result
 
     
     def update(self, po=None, requiringPo=None, **kwargs):
@@ -2251,17 +2254,17 @@ class YumBase(depsolve.Depsolve):
         else:
             obsoletes = []
 
-        tx_return = []
+        result = transactioninfo.AdditionResult()
         if not po and not kwargs: # update everything (the easy case)
             self.verbose_logger.log(logginglevels.DEBUG_2, _('Updating Everything'))
             for (obsoleting, installed) in obsoletes:
                 obsoleting_pkg = self.getPackageObject(obsoleting)
                 installed_pkg =  self.rpmdb.searchPkgTuple(installed)[0]
-                txmbr = self.tsInfo.addObsoleting(obsoleting_pkg, installed_pkg)
-                self.tsInfo.addObsoleted(installed_pkg, obsoleting_pkg)
+                res = self.tsInfo.addObsoleting(obsoleting_pkg, installed_pkg)
+                self.tsInfo.addObsoleted(installed_pkg, obsoleting_pkg) # XXX result???
                 if requiringPo:
-                    txmbr.setAsDep(requiringPo)
-                tx_return.append(txmbr)
+                    res.primary.setAsDep(requiringPo)
+                result.add(res)
                 
             for (new, old) in updates:
                 if self.tsInfo.isObsoleted(pkgtup=old):
@@ -2270,12 +2273,12 @@ class YumBase(depsolve.Depsolve):
                 else:
                     updating_pkg = self.getPackageObject(new)
                     updated_pkg = self.rpmdb.searchPkgTuple(old)[0]
-                    txmbr = self.tsInfo.addUpdate(updating_pkg, updated_pkg)
+                    res = self.tsInfo.addUpdate(updating_pkg, updated_pkg)
                     if requiringPo:
-                        txmbr.setAsDep(requiringPo)
-                    tx_return.append(txmbr)
+                        res.primary.setAsDep(requiringPo)
+                    result.add(res)
             
-            return tx_return
+            return result
 
         # complications
         # the user has given us something - either a package object to be
@@ -2343,23 +2346,23 @@ class YumBase(depsolve.Depsolve):
                 for obsoleting in self.up.obsoleted_dict.get(installed_pkg.pkgtup, []):
                     obsoleting_pkg = self.getPackageObject(obsoleting)
                     # FIXME check for what might be in there here
-                    txmbr = self.tsInfo.addObsoleting(obsoleting_pkg, installed_pkg)
-                    self.tsInfo.addObsoleted(installed_pkg, obsoleting_pkg)
+                    res = self.tsInfo.addObsoleting(obsoleting_pkg, installed_pkg)
+                    self.tsInfo.addObsoleted(installed_pkg, obsoleting_pkg) # XXX result???
                     if requiringPo:
-                        txmbr.setAsDep(requiringPo)
-                    tx_return.append(txmbr)
+                        res.primary.setAsDep(requiringPo)
+                    result.add(res)
             for available_pkg in availpkgs:
                 for obsoleted in self.up.obsoleting_dict.get(available_pkg.pkgtup, []):
                     obsoleted_pkg = self.getInstalledPackageObject(obsoleted)
-                    txmbr = self.tsInfo.addObsoleting(available_pkg, obsoleted_pkg)
+                    res = self.tsInfo.addObsoleting(available_pkg, obsoleted_pkg)
                     if requiringPo:
-                        txmbr.setAsDep(requiringPo)
-                    tx_return.append(txmbr)
+                        res.primary.setAsDep(requiringPo)
+                    result.add(res)
                     if self.tsInfo.isObsoleted(obsoleted):
                         self.verbose_logger.log(logginglevels.DEBUG_2, _('Package is already obsoleted: %s.%s %s:%s-%s'), obsoleted)
                     else:
-                        txmbr = self.tsInfo.addObsoleted(obsoleted_pkg, available_pkg)
-                        tx_return.append(txmbr)
+                        res = self.tsInfo.addObsoleted(obsoleted_pkg, available_pkg)
+                        result.add(res)
 
         for installed_pkg in instpkgs:
             for updating in self.up.updatesdict.get(installed_pkg.pkgtup, []):
@@ -2368,10 +2371,10 @@ class YumBase(depsolve.Depsolve):
                     self.verbose_logger.log(logginglevels.DEBUG_2, _('Not Updating Package that is already obsoleted: %s.%s %s:%s-%s'), 
                                             installed_pkg.pkgtup)                                               
                 else:
-                    txmbr = self.tsInfo.addUpdate(updating_pkg, installed_pkg)
+                    res = self.tsInfo.addUpdate(updating_pkg, installed_pkg)
                     if requiringPo:
-                        txmbr.setAsDep(requiringPo)
-                    tx_return.append(txmbr)
+                        res.primary.setAsDep(requiringPo)
+                    result.add(res)
                         
                         
         for available_pkg in availpkgs:
@@ -2385,10 +2388,10 @@ class YumBase(depsolve.Depsolve):
                 
                 else:
                     updated_pkg =  self.rpmdb.searchPkgTuple(updated)[0]
-                    txmbr = self.tsInfo.addUpdate(available_pkg, updated_pkg)
+                    res = self.tsInfo.addUpdate(available_pkg, updated_pkg)
                     if requiringPo:
-                        txmbr.setAsDep(requiringPo)
-                    tx_return.append(txmbr)
+                        res.primary.setAsDep(requiringPo)
+                    result.add(res)
                     
             # check to see if the pkg we want to install is not _quite_ the newest
             # one but still technically an update over what is installed.
@@ -2399,13 +2402,12 @@ class YumBase(depsolve.Depsolve):
             pot_updated = self.rpmdb.searchNevra(name=available_pkg.name, arch=available_pkg.arch)
             for ipkg in pot_updated:
                 if ipkg.EVR < available_pkg.EVR:
-                    txmbr = self.tsInfo.addUpdate(available_pkg, ipkg)
+                    res = self.tsInfo.addUpdate(available_pkg, ipkg)
                     if requiringPo:
-                        txmbr.setAsDep(requiringPo)
-                    tx_return.append(txmbr)
-                                                     
+                        res.primary.setAsDep(requiringPo)
+                    result.add(res)
 
-        return tx_return
+        return result
         
         
     def remove(self, po=None, **kwargs):
@@ -2417,7 +2419,7 @@ class YumBase(depsolve.Depsolve):
         if not po and not kwargs:
             raise Errors.RemoveError, 'Nothing specified to remove'
         
-        tx_return = []
+        result = transactioninfo.AdditionResult()
         pkgs = []
         
         
@@ -2456,10 +2458,10 @@ class YumBase(depsolve.Depsolve):
                     self.logger.warning(_("No package matched to remove"))
 
         for po in pkgs:
-            txmbr = self.tsInfo.addErase(po)
-            tx_return.append(txmbr)
+            res = self.tsInfo.addErase(po)
+            result.add(res)
         
-        return tx_return
+        return result
 
     def installLocal(self, pkg, po=None, updateonly=False):
         """
@@ -2478,7 +2480,7 @@ class YumBase(depsolve.Depsolve):
         # check if it can be installed or updated based on nevra versus rpmdb
         # don't import the repos until we absolutely need them for depsolving
 
-        tx_return = []
+        result = transactioninfo.AdditionResult()
         installpkgs = []
         updatepkgs = []
         donothingpkgs = []
@@ -2488,7 +2490,7 @@ class YumBase(depsolve.Depsolve):
                 po = YumLocalPackage(ts=self.rpmdb.readOnlyTS(), filename=pkg)
             except Errors.MiscError:
                 self.logger.critical(_('Cannot open file: %s. Skipping.'), pkg)
-                return tx_return
+                return result
             self.verbose_logger.log(logginglevels.INFO_2,
                 _('Examining %s: %s'), po.localpath, po)
 
@@ -2498,7 +2500,7 @@ class YumBase(depsolve.Depsolve):
         if len(installedByKey) == 0: # nothing installed by that name
             if updateonly:
                 self.logger.warning(_('Package %s not installed, cannot update it. Run yum install to install it instead.'), po.name)
-                return tx_return
+                return result
             else:
                 installpkgs.append(po)
 
@@ -2531,26 +2533,25 @@ class YumBase(depsolve.Depsolve):
 
         if po in toexc:
            self.verbose_logger.debug(_('Excluding %s'), po)
-           return tx_return
+           return result
 
         for po in installpkgs:
             self.verbose_logger.log(logginglevels.INFO_2,
                 _('Marking %s to be installed'), po.localpath)
             self.localPackages.append(po)
-            tx_return.extend(self.install(po=po))
+            result.add(self.install(po=po))
 
         for (po, oldpo) in updatepkgs:
             self.verbose_logger.log(logginglevels.INFO_2,
                 _('Marking %s as an update to %s'), po.localpath, oldpo)
             self.localPackages.append(po)
-            txmbr = self.tsInfo.addUpdate(po, oldpo)
-            tx_return.append(txmbr)
+            result.add(self.tsInfo.addUpdate(po, oldpo))
 
         for po in donothingpkgs:
             self.verbose_logger.log(logginglevels.INFO_2,
                 _('%s: does not update installed package.'), po.localpath)
 
-        return tx_return
+        return result
 
     def reinstall(self, po=None, **kwargs):
         """Setup the problem filters to allow a reinstall to work, then
@@ -2563,9 +2564,8 @@ class YumBase(depsolve.Depsolve):
         if rpm.RPMPROB_FILTER_REPLACEOLDFILES not in self.tsInfo.probFilterFlags:
             self.tsInfo.probFilterFlags.append(rpm.RPMPROB_FILTER_REPLACEOLDFILES)
 
-        tx_mbrs = []
-        tx_mbrs.extend(self.remove(po, **kwargs))
-        if not tx_mbrs:
+        result = self.remove(po, **kwargs)
+        if not tx_mbrs.transactionChanged():
             raise Errors.ReinstallError, _("Problem in reinstall: no package matched to remove")
         templen = len(tx_mbrs)
         # this is a reinstall, so if we can't reinstall exactly what we uninstalled
diff --git a/yum/depsolve.py b/yum/depsolve.py
index ead17b7..c738fe3 100644
--- a/yum/depsolve.py
+++ b/yum/depsolve.py
@@ -282,8 +282,8 @@ class Depsolve(object):
         if remove_txmbr and remove_txmbr.ts_state=='e' and not (remove_txmbr.obsoleted_by or remove_txmbr.updated_by):
             self.verbose_logger.log(logginglevels.DEBUG_2, _('TSINFO: %s package requiring %s marked as erase'),
                 requiringPo, needname)
-            txmbr = self.tsInfo.addErase(requiringPo)
-            txmbr.setAsDep(po=remove_txmbr.po)
+            res = self.tsInfo.addErase(requiringPo)
+            res.primary.setAsDep(po=remove_txmbr.po)
             checkdeps = 1
             return checkdeps, missingdep
 
@@ -383,13 +383,12 @@ class Depsolve(object):
 
         # try updating the already install pkgs
         for pkg in provSack.returnNewestByName():
-            results = self.update(requiringPo=requiringPo, name=pkg.name,
-                                  epoch=pkg.epoch, version=pkg.version,
-                                  rel=pkg.rel)
-            for txmbr in results:
-                if pkg == txmbr.po:
-                    checkdeps = True
-                    return checkdeps, missingdep
+            result = self.update(requiringPo=requiringPo, name=pkg.name,
+                                 epoch=pkg.epoch, version=pkg.version,
+                                 rel=pkg.rel)
+            if result.transactionChanged():
+                checkdeps = True
+                return checkdeps, missingdep
 
         # find out which arch of the ones we can choose from is closest
         # to the arch of the requesting pkg
@@ -421,14 +420,14 @@ class Depsolve(object):
             self.verbose_logger.debug(_('TSINFO: Marking %s as update for %s') %(best,
                 requiringPo))
             # FIXME: we should probably handle updating multiple packages...
-            txmbr = self.tsInfo.addUpdate(best, inst[0])
-            txmbr.setAsDep(po=requiringPo)
-            txmbr.reason = "dep"
+            res = self.tsInfo.addUpdate(best, inst[0])
+            res.primary.setAsDep(po=requiringPo)
+            res.primary.reason = "dep"
         else:
             self.verbose_logger.debug(_('TSINFO: Marking %s as install for %s'), best,
                 requiringPo)
-            txmbr = self.tsInfo.addInstall(best)
-            txmbr.setAsDep(po=requiringPo)
+            res = self.tsInfo.addInstall(best)
+            res.primary.setAsDep(po=requiringPo)
 
             # if we had other packages with this name.arch that we found
             # before, they're not going to be installed anymore, so we
diff --git a/yum/transactioninfo.py b/yum/transactioninfo.py
index b7fdd1e..a6336c7 100644
--- a/yum/transactioninfo.py
+++ b/yum/transactioninfo.py
@@ -172,9 +172,11 @@ class TransactionData:
         
     def add(self, txmember):
         """add a package to the transaction"""
+        result = AdditionResult()
         
         for oldpo in txmember.updates:
-            self.addUpdated(oldpo, txmember.po)
+            res = self.addUpdated(oldpo, txmember.po)
+            result.add(res)
 
         if not self.pkgdict.has_key(txmember.pkgtup):
             self.pkgdict[txmember.pkgtup] = []
@@ -183,7 +185,11 @@ class TransactionData:
             for member in self.pkgdict[txmember.pkgtup]:
                 if member.ts_state == txmember.ts_state:
                     self.debugprint("Package in same mode, skipping.")
-                    return
+                    result.setPrimaryMember(member, new=False)
+                    return result
+
+        result.setPrimaryMember(txmember)
+
         self.pkgdict[txmember.pkgtup].append(txmember)
         self._namedict.setdefault(txmember.name, []).append(txmember)
         self.changed = True
@@ -196,15 +202,18 @@ class TransactionData:
             for po in self.conditionals[txmember.name]:
                 if self.rpmdb.contains(po=po):
                     continue
-                condtxmbr = self.addInstall(po)
-                condtxmbr.setAsDep(po=txmember.po)
+                res = self.addInstall(po, True)
+                result.addConditionals(res)
+                res.primary.setAsDep(po=txmember.po)
+
         self._unresolvedMembers.add(txmember)
+        return result
 
     def remove(self, pkgtup):
         """remove a package from the transaction"""
         if not self.pkgdict.has_key(pkgtup):
             self.debugprint("Package: %s not in ts" %(pkgtup,))
-            return
+            return []
         for txmbr in self.pkgdict[pkgtup]:
             txmbr.po.state = None
             if self._isLocalPackage(txmbr):
@@ -214,10 +223,12 @@ class TransactionData:
             self._namedict[txmbr.name].remove(txmbr)
             self._unresolvedMembers.add(txmbr)
         
+        result = self.pkgdict[pkgtup]
         del self.pkgdict[pkgtup]
         if not self._namedict[pkgtup[0]]:
             del self._namedict[pkgtup[0]]
-        self.changed = True        
+        self.changed = True
+        return result
     
     def exists(self, pkgtup):
         """tells if the pkg is in the class"""
@@ -310,8 +321,7 @@ class TransactionData:
         txmbr.po.state = TS_INSTALL        
         txmbr.ts_state = 'u'
         txmbr.reason = 'user'
-        self.add(txmbr)
-        return txmbr
+        return self.add(txmbr)
 
     def addTrueInstall(self, po):
         """adds a package as an install
@@ -323,9 +333,7 @@ class TransactionData:
         txmbr.po.state = TS_INSTALL        
         txmbr.ts_state = 'i'
         txmbr.reason = 'user'
-        self.add(txmbr)
-        return txmbr
-    
+        return self.add(txmbr)
 
     def addErase(self, po):
         """adds a package as an erasure
@@ -336,8 +344,7 @@ class TransactionData:
         txmbr.output_state = TS_ERASE
         txmbr.po.state = TS_INSTALL
         txmbr.ts_state = 'e'
-        self.add(txmbr)
-        return txmbr
+        return self.add(txmbr)
 
     def addUpdate(self, po, oldpo=None):
         """adds a package as an update
@@ -355,8 +362,7 @@ class TransactionData:
             txmbr.relatedto.append((oldpo, 'updates'))
             txmbr.updates.append(oldpo)
             
-        self.add(txmbr)
-        return txmbr
+        return self.add(txmbr)
 
     def addUpdated(self, po, updating_po):
         """adds a package as being updated by another pkg
@@ -369,8 +375,7 @@ class TransactionData:
         txmbr.ts_state = None
         txmbr.relatedto.append((updating_po, 'updatedby'))
         txmbr.updated_by.append(updating_po)
-        self.add(txmbr)
-        return txmbr
+        return self.add(txmbr)
 
     def addObsoleting(self, po, oldpo):
         """adds a package as an obsolete over another pkg
@@ -383,8 +388,7 @@ class TransactionData:
         txmbr.ts_state = 'u'
         txmbr.relatedto.append((oldpo, 'obsoletes'))
         txmbr.obsoletes.append(oldpo)
-        self.add(txmbr)
-        return txmbr
+        return self.add(txmbr)
 
     def addObsoleted(self, po, obsoleting_po):
         """adds a package as being obsoleted by another pkg
@@ -397,8 +401,7 @@ class TransactionData:
         txmbr.ts_state = None
         txmbr.relatedto.append((obsoleting_po, 'obsoletedby'))
         txmbr.obsoleted_by.append(obsoleting_po)
-        self.add(txmbr)
-        return txmbr
+        return self.add(txmbr)
 
 
     def setDatabases(self, rpmdb, pkgSack):
@@ -515,6 +518,52 @@ class SortableTransactionData(TransactionData):
         self._sorted.reverse()
         return self._sorted
 
+class AdditionResult:
+    def __init__(self, txmbr=None):
+        self.primary = txmbr
+        self.new = set()
+        self.all = set()
+        self.new_conditionals = set()
+        self.all_conditionals = set()
+
+    def setPrimaryMember(self, txmbr, new=True):
+        if self.primary:
+            raise ValueError, "Primary already set"
+        self.primary = txmbr
+        self.all.add(txmbr)
+        if new:
+            self.new.add(txmbr)
+
+    def addNewMember(self, txmbr):
+        self.all.add(txmbr)
+        self.new.add(txmbr)
+
+    def addMember(self, txmbr):
+        self.all.add(txmbr)
+
+    def addNewConditional(self, txmbr):
+        self.new_conditionals.add(txmbr)
+        self.all_conditionals.add(txmbr)
+
+    def addConditional(self, txmbr):
+        self.all_conditionals.add(txmbr)
+
+    def removeMember(self, txmbr):
+        self.new.discard(txmbr)
+        self.all.discard(txmbr)
+        self.new_conditionals.discard(txmbr)
+        self.all_conditionals.discard(txmbr)
+        if self.primary is txmbr:
+            self.primary = None
+
+    def add(self, other):
+        for attr in ('new', 'all', 'new_conditionals', 'all_conditionals'):
+            getattr(self, attr).update(getattr(other, attr))
+
+    def transactionChanged(self):
+        return bool(self.new) | bool(self.new_conditionals)
+
+
 class TransactionMember:
     """Class to describe a Transaction Member (a pkg to be installed/
        updated/erased)."""



More information about the Yum-cvs-commits mailing list