Florian Festi wrote:
Hi Tim!
Some more skip broken code:
Fix the endless loop (sorry, test case is still broken). Code is not
that beautiful - feel free to adjust your personal taste ;)=
Tim Lauridsen wrote:
Added some patch to fix issues with skip-broken and updates.
If we remove an update, we have to remove the cleanup txmbr of the
package being updated.
There is also a patch to fix the testcases.
Add support for obsoletes.
Have fun
Florian
------------------------------------------------------------------------
_______________________________________________
Yum-devel mailing list
[email protected]
https://lists.dulug.duke.edu/mailman/listinfo/yum-devel
Thanks,
To not loose track of all the changes, i have created a patch with all
the changes against the current yum HEAD.
Tim
>From c05d5fb5edb030680cd5236c21e5f06145f378c8 Mon Sep 17 00:00:00 2001
From: Tim Lauridsen <[EMAIL PROTECTED]>
Date: Wed, 28 Nov 2007 11:21:44 +0100
Subject: [PATCH] Added current skip-broken code
---
test/skipbroken-tests.py | 137 ++++++++++++++++++++++++++++++++++++++++++++++
test/testbase.py | 1 +
yum/__init__.py | 40 +++++++++++++
yum/config.py | 1 +
yum/depsolve.py | 16 ++++-
5 files changed, 192 insertions(+), 3 deletions(-)
create mode 100644 test/skipbroken-tests.py
diff --git a/test/skipbroken-tests.py b/test/skipbroken-tests.py
new file mode 100644
index 0000000..a6a55b5
--- /dev/null
+++ b/test/skipbroken-tests.py
@@ -0,0 +1,137 @@
+import unittest
+from testbase import *
+
+class SkipBrokenTests(DepsolveTests):
+
+ def testMissingReqNoSkip(self):
+ ''' bar fails because foobar is not provided '''
+ po = FakePackage('foo', '1', '0', '0', 'noarch')
+ po.addRequires('bar', None, (None,None,None))
+ self.tsInfo.addInstall(po)
+
+ xpo = FakePackage('bar', '1', '0', '0', 'noarch')
+ xpo.addRequires('foobar', None, (None,None,None))
+ self.xsack.addPackage(xpo)
+ self.assertEquals('err', *self.resolveCode(skip=False))
+ self.assertResult((po,xpo))
+
+ def testMissingReqSkip(self):
+ ''' foo + bar is skipped, because foobar is not provided '''
+ po = FakePackage('foo', '1', '0', '0', 'noarch')
+ po.addRequires('bar', None, (None,None,None))
+ self.tsInfo.addInstall(po)
+
+ xpo = FakePackage('bar', '1', '0', '0', 'noarch')
+ xpo.addRequires('foobar', None, (None,None,None))
+ self.xsack.addPackage(xpo)
+ self.assertEquals('empty', *self.resolveCode(skip=True))
+ self.assertResult([])
+
+ def testDepWithMissingReqSkip(self):
+ ''' foo + foobar is skipped because barfoo is not provided
+ bar stays in the transaction
+ '''
+ po1 = FakePackage('foo', '1', '0', '0', 'noarch')
+ po1.addRequires('foobar', None, (None,None,None))
+ self.tsInfo.addInstall(po1)
+
+ po2 = FakePackage('bar', '1', '0', '0', 'noarch')
+ self.tsInfo.addInstall(po2)
+
+ xpo1 = FakePackage('foobar', '1', '0', '0', 'noarch')
+ xpo1.addRequires('barfoo', None, (None,None,None))
+ self.xsack.addPackage(xpo1)
+ self.assertEquals('ok', *self.resolveCode(skip=True))
+ self.assertResult([po2])
+
+ def testUpdateOldRequired(self):
+ po1 = FakePackage('foo', '1', '0', '0', 'noarch')
+ po2 = FakePackage('foo', '2', '0', '0', 'noarch')
+
+ ipo = FakePackage('foo-tools', '2.5', '0', '0', 'noarch')
+ ipo.addRequires('foo', 'EQ', ('0', '1', '0'))
+
+ self.rpmdb.addPackage(po1)
+ self.tsInfo.addUpdate(po2, oldpo=po1)
+ self.rpmdb.addPackage(ipo)
+
+ self.assertEquals('ok', *self.resolveCode(skip=True))
+ self.assertResult([ipo, po2])
+
+ def testUpdateRequireOld(self):
+ po1 = FakePackage('foo', '1', '0', '0', 'noarch')
+ po1.addRequires('foo-tools', 'EQ', ('0', '1', '0'))
+ po2 = FakePackage('foo', '2', '0', '0', 'noarch')
+ po2.addRequires('foo-tools', 'EQ', ('0', '2', '0'))
+
+ ipo = FakePackage('foo-tools', '1', '0', '0', 'noarch')
+
+ self.rpmdb.addPackage(po1)
+ self.tsInfo.addUpdate(po2, oldpo=po1)
+ self.rpmdb.addPackage(ipo)
+
+ self.assertEquals('empty', *self.resolveCode(skip=True))
+ self.assertResult([ipo, po1])
+
+ def testUpdateRequireBoth(self):
+ po1 = FakePackage('foo', '1', '0', '0', 'noarch')
+ po1.addRequires('foo-tools', 'EQ', ('0', '1', '0'))
+ po2 = FakePackage('foo', '2', '0', '0', 'noarch')
+ po2.addRequires('foo-tools', 'EQ', ('0', '2', '0'))
+
+ ipo = FakePackage('foo-tools', '1', '0', '0', 'noarch')
+ por = FakePackage('foo-gui', '1', '0', '0', 'noarch')
+ por.addRequires('foo', 'EQ', ('0', '2', '0'))
+
+ self.rpmdb.addPackage(po1)
+ self.tsInfo.addUpdate(po2, oldpo=po1)
+ self.rpmdb.addPackage(ipo)
+ self.tsInfo.addInstall(por)
+
+ self.assertEquals('empty', *self.resolveCode(skip=True))
+ self.assertResult([ipo, po1])
+
+ def testLoop(self):
+ ipo = FakePackage('foo', '1', '0', '0', 'noarch')
+ ipo2 = FakePackage('foo-tools', '1', '0', '0', 'noarch')
+ ipo2.addRequires('foo', 'EQ', ('0', '1', '0'))
+
+ self.rpmdb.addPackage(ipo)
+ self.rpmdb.addPackage(ipo2)
+
+ self.tsInfo.addErase(ipo)
+ self.assertEquals('ok', *self.resolveCode(skip=True))
+
+
+ def resolveCode(self,skip = False):
+ solver = YumBase()
+ solver.conf = FakeConf()
+ solver.conf.skip_broken = skip
+ solver.tsInfo = solver._tsInfo = self.tsInfo
+ solver.rpmdb = self.rpmdb
+ solver.pkgSack = self.xsack
+
+ for po in self.rpmdb:
+ po.repoid = po.repo.id = "installed"
+ for po in self.xsack:
+ po.repoid = po.repo.id = "TestRepository"
+ for txmbr in solver.tsInfo:
+ if txmbr.ts_state in ('u', 'i'):
+ txmbr.po.repoid = txmbr.po.repo.id = "TestRepository"
+ else:
+ txmbr.po.repoid = txmbr.po.repo.id = "installed"
+
+ res, msg = solver.buildTransaction()
+ #self.tsInfo = copy.copy(solver._tsInfo)
+ return self.res[res], msg
+
+
+
+
+def suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(SkipBrokenTests))
+ return suite
+
+if __name__ == "__main__":
+ unittest.main(defaultTest="suite")
diff --git a/test/testbase.py b/test/testbase.py
index 3c90636..e22dcc2 100644
--- a/test/testbase.py
+++ b/test/testbase.py
@@ -35,6 +35,7 @@ class FakeConf(object):
self.installroot = '/'
self.tsflags = []
self.installonly_limit = 0
+ self.skip_broken = False
class FakeRepo(object):
diff --git a/yum/__init__.py b/yum/__init__.py
index f9618bc..0076dc2 100644
--- a/yum/__init__.py
+++ b/yum/__init__.py
@@ -580,9 +580,49 @@ 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 self.conf.skip_broken and rescode==1:
+ rescode, restring = self._skipPackagesWithProblems(rescode, restring)
return rescode, restring
+ def _skipPackagesWithProblems(self, rescode, restring):
+ ''' Remove the packages with depsolve errors and depsolve again '''
+ # Keep removing packages & Depsolve until all errors is gone
+ # or the transaction is empty
+ while len(self.po_with_problems) > 0 and rescode == 1:
+ length = len(self.tsInfo)
+ for po in self.po_with_problems:
+ self.verbose_logger.debug("skipping %s because of depsolving problems" % po)
+ self._skipDeps(po)
+ self.tsInfo.remove(po.pkgtup)
+ # self.pkgSack.delPackage(po)
+ if len(self.tsInfo) == length:
+ break
+ rescode, restring = self.resolveDeps()
+ return rescode, restring
+
+ def _skipDeps(self, pkg):
+ '''
+ Remove the deps for a package with dep problem
+ from the Transaction
+ '''
+ removelist = []
+ for txmbr in self.tsInfo.getMembers(pkg.pkgtup):
+ for dep in txmbr.depends_on:
+ self.verbose_logger.debug("skipping dependency %s because of depsolving problems" % dep)
+ self.tsInfo.remove(dep.pkgtup)
+ # Move pkg being updated from transaction.
+ if txmbr.ts_state == 'u':
+ for upd in (txmbr.updates + txmbr.obsoletes):
+ self.verbose_logger.debug("skipping update %s because of depsolving problems in %s" % (upd,pkg))
+ self.tsInfo.remove(upd.pkgtup)
+
+
+
def runTransaction(self, cb):
"""takes an rpm callback object, performs the transaction"""
diff --git a/yum/config.py b/yum/config.py
index 174118d..f1fee12 100644
--- a/yum/config.py
+++ b/yum/config.py
@@ -555,6 +555,7 @@ class YumConf(StartupConf):
mirrorlist_expire = IntOption(86400) # time in seconds (1 day)
rpm_check_debug = BoolOption(True)
disable_excludes = ListOption()
+ skip_broken = BoolOption(False)
_reposlist = []
diff --git a/yum/depsolve.py b/yum/depsolve.py
index e026db2..15cc447 100644
--- a/yum/depsolve.py
+++ b/yum/depsolve.py
@@ -258,6 +258,11 @@ class Depsolve(object):
CheckDeps, missingdep = self._requiringFromTransaction(po, requirement, errormsgs)
else:
CheckDeps, missingdep = self._requiringFromInstalled(po, requirement, errormsgs)
+
+ # Check packages with problems
+ if missingdep:
+ self.po_with_problems.add(po)
+
return (CheckDeps, missingdep, errormsgs)
def _requiringFromInstalled(self, requiringPo, requirement, errorlist):
@@ -559,13 +564,13 @@ class Depsolve(object):
name))
# FIXME: we should probably handle updating multiple packages...
txmbr = self.tsInfo.addUpdate(best, inst[0])
- txmbr.setAsDep()
+ txmbr.setAsDep(requiringPo)
txmbr.reason = "dep"
else:
self.verbose_logger.debug('TSINFO: Marking %s as install for %s', best,
name)
txmbr = self.tsInfo.addInstall(best)
- txmbr.setAsDep()
+ txmbr.setAsDep(requiringPo)
# if we had other packages with this name.arch that we found
# before, they're not going to be installed anymore, so we
@@ -648,7 +653,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:
+ self.po_with_problems.add(po)
+
return (CheckDeps, conflicts, errormsgs)
def _unresolveableConflict(self, conf, name, errors):
@@ -702,6 +709,7 @@ class Depsolve(object):
# reset what we've seen as things may have changed between calls
# to resolveDeps (rh#242368, rh#308321)
self._dcobj.reset()
+ self.po_with_problems = set()
CheckDeps = True
CheckRemoves = False
@@ -769,6 +777,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:
--
1.5.3.4
_______________________________________________
Yum-devel mailing list
[email protected]
https://lists.dulug.duke.edu/mailman/listinfo/yum-devel