[Yum-devel] [PATCH] Add a simple "how many packages does this provider require" test.

James Antill james at and.org
Tue Apr 20 22:17:53 UTC 2010


 This only goes one level deep, in theory it can screw up where:

 pkgA => pkgX
   pkgX => pkgC
   pkgX => pkgD
   pkgX => pkgE

 pkgB => pkgY
 pkgB => pkgZ

...with this patch we'd pick "pkgA" because it had "less" requirements,
even though it actually requires 1 more thing. However, real world
result on F12:

% yum install @core @base gdm
[...]
Resolving: desktop-notification-daemon

 kdebase-runtime => 38 things
 xfce4-notifyd => 4 things
 notification-daemon => 1 thing

...all were "equal" before this patch, so we're left with "shortest
name".
---
 yum/depsolve.py |   40 +++++++++++++++++++++++++++++++++++++++-
 1 files changed, 39 insertions(+), 1 deletions(-)

diff --git a/yum/depsolve.py b/yum/depsolve.py
index a9e4d55..5eb2f92 100644
--- a/yum/depsolve.py
+++ b/yum/depsolve.py
@@ -859,7 +859,11 @@ class Depsolve(object):
             
             self.verbose_logger.log(logginglevels.DEBUG_2, _("looking for %s as a requirement of %s"), req, txmbr)
             provs = self.tsInfo.getProvides(*req)
-            if not provs:
+            #  The self provides should mostly be caught before here now, but
+            # at least config() crack still turns up, it's not that
+            # expensive to just do it, and we really don't want "false positive"
+            # requires for compare_providers().
+            if not provs and not txmbr.po.inPrcoRange('provides', req):
                 ret.append( (txmbr.po, self._prco_req2req(req)) )
                 continue
 
@@ -1228,6 +1232,7 @@ class Depsolve(object):
                     if res == po:
                         pkgresults[po] += 5
 
+            # End of O(N*N): for nextpo in pkgs:
             if _common_sourcerpm(po, reqpo):
                 self.verbose_logger.log(logginglevels.DEBUG_4,
                     _('common sourcerpm %s and %s' % (po, reqpo)))
@@ -1243,7 +1248,40 @@ class Depsolve(object):
                         _('common prefix of %s between %s and %s' % (cpl, po, reqpo)))
                 
                     pkgresults[po] += cpl*2
+
+        #  If we have more than one "best", see what would happen if we picked
+        # each package ... ie. what things do they require that _aren't_ already
+        # installed/to-be-installed. In theory this can screw up due to:
+        #   pkgA => requires pkgX
+        #   pkgB => requires pkgY, requires pkgZ
+        # ...but pkgX requires 666 other things. Going recursive is
+        # "non-trivial" though, python != prolog. This seems to do "better"
+        # from simple testing though.
+        bestnum = max(pkgresults.values())
+        rec_depsolve = {}
+        for po in pkgs:
+            if pkgresults[po] != bestnum:
+                continue
+            rec_depsolve[po] = 0
+        if len(rec_depsolve) > 1:
+            for po in rec_depsolve:
+                # FIXME: Can't str() this to something usable...
+                fake_txmbr = misc.GenericHolder()
+                fake_txmbr.po = po
+                fake_txmbr.name = po.name
+                fake_txmbr.updates = []
                 
+                rec_depsolve[po] = self._checkInstall(fake_txmbr)
+
+        #  We don't want to decide to use a "shortest first", if something else
+        # has told us to pick something else. But we want to pick between
+        # multiple "best" packages. So we just give a bump to those packages
+        # which are already winning.
+        bestnum = max(pkgresults.values())
+        for po in pkgs:
+            if pkgresults[po] != bestnum:
+                continue
+            pkgresults[po] += 1000
             pkgresults[po] += (len(po.name)*-1)
 
         bestorder = sorted(pkgresults.items(),
-- 
1.6.6.1



More information about the Yum-devel mailing list