Hi!

Curiosity killed the cat and the current _requiringFromTransaction(). I thought that it should be possible to replace the _requiringFromTransaction() code by calls to .install() and .update. It turns out that this can be done quite simple although those methods need a little upgrade.

Although all test cases pass this patch most likely needs a more testing and checking. Especially cases where there are several possible packages available are likely to have changed their results.

Have fun

Florian
>From c26b15b6e7d77ecaf485e799258d3a060b0bfb41 Mon Sep 17 00:00:00 2001
From: Florian Festi <[EMAIL PROTECTED]>
Date: Thu, 14 Feb 2008 16:45:28 +0100
Subject: [PATCH] Use update() and install() to implement _requiringFromTransaction()

---
 yum/__init__.py |   55 +++++++++++------
 yum/depsolve.py |  178 ++++++------------------------------------------------
 2 files changed, 56 insertions(+), 177 deletions(-)

diff --git a/yum/__init__.py b/yum/__init__.py
index 2d7c1b6..cdba688 100644
--- a/yum/__init__.py
+++ b/yum/__init__.py
@@ -2018,7 +2018,7 @@ class YumBase(depsolve.Depsolve):
         return returnlist
 
 
-    def install(self, po=None, **kwargs):
+    def install(self, po=None, requiringPo=None, **kwargs):
         """try to mark for install the item specified. Uses provided package 
            object, if available. If not it uses the kwargs and gets the best
            packages from the keyword options provided 
@@ -2060,6 +2060,9 @@ class YumBase(depsolve.Depsolve):
                         if mypkgs:
                             pkgs.extend(self.bestPackagesFromList(mypkgs))
                         
+            elif kwargs.has_key('pkgs'):
+                was_pattern = True
+                pkgs = kwargs['pkgs']
             else:
                 nevra_dict = self._nevra_kwarg_parse(kwargs)
 
@@ -2077,21 +2080,26 @@ class YumBase(depsolve.Depsolve):
                 if rpmUtils.arch.isMultiLibArch():
                     if was_pattern or not nevra_dict['arch']: # and only if they
                                                               # they didn't specify an arch
-                       if self.conf.multilib_policy == 'best':
-                           pkgs_by_name = {}
-                           use = []
-                           not_added = []
-                           for pkg in pkgs:
-                               if pkg.arch in rpmUtils.arch.legitMultiArchesInSameLib():
-                                   pkgs_by_name[pkg.name] = 1    
-                                   use.append(pkg)  
-                               else:
-                                   not_added.append(pkg)
-                           for pkg in not_added:
-                               if not pkg.name in pkgs_by_name:
-                                   use.append(pkg)
+
+                        if self.conf.multilib_policy == 'best' or requiringPo:
+                            pkgs_by_name = {}
+                            use = []
+                            not_added = []
+                            if requiringPo:
+                                legitArches = set(rpmUtils.arch.legitMultiArchesInSameLib(requiringPo.arch))
+                            else:
+                                legitArches = set(rpmUtils.arch.legitMultiArchesInSameLib())
+                            for pkg in pkgs:
+                                if pkg.arch in legitArches:
+                                    pkgs_by_name[pkg.name] = 1
+                                    use.append(pkg)
+                                else:
+                                    not_added.append(pkg)
+                            for pkg in not_added:
+                                if not pkg.name in pkgs_by_name:
+                                    use.append(pkg)
                            
-                           pkgs = use
+                            pkgs = use
                            
                 pkgSack = ListPackageSack(pkgs)
                 pkgs = pkgSack.returnNewestByName()
@@ -2129,11 +2137,16 @@ class YumBase(depsolve.Depsolve):
                     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)
+            updated = False
+            for updated_pkg in self.up.updating_dict.get(po.pkgtup, []):
+                if not self.tsInfo.getMembersWithState(updated_pkg, TS_REMOVE_STATES):
+                    txmbrs = self.update(po=po)
+                    tx_return.extend(txmbrs)
+                    updated = True
+                    break
+            if updated:
                 continue
-            
+
             # make sure it's not already installed
             if self.rpmdb.contains(po=po):
                 if not self.tsInfo.getMembersWithState(po.pkgtup, TS_REMOVE_STATES):
@@ -2151,6 +2164,8 @@ class YumBase(depsolve.Depsolve):
                 continue
                 
             txmbr = self.tsInfo.addInstall(po)
+            if requiringPo:
+                txmbr.setAsDep(requiringPo)
             tx_return.append(txmbr)
         
         return tx_return
@@ -2218,6 +2233,8 @@ class YumBase(depsolve.Depsolve):
                 instpkgs.extend(e)
                 instpkgs.extend(m)
                 
+            elif kwargs.has_key('pkgs'):
+                availpkgs = kwargs['pkgs']
             else: # we have kwargs, sort them out.
                 nevra_dict = self._nevra_kwarg_parse(kwargs)
 
diff --git a/yum/depsolve.py b/yum/depsolve.py
index 8c784eb..47a69fa 100644
--- a/yum/depsolve.py
+++ b/yum/depsolve.py
@@ -392,173 +392,35 @@ class Depsolve(object):
         """processes the dependency resolution for a dep where requiring 
            package is in the transaction set"""
         
-        (name, arch, epoch, version, release) = requiringPo.pkgtup
-        (needname, needflags, needversion) = requirement
+        needname, needflags, needversion = requirement
         checkdeps = 0
         missingdep = 0
-        upgraded = {}
-
-        #~ - if it's not available from some repository:
-        #~     - mark as unresolveable.
-        #
-        #~ - if it's available from some repo:
-        #~    - if there is an another version of the package currently installed then
-        #        - if the other version is marked in the transaction set
-        #           - if it's marked as erase
-        #              - mark the dep as unresolveable
-         
-        #           - if it's marked as update or install
-        #              - check if the version for this requirement:
-        #                  - if it is higher 
-        #                       - mark this version to be updated/installed
-        #                       - remove the other version from the transaction set
-        #                       - tell the transaction set to be rebuilt
-        #                  - if it is lower
-        #                       - mark the dep as unresolveable
-        #                   - if they are the same
-        #                       - be confused but continue
-
-        provSack = self.whatProvides(needname, needflags, needversion)
-
-        # get rid of things that are already in the rpmdb - b/c it's pointless to use them here
-
-        for pkg in provSack.returnPackages():
-            if pkg.pkgtup in self.rpmdb.simplePkgList(): # is it already installed?
-                self.verbose_logger.log(logginglevels.DEBUG_2, _('%s is in providing packages but it is already installed, removing.'), pkg)
-                provSack.delPackage(pkg)
-                continue
-
-            # we need to check to see, if we have anything similar to it (name-wise)
-            # installed or in the ts, and this isn't a package that allows multiple installs
-            # then if it's newer, fine - continue on, if not, then we're unresolveable
-            # cite it and exit
-
-            tspkgs = []
-            if not self.allowedMultipleInstalls(pkg):
-                # from ts
-                tspkgs = self.tsInfo.matchNaevr(name=pkg.name, arch=pkg.arch)
-                for tspkg in tspkgs:
-                    if tspkg.po.EVR > pkg.EVR:
-                        msg = _('Potential resolving package %s has newer instance in ts.') % pkg
-                        self.verbose_logger.log(logginglevels.DEBUG_2, msg)
-                        provSack.delPackage(pkg)
-                        continue
-                    elif tspkg.po.EVR < pkg.EVR:
-                        upgraded.setdefault(pkg.pkgtup, []).append(tspkg.pkgtup)
-                
-                # from rpmdb
-                dbpkgs = self.rpmdb.searchNevra(name=pkg.name, arch=pkg.arch)
-                for dbpkg in dbpkgs:
-                    if dbpkg.EVR > pkg.EVR:
-                        msg = _('Potential resolving package %s has newer instance installed.') % pkg
-                        self.verbose_logger.log(logginglevels.DEBUG_2, msg)
-                        provSack.delPackage(pkg)
-                        continue
 
-        if len(provSack) == 0: # unresolveable
-            missingdep = 1
-            prob_pkg = "%s (%s)" % (requiringPo,requiringPo.repoid)
-            msg = _('Missing Dependency: %s is needed by package %s') % \
-            (rpmUtils.miscutils.formatRequire(needname, needversion, needflags),
-                                                                   prob_pkg)
-            errorlist.append(msg)
-            return checkdeps, missingdep
-        
-        # iterate the provSack briefly, if we find the package is already in the 
-        # tsInfo then just skip this run
-        for pkg in provSack.returnPackages():
-            (n,a,e,v,r) = pkg.pkgtup
-            pkgmode = self.tsInfo.getMode(name=n, arch=a, epoch=e, ver=v, rel=r)
-            if pkgmode in ['i', 'u']:
-                self.verbose_logger.log(logginglevels.DEBUG_2,
-                    _('%s already in ts, skipping this one'), pkg)
-                # FIXME: Remove this line, if it is not needed ?
-                # checkdeps = 1
-                return checkdeps, missingdep
-        
-
-        # find the best one 
-
-        # try updating the already install pkgs
+        pkgs = self.whatProvides(needname, needflags, needversion).returnPackages()
         length = len(self.tsInfo)
-        for pkg in provSack.returnNewestByName():
-            self.update(requiringPo=requiringPo, name=pkg.name, epoch=pkg.epoch, version=pkg.version, rel=pkg.rel)
-            if len(self.tsInfo) != length:
-                checkdeps = True
+        if pkgs:
+            txmbrs = self.update(requiringPo=requiringPo, pkgs=pkgs)
+            if length < len(self.tsInfo):
+                self.verbose_logger.debug(_('TSINFO: Marking %s as update for %s') %
+                                          (txmbrs[0].po, requiringPo))
+                checkdeps = 1
+                return checkdeps, missingdep
+            txmbrs = self.install(requiringPo=requiringPo, pkgs=pkgs)
+            if length < len(self.tsInfo):
+                self.verbose_logger.debug(_('TSINFO: Marking %s as install for %s'),
+                                          txmbrs[0].po, requiringPo)
+                checkdeps = 1
                 return checkdeps, missingdep
 
-        # find out which arch of the ones we can choose from is closest
-        # to the arch of the requesting pkg
-        thisarch = requiringPo.arch
-        newest = provSack.returnNewestByNameArch()
-        if len(newest) > 1: # there's no way this can be zero
-            best = newest[0]
-            for po in newest[1:]:
-                if thisarch != 'noarch':
-                    best_dist = archDifference(thisarch, best.arch)
-                    if isMultiLibArch(): # only go to the next one if we're multilib - i686 can satisfy i386 deps
-                        if best_dist == 0: # can't really use best's arch anyway...
-                            best = po # just try the next one - can't be much worse
-                            continue
-                
-                    po_dist = archDifference(thisarch, po.arch)
-                    if po_dist > 0 and best_dist > po_dist:
-                        best = po
-                        continue
-                        
-                    if best_dist == po_dist:
-                        if len(po.name) < len(best.name):
-                            best=po
-                            continue
-                            
-                elif len(po.name) < len(best.name):
-                    best = po
-                elif len(po.name) == len(best.name):
-                    # compare arch
-                    arch = rpmUtils.arch.getBestArchFromList([po.arch, best.arch])
-                    if arch == po.arch:
-                        best = po
-        elif len(newest) == 1:
-            best = newest[0]
-        
-        
-        if self.rpmdb.contains(po=best): # is it already installed?
-            missingdep = 1
-            checkdeps = 0
-            prob_pkg = "%s (%s)" % (requiringPo,requiringPo.repoid)
-            msg = _('Missing Dependency: %s is needed by package %s') % (needname, prob_pkg)
-            errorlist.append(msg)
-            return checkdeps, missingdep
-        
-                
-            
-        # FIXME - why can't we look up in the transaction set for the requiringPkg
-        # and know what needs it that way and provide a more sensible dep structure in the txmbr
-        inst = self.rpmdb.searchNevra(name=best.name, arch=best.arch)
-        if len(inst) > 0: 
-            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"
-        else:
-            self.verbose_logger.debug(_('TSINFO: Marking %s as install for %s'), best,
-                requiringPo)
-            txmbr = self.tsInfo.addInstall(best)
-            txmbr.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
-            # should mark them to be re-checked
-            if upgraded.has_key(best.pkgtup):
-                map(lambda x: self.tsInfo.remove(x), upgraded[best.pkgtup])
-
-        checkdeps = 1
+        missingdep = 1
+        prob_pkg = "%s (%s)" % (requiringPo,requiringPo.repoid)
+        msg = _('Missing Dependency: %s is needed by package %s') % \
+            (rpmUtils.miscutils.formatRequire(needname, needversion, needflags),
+                                                                   prob_pkg)
+        errorlist.append(msg)
         
         return checkdeps, missingdep
 
-
     def _processConflict(self, po, conflict):
         """processes a Conflict dep from the resolveDeps() method"""
                 
-- 
1.5.3.8

_______________________________________________
Yum-devel mailing list
[email protected]
https://lists.dulug.duke.edu/mailman/listinfo/yum-devel

Reply via email to