I have created at patch to add skip-broken functionality to YumBase.
I works the following way:1. I have added some code to the depsolver to store packages with problems in the self.po_with_problems dict. So we have the po with problems when the depsolving is completed. 2. I have added a extra 'skip-broken' parameter to YumBase.buildTransaction to control if we want to skip packages with problem from the transaction. (default = no)
3. if the skip-broken parameter is True, then we do
While "There is problems"
Remove the packages from the transaction
Depsolve
It will remove packages with problem from the transaction and desolve
again until all problems are gone or the transaction is empty.
I have attached a test script and some test packages to provoke dep errors. foo-1.0-1.fc8.noarch.rpm: Requires: foobar > 1.1.0 ( This should fails always ) bar-1.0-1.fc8.noarch.rpm: Requires: bar ( This should fails if foo is not in the transaction ) # sudo python test-skipbroken.py Will do normal depsolvning and report depsolve error. # sudo python test-skipbroken.py --skip-broken Will first remove the foo packages, because nothing provides foobar. Then bar will fail because there is no longer anything providing foo. bar will be removed and the transaction will complete. to test how it look when all packages is removed, just comment out txmbr = yb.install(name='BackupPC') and run # sudo python test-skipbroken.py --skip-broken Tim
>From f9915c21c8d47bcae11c98d42fa8347b37f66084 Mon Sep 17 00:00:00 2001
From: Tim Lauridsen <[EMAIL PROTECTED]>
Date: Thu, 15 Nov 2007 10:57:20 +0100
Subject: [PATCH] Added skip-broken packages functionality to YumBase
---
yum/__init__.py | 22 +++++++++++++++++++++-
yum/depsolve.py | 19 +++++++++++++++++++
2 files changed, 40 insertions(+), 1 deletions(-)
diff --git a/yum/__init__.py b/yum/__init__.py
index 69e233b..19c72d7 100644
--- a/yum/__init__.py
+++ b/yum/__init__.py
@@ -567,7 +567,7 @@ class YumBase(depsolve.Depsolve):
self.verbose_logger.log(logginglevels.INFO_2, msg)
self.repos.populateSack(mdtype='filelists')
- def buildTransaction(self):
+ def buildTransaction(self,skip_broken=False):
"""go through the packages in the transaction set, find them in the
packageSack or rpmdb, and pack up the ts accordingly"""
self.plugins.run('preresolve')
@@ -577,9 +577,29 @@ class YumBase(depsolve.Depsolve):
if self.tsInfo.changed:
(rescode, restring) = self.resolveDeps()
+
+ # if depsolve failed and skipbroken is enabled
+ # The remove the broken packages from the transactions and
+ # Try another depsolve
+ if skip_broken and rescode==1:
+ rescode, restring = self._skipPackagesWithProblems()
+
return rescode, restring
+ def _skipPackagesWithProblems(self):
+ ''' Remove the packages with depsolve errors and depsolve again '''
+ rescode = 1
+ # Keep removing packages & Depsolve until all errors is gone
+ # or the transaction is empty
+ while len(self.po_with_problems.keys()) > 0 and rescode == 1:
+ for po in self.po_with_problems:
+ self.verbose_logger.debug("skipping %s because of depsolving problems" % po)
+ self.tsInfo.remove(po.pkgtup)
+ rescode, restring = self.resolveDeps()
+ return rescode, restring
+
+
def runTransaction(self, cb):
"""takes an rpm callback object, performs the transaction"""
diff --git a/yum/depsolve.py b/yum/depsolve.py
index 0455b09..5b8838c 100644
--- a/yum/depsolve.py
+++ b/yum/depsolve.py
@@ -639,6 +639,9 @@ class Depsolve(object):
CheckDeps, conflicts = self._unresolveableConflict(conf, name, errormsgs)
self.verbose_logger.log(logginglevels.DEBUG_1, '%s conflicts: %s',
name, conf)
+ if conflicts:
+ if not po in self.po_with_problems.keys():
+ self.po_with_problems[po] = 1
return (CheckDeps, conflicts, errormsgs)
@@ -692,6 +695,8 @@ class Depsolve(object):
# reset what we've seen as things may have changed between calls
# to resolveDeps (rh#242368, rh#308321)
self._dcobj.already_seen = {}
+ self.po_with_problems = {}
+
CheckDeps = True
CheckRemoves = False
@@ -720,6 +725,12 @@ class Depsolve(object):
CheckRemoves = False
for po, dep in self._checkFileRequires():
(checkdep, missing, errormsgs) = self._processReq(po, dep)
+ # If there is missing deps then add the po to
+ # problem dictionary
+ if missing:
+ if not po in self.po_with_problems.keys():
+ self.po_with_problems[po] = 1
+
CheckDeps |= checkdep
errors += errormsgs
@@ -759,6 +770,8 @@ class Depsolve(object):
self.tsInfo.changed = False
if len(errors) > 0:
errors = unique(errors)
+ for po in self.po_with_problems:
+ self.verbose_logger.debug("%s has depsolving problems" % po)
return (1, errors)
if len(self.tsInfo) > 0:
@@ -793,6 +806,12 @@ class Depsolve(object):
missing_in_pkg = False
for po, dep in thisneeds:
(checkdep, missing, errormsgs) = self._processReq(po, dep)
+ # If there is missing deps then add the po to
+ # problem dictionary
+ if missing:
+ if not po in self.po_with_problems.keys():
+ self.po_with_problems[po] = 1
+
CheckDeps |= checkdep
errors += errormsgs
missing_in_pkg |= missing
--
1.5.3.4
import yum
import copy
import sys
skip = False
if len(sys.argv) > 1:
if sys.argv[1] == '--skip-broken':
skip = True
yb = yum.YumBase()
yb.doConfigSetup(debuglevel=3)
# Add local packages with dep problems to transaction
# This package requires foobar > 1.1.0, there cat be resolved
po = yum.packages.YumLocalPackage(ts=yb.rpmdb.readOnlyTS(), filename='foo-1.0-1.fc8.noarch.rpm')
yb.install(po)
# This package requires foo, there cat only be resolved, if foo is in the transaction
po = yum.packages.YumLocalPackage(ts=yb.rpmdb.readOnlyTS(), filename='bar-1.0-1.fc8.noarch.rpm')
yb.install(po)
## add a package from the repo
txmbr = yb.install(name='BackupPC') # Deps needed
# Do Depsolve
rc,msgs = yb.buildTransaction(skip_broken=skip)
if rc == 2:
print "Packages in Transaction"
for txmbr in yb.tsInfo:
print " --> %s" % txmbr
else:
print "\n".join(msgs)
bar-1.0-1.fc8.noarch.rpm
Description: application/rpm
foo-1.0-1.fc8.noarch.rpm
Description: application/rpm
_______________________________________________ Yum-devel mailing list [email protected] https://lists.dulug.duke.edu/mailman/listinfo/yum-devel
