Sadly, smart is not deterministic so the same build can go down multiple different pathways. We'd expect to see the same warnings however depending on the pathway taken, it may or may not warn, particularly with Recommends since they're optional. For example, where a Recommended package is available but has Conflicts, we'd expect to see an warning that we couldn't install it. Some code paths silently hide this (its a LOCKED_CONFLICT). We add printing of warnings for this case. Also, if there are two compatible feeds available (e.g. i586 and core2_32), this changes the code path from direct _install() to _pending() since there are multiple providers. This patch adds warning handling to _pending() so we don't hit hard failures there. This is as seen with the mysterious libspeexdsp failures for x86-lsb on the autobuilder. Upstream-Status: Pending RP 2015/7/16 Index: git/smart/transaction.py =================================================================== --- git.orig/smart/transaction.py +++ git/smart/transaction.py @@ -651,13 +651,14 @@ class Transaction(object): if not prvpkgs: # No packages provide it at all. Give up. + + reasons = [] + for prv in req.providedby: + for prvpkg in prv.packages: + lockedres = lockedpkgs.get(prvpkg, None) + if lockedres: + reasons.append(lock_reason(prvpkg, lockedres)) if reqrequired: - reasons = [] - for prv in req.providedby: - for prvpkg in prv.packages: - lockedres = lockedpkgs.get(prvpkg, None) - if lockedres: - reasons.append(lock_reason(prvpkg, lockedres)) if reasons: raise Failed, _("Can't install %s: unable to install provider for %s:\n %s") % \ (pkg, req, '\n '.join(reasons)) @@ -665,7 +666,11 @@ class Transaction(object): raise Failed, _("Can't install %s: no package provides %s") % \ (pkg, req) else: + if reasons: + iface.warning(_("Can't install %s: unable to install provider for %s:\n %s") % \ + (pkg, req, '\n '.join(reasons))) + # It's only a recommend, skip continue if len(prvpkgs) == 1: @@ -846,6 +852,14 @@ class Transaction(object): isinst = changeset.installed getweight = self._policy.getWeight + attempt = sysconf.has("attempt-install", soft=True) + + def handle_failure(msg): + if attempt: + iface.warning(msg) + else: + raise Failed, msg + updown = [] while pending: item = pending.pop(0) @@ -870,8 +884,9 @@ class Transaction(object): if not prvpkgs: # No packages provide it at all. Give up. - raise Failed, _("Can't install %s: no package " - "provides %s") % (pkg, req) + handle_failure(_("Can't install %s: no package " + "provides %s") % (pkg, req)) + continue if len(prvpkgs) > 1: # More than one package provide it. We use _pending here, @@ -894,9 +909,10 @@ class Transaction(object): keeporder, cs, lk)) keeporder += 0.000001 if not alternatives: - raise Failed, _("Can't install %s: all packages " + handle_failure(_("Can't install %s: all packages " "providing %s failed to install:\n%s")\ - % (pkg, req, "\n".join(failures)) + % (pkg, req, "\n".join(failures))) + continue alternatives.sort() changeset.setState(alternatives[0][1]) if len(alternatives) == 1: @@ -954,18 +970,20 @@ class Transaction(object): for reqpkg in reqpkgs: if reqpkg in locked and isinst(reqpkg): - raise Failed, _("Can't remove %s: requiring " + handle_failure(_("Can't remove %s: requiring " "package %s is locked") % \ - (pkg, reqpkg) + (pkg, reqpkg)) + continue for reqpkg in reqpkgs: # We check again, since other actions may have # changed their state. if not isinst(reqpkg): continue if reqpkg in locked: - raise Failed, _("Can't remove %s: requiring " + handle_failure(_("Can't remove %s: requiring " "package %s is locked") % \ - (pkg, reqpkg) + (pkg, reqpkg)) + continue self._remove(reqpkg, changeset, locked, pending, depth) continue @@ -978,12 +996,14 @@ class Transaction(object): try: for reqpkg in reqpkgs: if reqpkg in locked and isinst(reqpkg): - raise Failed, _("%s is locked") % reqpkg + handle_failure(_("%s is locked") % reqpkg) + continue for reqpkg in reqpkgs: if not cs.installed(reqpkg): continue if reqpkg in lk: - raise Failed, _("%s is locked") % reqpkg + handle_failure(_("%s is locked") % reqpkg) + continue self._remove(reqpkg, cs, lk, None, depth) except Failed, e: failures.append(unicode(e)) @@ -991,9 +1011,10 @@ class Transaction(object): alternatives.append((getweight(cs), cs, lk)) if not alternatives: - raise Failed, _("Can't install %s: all packages providing " + handle_failure(_("Can't install %s: all packages providing " "%s failed to install:\n%s") \ - % (pkg, prv, "\n".join(failures)) + % (pkg, prv, "\n".join(failures))) + continue alternatives.sort() changeset.setState(alternatives[0][1]) @@ -1246,6 +1267,7 @@ class Transaction(object): changeset.setRequested(pkg, True) except Failed, e: if sysconf.has("attempt-install", soft=True): + iface.warning(_("Can't install %s: %s") % (pkg, str(e))) if pkg in changeset: del changeset[pkg] continue