Hi!

Reimplementing .processConflict() is on the todo list for too long now. The first patch removes pkgs from updates (self.up) to avoid errors when trying to update to an already skipped package (which is no longer found in the .pkgSack). The second patch is the new processConflict implementation which now get passed the conflicting package object. The method just calls .update on both packages and tries to be smart which to update first.

Comments?

Florian

Btw. One test case had to be adjusted as Yum is now capable of handling this situation properly.
>From 30ef4150dae034cb9fe6507eec15da7024040fdc Mon Sep 17 00:00:00 2001
From: Florian Festi <[EMAIL PROTECTED]>
Date: Mon, 14 Jan 2008 14:13:33 +0100
Subject: [PATCH] Deleted from updates (aka Depsolve.up)

---
 rpmUtils/updates.py |   45 +++++++++++++++++++++++++++++++++++++++++++--
 yum/__init__.py     |    2 ++
 2 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/rpmUtils/updates.py b/rpmUtils/updates.py
index b5ccc72..f348ae9 100644
--- a/rpmUtils/updates.py
+++ b/rpmUtils/updates.py
@@ -28,13 +28,15 @@ class Updates:
     """
 
     def __init__(self, instlist, availlist):
-        self.changeTup = [] # storage list tuple of updates or obsoletes
-                            # (oldpkg, newpkg, ['update'|'obsolete'])
 
         self.installed = instlist # list of installed pkgs (n, a, e, v, r)
         self.available = availlist # list of available pkgs (n, a, e, v, r)
+
         self.rawobsoletes = {} # dict of obsoleting package->[what it obsoletes]
         self._obsoletes_by_name = None
+        self.obsoleted_dict = {}  # obsoleted pkgtup -> [ obsoleting pkgtups ]
+        self.obsoleting_dict = {} # obsoleting pkgtup -> [ obsoleted pkgtups ]
+
         self.exactarch = 1 # don't change archs by default
         self.exactarchlist = ['kernel', 'kernel-smp', 'glibc', 'kernel-hugemem',
                               'kernel-enterprise', 'kernel-bigmem', 'kernel-BOOT']
@@ -49,9 +51,48 @@ class Updates:
 
         # holder for our updates dict
         self.updatesdict = {}
+        self.updating_dict = {}
         #debug, ignore me
         self.debug = 0
 
+    def _delFromDict(self, dict_, keys, value):
+        for key in keys:
+            if not dict_.has_key(key):
+                continue
+            dict_[key] = filter(value.__ne__, dict_[key])
+            if not dict_[key]:
+                del dict_[key]
+
+    def _delFromNADict(self, dict_, pkgtup):
+        (n, a, e, v, r) = pkgtup
+        if dict_.has_key((n, a)):
+            dict_[(n, a)] = filter((e,v,r).__ne__, dict_[(n, a)])
+            if not dict_[(n, a)]:
+                del dict_[(n, a)]
+        if dict_.has_key((n, None)):
+            dict_[(n, None)] = filter((e,v,r).__ne__, dict_[(n, None)])
+            if not dict_[(n, None)]:
+                del dict_[(n, None)]
+
+    def delPackage(self, pkgtup):
+        """remove available pkgtup that is no longer available"""
+        if pkgtup not in self.available:
+            return
+        self.available.remove(pkgtup)
+        self._delFromNADict(self.availdict, pkgtup)
+
+        self._delFromDict(self.updating_dict, self.updatesdict.get(pkgtup, []), pkgtup)
+        self._delFromDict(self.updatesdict, self.updating_dict.get(pkgtup, []), pkgtup)
+
+        if self.rawobsoletes.has_key(pkgtup):
+            if self._obsoletes_by_name:
+                for name, flag, version in self.rawobsoletes[pkgtup]:
+                    self._delFromDict(self._obsoletes_by_name, [name], (flag, version, pkgtup))
+                del self.rawobsoletes[pkgtup]
+
+        self._delFromDict(self.obsoleted_dict, self.obsoleting_dict.get(pkgtup, []), pkgtup)
+        self._delFromDict(self.obsoleting_dict, self.obsoleted_dict.get(pkgtup, []), pkgtup)
+
     def debugprint(self, msg):
         if self.debug:
             print msg
diff --git a/yum/__init__.py b/yum/__init__.py
index 2d7c1b6..7491e8b 100644
--- a/yum/__init__.py
+++ b/yum/__init__.py
@@ -654,10 +654,12 @@ class YumBase(depsolve.Depsolve):
                         self._getPackagesToRemove(wpo, depTree, toRemove)
                         if not wpo.repoid == 'installed': # Only remove non installed packages from pkgSack
                             self.pkgSack.delPackage(wpo)
+                            self.up.delPackage(wpo.pkgtup)
                 else:
                     self._getPackagesToRemove(po, depTree, toRemove)
                     if not po.repoid == 'installed': # Only remove non installed packages from pkgSack
                         self.pkgSack.delPackage(po)
+                        self.up.delPackage(po.pkgtup)
             for po in toRemove:
                 skipped = self._skipFromTransaction(po)
                 for skip in skipped:
-- 
1.5.3.8

>From 2c278de0912e366baf3326e398821187cb3bd7c3 Mon Sep 17 00:00:00 2001
From: Florian Festi <[EMAIL PROTECTED]>
Date: Wed, 13 Feb 2008 16:26:11 +0100
Subject: [PATCH] New processConflict implementation

---
 test/depsolvetests.py |    7 +--
 yum/depsolve.py       |  110 +++++++++++++++----------------------------------
 2 files changed, 35 insertions(+), 82 deletions(-)

diff --git a/test/depsolvetests.py b/test/depsolvetests.py
index 011b8be..9012e82 100644
--- a/test/depsolvetests.py
+++ b/test/depsolvetests.py
@@ -474,11 +474,8 @@ class DepsolveTests(DepsolveTests):
         updatepo = FakePackage('zip', '2', '1', '0', 'i386')
         self.xsack.addPackage(updatepo)
 
-        if new_behavior:
-            self.assertEquals('ok', *self.resolveCode())
-            self.assertResult((po, updatepo))
-        else:
-            self.assertEquals('err', *self.resolveCode())
+        self.assertEquals('ok', *self.resolveCode())
+        self.assertResult((po, updatepo))
 
     def testUpdateForConflictProvide2(self):
         po = FakePackage('zsh', '1', '1', '0', 'i386')
diff --git a/yum/depsolve.py b/yum/depsolve.py
index 8c784eb..76a50a8 100644
--- a/yum/depsolve.py
+++ b/yum/depsolve.py
@@ -559,89 +559,45 @@ class Depsolve(object):
         return checkdeps, missingdep
 
 
-    def _processConflict(self, po, conflict):
+    def _processConflict(self, po, conflict, conflicting_po):
         """processes a Conflict dep from the resolveDeps() method"""
-                
-        CheckDeps = 0
-        conflicts = 0
+
+        CheckDeps = True
         errormsgs = []
-        
 
         needname, flags, needversion = conflict
         (name, arch, epoch, ver, rel) = po.pkgtup
-        requiringPo = po
 
         niceformatneed = rpmUtils.miscutils.formatRequire(needname, needversion, flags)
         if self.dsCallback: self.dsCallback.procConflict(name, niceformatneed)
-        
-        # we should try to update out of the dep, if possible        
-        # see which side of the conflict is installed and which is in the transaction Set
-        needmode = self.tsInfo.getMode(name=needname)
-        confmode = self.tsInfo.getMode(name=name, ver=ver, rel=rel)
-        if confmode is None:
-            confname = name
-        elif needmode is None:
-            confname = needname
-        else:
-            confname = name
-            
-        po = None        
-
-        uplist = self.up.getUpdatesList(name=confname)
-        
-        conflict_packages = self.rpmdb.searchNevra(name=confname)
-        if conflict_packages:
-            confpkg = conflict_packages[0] # take the first one, probably the only one
-                
-
-            # if there's an update for the reqpkg, then update it
-            if len(uplist) > 0:
-                if confpkg.name not in self.conf.exactarchlist:
-                    try:
-                        pkgs = self.pkgSack.returnNewestByName(confpkg.name)
-                        archs = {}
-                        for pkg in pkgs:
-                            archs[pkg.arch] = pkg
-                        a = rpmUtils.arch.getBestArchFromList(archs.keys())
-                        po = archs[a]                        
-                    except Errors.PackageSackError:
-                        self.verbose_logger.log(logginglevels.DEBUG_4, _("unable to find newer package for %s") %(confpkg,))
-                        pkgs = []
-                        po = None
-                else:
-                    try:
-                        po = self.pkgSack.returnNewestByNameArch((confpkg.name,confpkg.arch))[0]
-                    except Errors.PackageSackError:
-                        self.verbose_logger.log(logginglevels.DEBUG_4, _("unable to find newer package for %s") %(confpkg))
-                        po = None
-                if po and po.pkgtup not in uplist:
-                    po = None
-
-        if po:
-            self.verbose_logger.log(logginglevels.DEBUG_2,
-                _('TSINFO: Updating %s to resolve conflict.'), po)
-            txmbr = self.tsInfo.addUpdate(po, confpkg)
-            txmbr.setAsDep(po=requiringPo)
-            txmbr.reason = "dep"
-            CheckDeps = 1
-            
-        else:
-            conf = rpmUtils.miscutils.formatRequire(needname, needversion, flags)
-            prob_pkg = "%s (%s)" % (requiringPo,requiringPo.repoid)
-            CheckDeps, conflicts = self._unresolveableConflict(conf, prob_pkg, errormsgs)
-            self.verbose_logger.log(logginglevels.DEBUG_1, _('%s conflicts: %s'),
-                prob_pkg, conf)
-            if conflicts:
-                self.po_with_problems.add((requiringPo,None,errormsgs[-1]))
-
-        return (CheckDeps, conflicts, errormsgs)
 
-    def _unresolveableConflict(self, conf, name, errors):
-        CheckDeps = 0
-        conflicts = 1
-        msg = _('%s conflicts with %s') % (name, conf)
-        errors.append(msg)
-        return CheckDeps, conflicts
+        length = len(self.tsInfo)
+        if flags & rpm.RPMSENSE_LESS:
+            self.update(name=conflicting_po.name)
+            txmbrs = self.tsInfo.getMembersWithState(conflicting_po.pkgtup, TS_REMOVE_STATES)
+            if len(self.tsInfo) != length and txmbrs:
+                return CheckDeps, errormsgs
+        elif flags & rpm.RPMSENSE_GREATER:
+            self.update(name=name)
+            txmbrs = self.tsInfo.getMembersWithState(po.pkgtup, TS_REMOVE_STATES)
+            if len(self.tsInfo) != length and txmbrs:
+                return CheckDeps, errormsgs
+
+        self.update(name=conflicting_po.name)
+        txmbrs = self.tsInfo.getMembersWithState(conflicting_po.pkgtup, TS_REMOVE_STATES)
+        if len(self.tsInfo) != length and txmbrs:
+            return CheckDeps, errormsgs
+        self.update(name=name)
+        txmbrs = self.tsInfo.getMembersWithState(po.pkgtup, TS_REMOVE_STATES)
+        if len(self.tsInfo) != length and txmbrs:
+            return CheckDeps, errormsgs
+
+        msg = '%s conflicts with %s' % (name, conflicting_po.name)
+        errormsgs.append(msg)
+        self.verbose_logger.log(logginglevels.DEBUG_1, msg)
+        CheckDeps = False
+        self.po_with_problems.add((po,None,errormsgs[-1]))
+        return CheckDeps, errormsgs
 
     def _undoDepInstalls(self):
         # clean up after ourselves in the case of failures
@@ -730,7 +686,7 @@ class Depsolve(object):
             if CheckInstalls:
                 CheckInstalls = False
                 for conflict in self._checkConflicts():
-                    (checkdep, conflict, errormsgs) = self._processConflict(*conflict)
+                    (checkdep, errormsgs) = self._processConflict(*conflict)
                     CheckDeps |= checkdep
                     errors += errormsgs
 
@@ -948,7 +904,7 @@ class Depsolve(object):
                 for conflicting_po in self.tsInfo.getNewProvides(r, f, v):
                     if conflicting_po.pkgtup[0] == po.pkgtup[0] and conflicting_po.pkgtup[2:] == po.pkgtup[2:]:
                         continue
-                    ret.append( (po, (r, flags[f], version_tuple_to_string(v))) )
+                    ret.append( (po, (r, flags[f], version_tuple_to_string(v)), conflicting_po) )
         for txmbr in self.tsInfo.getMembersWithState(output_states=TS_INSTALL_STATES):
             po = txmbr.po
             for conflict in txmbr.po.returnPrco('conflicts'):
@@ -956,7 +912,7 @@ class Depsolve(object):
                 for conflicting_po in self.tsInfo.getProvides(r, f, v):
                     if conflicting_po.pkgtup[0] == po.pkgtup[0] and conflicting_po.pkgtup[2:] == po.pkgtup[2:]:
                         continue
-                    ret.append( (po, (r, flags[f], version_tuple_to_string(v))) )
+                    ret.append( (po, (r, flags[f], version_tuple_to_string(v)), conflicting_po) )
         return ret
 
 
-- 
1.5.3.8

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

Reply via email to