From 5cf71e7891847c6d9d01c07b0952a543a8c8a7ec Mon Sep 17 00:00:00 2001 From: Stefan Schubert Date: Wed, 20 Jun 2007 09:47:53 +0000 Subject: [PATCH] - Ignore conflicting items which are uninstallable - Create a "needed by" info if a requirement is still fulfilled. - Allow only one needed_by and needed_by_capability in QueueItemInstall - Added capability and type (REQUIRE, RECOMMEND,....) to ResolverInfoNeededBy - Evaluate ResolverInfoNeededBy for more information in the error messages - Enlarge detail description in the error messages --- zypp/solver/detail/QueueItemEstablish.cc | 6 +- zypp/solver/detail/QueueItemInstall.cc | 83 +++++++------------------ zypp/solver/detail/QueueItemInstall.h | 8 +-- zypp/solver/detail/QueueItemRequire.cc | 17 ++--- zypp/solver/detail/QueueItemUninstall.cc | 5 +- zypp/solver/detail/ResolverContext.cc | 52 ++++++++++++---- zypp/solver/detail/ResolverContext.h | 10 ++- zypp/solver/detail/ResolverInfoNeededBy.cc | 99 ++++++++++++++++++++++++++---- zypp/solver/detail/ResolverInfoNeededBy.h | 4 ++ zypp/solver/detail/Resolver_problems.cc | 96 +++++++++++++++++++++++++++-- 10 files changed, 274 insertions(+), 106 deletions(-) diff --git a/zypp/solver/detail/QueueItemEstablish.cc b/zypp/solver/detail/QueueItemEstablish.cc index 7733448..c83f563 100644 --- a/zypp/solver/detail/QueueItemEstablish.cc +++ b/zypp/solver/detail/QueueItemEstablish.cc @@ -127,7 +127,7 @@ QueueItemEstablish::process (ResolverContext_Ptr context, QueueItemList & qil) CapSet::const_iterator iter; for (iter = freshens.begin(); iter != freshens.end(); iter++) { const Capability cap = *iter; - if (context->requirementIsMet (cap)) { + if (context->requirementIsMet (cap, _item, Dep::FRESHENS)) { _XDEBUG("this freshens " << cap); break; } @@ -153,7 +153,7 @@ QueueItemEstablish::process (ResolverContext_Ptr context, QueueItemList & qil) CapSet::const_iterator iter; for (iter = supplements.begin(); iter != supplements.end(); iter++) { const Capability cap = *iter; - if (context->requirementIsMet (cap)) { + if (context->requirementIsMet (cap, _item, Dep::SUPPLEMENTS)) { _XDEBUG("this supplements " << cap); break; } @@ -199,7 +199,7 @@ QueueItemEstablish::process (ResolverContext_Ptr context, QueueItemList & qil) for (iter = requires.begin(); iter != requires.end(); iter++) { missing = *iter; bool unneeded; - if (!context->requirementIsMet (missing, &unneeded)) { + if (!context->requirementIsMet (missing, _item, Dep::REQUIRES, &unneeded)) { all_unneeded = false; break; } diff --git a/zypp/solver/detail/QueueItemInstall.cc b/zypp/solver/detail/QueueItemInstall.cc index bf0ee53..028db2c 100644 --- a/zypp/solver/detail/QueueItemInstall.cc +++ b/zypp/solver/detail/QueueItemInstall.cc @@ -69,22 +69,11 @@ QueueItemInstall::dumpOn( std::ostream & os ) const os << ", Upgrades "; os << _upgrades; } - if (!_deps_satisfied_by_this_install.empty()) { - os << ", Satisfies ["; - for (CapSet::const_iterator iter = _deps_satisfied_by_this_install.begin(); - iter != _deps_satisfied_by_this_install.end(); iter++) - { - if (iter != _deps_satisfied_by_this_install.begin()) os << ", "; - os << (*iter); - } - os << "]"; + if (_dep_satisfied_by_this_install != Capability::noCap) { + os << ", Satisfies [" << _dep_satisfied_by_this_install << "]"; } - if (!_needed_by.empty()) { - os << ", Needed by "; - for (PoolItemList::const_iterator it = _needed_by.begin(); it != _needed_by.end(); ++it) { - if (it != _needed_by.begin()) os << ", "; - os << *it; - } + if (_needed_by) { + os << ", Needed by " << _needed_by; } if (_explicitly_requested) os << ", Explicit !"; os << "]"; @@ -97,6 +86,8 @@ QueueItemInstall::QueueItemInstall (const ResPool & pool, PoolItem_Ref item, boo : QueueItem (QUEUE_ITEM_TYPE_INSTALL, pool) , _item (item) , _soft (soft) + , _dep_satisfied_by_this_install (Capability::noCap) + , _needed_by (PoolItem_Ref()) , _channel_priority (0) , _other_penalty (0) , _explicitly_requested (false) @@ -315,23 +306,16 @@ QueueItemInstall::process (ResolverContext_Ptr context, QueueItemList & qil) // check if this install is still needed // (maybe other resolver processing made this install obsolete - if (!_needed_by.empty()) { - bool still_needed = false; - + if (_needed_by) { _XDEBUG( "still needed "); - for (PoolItemList::const_iterator iter = _needed_by.begin(); iter != _needed_by.end() && !still_needed; ++iter) { - ResStatus status = iter->status(); - _XDEBUG("by: [status: " << status << "] " << *iter); - if (! status.isToBeUninstalled() - && ! status.isImpossible()) - { - still_needed = true; - } + ResStatus status = _needed_by.status(); + _XDEBUG("by: [status: " << status << "] " << _needed_by); + if ( status.isToBeUninstalled() + || status.isImpossible()) + { + goto finished; } - - if (! still_needed) - goto finished; } /* If we are in verify mode and this install is about to fail, don't let it happen... @@ -340,14 +324,11 @@ QueueItemInstall::process (ResolverContext_Ptr context, QueueItemList & qil) if (context->verifying() && (status.isToBeUninstalled() || status.isImpossible()) - && !_needed_by.empty()) { + && _needed_by) { QueueItemUninstall_Ptr uninstall_item; - - for (PoolItemList::const_iterator iter = _needed_by.begin(); iter != _needed_by.end(); iter++) { - uninstall_item = new QueueItemUninstall (pool(), *iter, QueueItemUninstall::BACKOUT); - qil.push_front (uninstall_item); - } + uninstall_item = new QueueItemUninstall (pool(), _needed_by, QueueItemUninstall::BACKOUT); + qil.push_front (uninstall_item); goto finished; } @@ -396,12 +377,13 @@ QueueItemInstall::process (ResolverContext_Ptr context, QueueItemList & qil) /* Log which item need this install */ - if (!_needed_by.empty()) { + if (_needed_by) { ResolverInfoNeededBy_Ptr info; info = new ResolverInfoNeededBy (_item); - info->addRelatedPoolItemList (_needed_by); + info->addRelatedPoolItem (_needed_by); + info->setCapability (_dep_satisfied_by_this_install, _soft?Dep::RECOMMENDS:Dep::REQUIRES); context->addInfo (info); } @@ -447,12 +429,7 @@ QueueItemInstall::process (ResolverContext_Ptr context, QueueItemList & qil) _XDEBUG("this requires " << cap); bool fulfilled = false; - if (_item) - { - fulfilled = context->requirementIsInstalledOrUnneeded (_item->kind(), cap); - } else { - fulfilled = context->requirementIsMet (cap); - } + fulfilled = context->requirementIsInstalledOrUnneeded (cap, _item, Dep::REQUIRES); if (!fulfilled) { _XDEBUG("this requirement is still unfulfilled"); @@ -469,7 +446,7 @@ QueueItemInstall::process (ResolverContext_Ptr context, QueueItemList & qil) const Capability cap = *iter; _XDEBUG("this recommends " << cap); - if (!context->requirementIsMet (cap)) { + if (!context->requirementIsMet (cap, _item, Dep::RECOMMENDS)) { _XDEBUG("this recommends is still unfulfilled"); QueueItemRequire_Ptr req_item = new QueueItemRequire (pool(), cap, true); // this is a soft requires req_item->addPoolItem (_item); @@ -601,8 +578,8 @@ QueueItemInstall::copy (void) const new_install->QueueItem::copy(this); new_install->_upgrades = _upgrades; - new_install->_deps_satisfied_by_this_install = CapSet(_deps_satisfied_by_this_install.begin(), _deps_satisfied_by_this_install.end()); - new_install->_needed_by = PoolItemList (_needed_by.begin(), _needed_by.end()); + new_install->_dep_satisfied_by_this_install = _dep_satisfied_by_this_install; + new_install->_needed_by = _needed_by; new_install->_channel_priority = _channel_priority; new_install->_other_penalty = _other_penalty; new_install->_explicitly_requested = _explicitly_requested; @@ -621,20 +598,6 @@ QueueItemInstall::cmp (QueueItem_constPtr item) const return compareByNVRA (_item.resolvable(), install->_item.resolvable()); } -//--------------------------------------------------------------------------- - -void -QueueItemInstall::addDependency (const Capability & dep) -{ - _deps_satisfied_by_this_install.insert (dep); -} - - -void -QueueItemInstall::addNeededBy (PoolItem_Ref item) -{ - _needed_by.push_front (item); -} /////////////////////////////////////////////////////////////////// };// namespace detail diff --git a/zypp/solver/detail/QueueItemInstall.h b/zypp/solver/detail/QueueItemInstall.h index d7e85e0..d8f6480 100644 --- a/zypp/solver/detail/QueueItemInstall.h +++ b/zypp/solver/detail/QueueItemInstall.h @@ -51,8 +51,8 @@ class QueueItemInstall : public QueueItem { PoolItem_Ref _item; // the item to-be-installed bool _soft; // if triggered by a soft requirement (a recommends) PoolItem_Ref _upgrades; // the item this install upgrades (if any) - CapSet _deps_satisfied_by_this_install; - PoolItemList _needed_by; + Capability _dep_satisfied_by_this_install; + PoolItem_Ref _needed_by; int _channel_priority; int _other_penalty; @@ -96,8 +96,8 @@ class QueueItemInstall : public QueueItem { virtual bool isRedundant (ResolverContext_Ptr context) const { return false; } virtual bool isSatisfied (ResolverContext_Ptr context) const; - void addDependency (const Capability & capability); - void addNeededBy (const PoolItem_Ref item); + void setDependency (const Capability & capability) {_dep_satisfied_by_this_install = capability;} + void setNeededBy (const PoolItem_Ref item) {_needed_by=item;} }; diff --git a/zypp/solver/detail/QueueItemRequire.cc b/zypp/solver/detail/QueueItemRequire.cc index ab806dc..a71949e 100644 --- a/zypp/solver/detail/QueueItemRequire.cc +++ b/zypp/solver/detail/QueueItemRequire.cc @@ -31,6 +31,7 @@ #include "zypp/ResFilters.h" #include "zypp/CapFilters.h" #include "zypp/ResStatus.h" +#include "zypp/Dep.h" #include "zypp/ZYppFactory.h" @@ -454,9 +455,10 @@ QueueItemRequire::process (ResolverContext_Ptr context, QueueItemList & new_item if (_requiring_item) { - fulfilled = context->requirementIsInstalledOrUnneeded (_requiring_item->kind(),_capability); + fulfilled = context->requirementIsInstalledOrUnneeded (_capability, _requiring_item, + _soft?Dep::RECOMMENDS:Dep::REQUIRES); } else { - fulfilled = context->requirementIsMet (_capability); + fulfilled = context->requirementIsMet (_capability, PoolItem_Ref(), Dep::REQUIRES); } if (fulfilled) { @@ -747,6 +749,7 @@ provider_done:; ResolverInfoNeededBy_Ptr upgrade_info = new ResolverInfoNeededBy (upgrade_item); if (_upgraded_item) upgrade_info->addRelatedPoolItem (_upgraded_item); + upgrade_info->setCapability (_capability, Dep::REQUIRES); install_item->addInfo (upgrade_info); // If an upgrade item has its requirements met, don't do the uninstall branch. @@ -757,7 +760,7 @@ provider_done:; CapSet::const_iterator iter = requires.begin(); for (; iter != requires.end(); iter++) { const Capability req = *iter; - if (! context->requirementIsMet (req)) { + if (! context->requirementIsMet (req, upgrade_item, Dep::REQUIRES)) { break; } } @@ -894,11 +897,11 @@ provider_done:; goto finished; } QueueItemInstall_Ptr install_item = new QueueItemInstall (pool(), item, _soft); - install_item->addDependency (_capability); + install_item->setDependency (_capability); // The requiring item could be NULL if the requirement was added as an extra dependency. if (_requiring_item) { - install_item->addNeededBy (_requiring_item); + install_item->setNeededBy (_requiring_item); } new_items.push_front (install_item); @@ -929,12 +932,12 @@ provider_done:; } QueueItemInstall_Ptr install_item = new QueueItemInstall( pool(), item, _soft ); - install_item->addDependency( _capability ); + install_item->setDependency( _capability ); branch_item->addItem( install_item ); // The requiring item could be NULL if the requirement was added as an extra dependency. if (_requiring_item) { - install_item->addNeededBy( _requiring_item ); + install_item->setNeededBy( _requiring_item ); } } diff --git a/zypp/solver/detail/QueueItemUninstall.cc b/zypp/solver/detail/QueueItemUninstall.cc index 1c0b645..c7bac7a 100644 --- a/zypp/solver/detail/QueueItemUninstall.cc +++ b/zypp/solver/detail/QueueItemUninstall.cc @@ -144,13 +144,14 @@ struct UnlinkCheck bool operator()( const CapAndItem & cai ) { + PoolItem provider( cai.item ); if (cancel_unlink) // already cancelled return true; if (! context->isPresent (cai.item)) // item is not (to-be-)installed return true; - if (context->requirementIsMet (cai.cap)) // another resolvable provided match + if (context->requirementIsMet (cai.cap, provider, Dep::REQUIRES)) // another resolvable provided match return true; cancel_unlink = true; // cancel, as this would break dependencies @@ -190,7 +191,7 @@ struct UninstallProcess if (! context->isPresent (requirer)) // its not installed -> dont care return true; - if (context->requirementIsMet( cai.cap )) // its provided by another installed resolvable -> dont care + if (context->requirementIsMet( cai.cap, requirer, Dep::REQUIRES )) // its provided by another installed resolvable -> dont care return true; if (context->getStatus(requirer).isSatisfied()) { // it is just satisfied, check freshens and supplements diff --git a/zypp/solver/detail/ResolverContext.cc b/zypp/solver/detail/ResolverContext.cc index 1813491..1d7f79b 100644 --- a/zypp/solver/detail/ResolverContext.cc +++ b/zypp/solver/detail/ResolverContext.cc @@ -40,6 +40,7 @@ #include "zypp/solver/detail/ResolverContext.h" #include "zypp/solver/detail/ResolverInfoMisc.h" #include "zypp/solver/detail/ResolverInfoConflictsWith.h" +#include "zypp/solver/detail/ResolverInfoNeededBy.h" ///////////////////////////////////////////////////////////////////////// namespace zypp @@ -514,9 +515,12 @@ ResolverContext::uninstall (PoolItem_Ref item, bool part_of_upgrade, bool due_to if ( !other_found && (info->affected() == item || other_item == item)) { - // put the info on the end as error - found = true; - addList.push_back (info); + if (!getStatus(info->affected()).isImpossible() // Check, if the both items are still "installable" + && !getStatus(other_item).isImpossible()) { // If not this is not an error anymore + // put the info on the end as an error + addList.push_back (info); + found = true; + } } } else if ( (info->type() == RESOLVER_INFO_TYPE_NO_PROVIDER || info->type() == RESOLVER_INFO_TYPE_NO_OTHER_PROVIDER @@ -572,7 +576,8 @@ ResolverContext::uninstall (PoolItem_Ref item, bool part_of_upgrade, bool due_to else if (due_to_unlink) { setStatus (item, ResStatus::toBeUninstalledDueToUnlink); } - else if (status.wasUninstalled()) { + else if (status.wasUninstalled() || + (status.isToBeInstalled() && status.isBySolver())) { setStatus (item, ResStatus::impossible); } else if (part_of_upgrade) { @@ -1484,12 +1489,16 @@ struct RequirementMet bool flag; bool unneeded; bool *installed; + const PoolItem_Ref whoNeeds; + const Dep cap; - RequirementMet (ResolverContext_Ptr ctx, bool *inst) + RequirementMet (ResolverContext_Ptr ctx, bool *inst, const PoolItem_Ref who, const Dep & capKind) : context (ctx) , flag (false) , unneeded( false ) , installed( inst ) + , whoNeeds( who ) + , cap( capKind ) { } @@ -1504,6 +1513,22 @@ struct RequirementMet { unneeded = my_unneeded; flag = true; + ResolverInfoNeededBy_Ptr info; + + if (cap == Dep::PREREQUIRES + || cap == Dep::REQUIRES + || cap == Dep::RECOMMENDS + || cap == Dep::SUGGESTS) { + info = new ResolverInfoNeededBy (provider); + info->addRelatedPoolItem (whoNeeds); + } else { + // FRESHENS, ENHANCES, SUPPLEMENTS + // are reverse dependencies + info = new ResolverInfoNeededBy (whoNeeds); + info->addRelatedPoolItem (provider); + } + info->setCapability (match, cap); + context->addInfo (info); } // ERR << "RequirementMet(" << provider << ", " << match << ") [capability " << @@ -1519,9 +1544,12 @@ struct RequirementMet bool -ResolverContext::requirementIsMet (const Capability & capability, bool *unneeded, bool *installed) +ResolverContext::requirementIsMet (const Capability & capability, + const PoolItem_Ref who, + const Dep & capKind, + bool *unneeded, bool *installed) { - RequirementMet info (this, installed); + RequirementMet info (this, installed, who, capKind); // world()->foreachProviding (capability, requirement_met_cb, (void *)&info); @@ -1547,9 +1575,11 @@ _XDEBUG( "ResolverContext::requirementIsMet(" << capability << ") " << (info.fla *which requires this capability. */ bool -ResolverContext::requirementIsInstalledOrUnneeded (const ResObject::Kind & kind, - const Capability & capability) +ResolverContext::requirementIsInstalledOrUnneeded (const Capability & capability, + const PoolItem_Ref who, + const Dep & capKind) { + ResObject::Kind kind = who->kind(); bool fulfilled = false; if (kind != ResTraits::kind @@ -1557,7 +1587,7 @@ ResolverContext::requirementIsInstalledOrUnneeded (const ResObject::Kind & kind, || kind != ResTraits::kind) { bool unneeded, installed; - fulfilled = requirementIsMet (capability, &unneeded, &installed); + fulfilled = requirementIsMet (capability, who, capKind, &unneeded, &installed); if (!fulfilled || (!unneeded && !installed)) { @@ -1567,7 +1597,7 @@ ResolverContext::requirementIsInstalledOrUnneeded (const ResObject::Kind & kind, // Bug 192535/204913 } }else { - fulfilled = requirementIsMet (capability); + fulfilled = requirementIsMet (capability, who, capKind); } return fulfilled; diff --git a/zypp/solver/detail/ResolverContext.h b/zypp/solver/detail/ResolverContext.h index 41388f7..d07c670 100644 --- a/zypp/solver/detail/ResolverContext.h +++ b/zypp/solver/detail/ResolverContext.h @@ -251,7 +251,10 @@ class ResolverContext : public base::ReferenceCounted, private base::NonCopyable *\return \c true if \c item is \a uninstalled or \a to-be-uninstalled */ bool isAbsent (PoolItem_Ref item); - bool requirementIsMet (const Capability & cap, bool *unneeded = NULL, + bool requirementIsMet (const Capability & cap, + const PoolItem_Ref who, + const Dep & capKind, + bool *unneeded = NULL, bool *installed = NULL); /** *\return \c true if the requirement is already fulfilled. @@ -259,8 +262,9 @@ class ResolverContext : public base::ReferenceCounted, private base::NonCopyable *The behaviour depends on the item kind (package,patch,..) *which requires this capability. */ - bool requirementIsInstalledOrUnneeded (const ResObject::Kind & kind, - const Capability & capability); + bool requirementIsInstalledOrUnneeded (const Capability & capability, + const PoolItem_Ref who, + const Dep & capKind); bool requirementIsPossible (const Capability & cap); bool itemIsPossible (const PoolItem_Ref item); bool isParallelInstall (const PoolItem_Ref item) const; diff --git a/zypp/solver/detail/ResolverInfoNeededBy.cc b/zypp/solver/detail/ResolverInfoNeededBy.cc index 30f6e33..22155b3 100644 --- a/zypp/solver/detail/ResolverInfoNeededBy.cc +++ b/zypp/solver/detail/ResolverInfoNeededBy.cc @@ -26,6 +26,7 @@ #include "zypp/solver/detail/ResolverInfoNeededBy.h" #include "zypp/base/String.h" #include "zypp/base/Gettext.h" +#include "zypp/Dep.h" ///////////////////////////////////////////////////////////////////////// namespace zypp @@ -52,10 +53,47 @@ ResolverInfoNeededBy::dumpOn( std::ostream & os ) const ostringstream affected_str; affected_str << ResolverInfo::toString (affected()); - // Translator: all.%s = name of package,patch,... - os << str::form (_("%s is needed by %s"), - affected_str.str().c_str(), - itemsToString(true).c_str()); + switch ( _capKind.inSwitch() ) + { + case Dep::RECOMMENDS_e: + // Translator: all.%s = name of package,patch,... + os << str::form (_("%s is recommended by %s"), + affected_str.str().c_str(), + itemsToString(true).c_str()); + break; + case Dep::SUGGESTS_e: + // Translator: all.%s = name of package,patch,... + os << str::form (_("%s is suggested by %s"), + affected_str.str().c_str(), + itemsToString(true).c_str()); + break; + case Dep::FRESHENS_e: + // Translator: all.%s = name of package,patch,... + os << str::form (_("%s is freshened by %s"), + affected_str.str().c_str(), + itemsToString(true).c_str()); + break; + case Dep::ENHANCES_e: + // Translator: all.%s = name of package,patch,... + os << str::form (_("%s is enhanced by %s"), + affected_str.str().c_str(), + itemsToString(true).c_str()); + break; + case Dep::SUPPLEMENTS_e: + // Translator: all.%s = name of package,patch,... + os << str::form (_("%s is supplemented by %s"), + affected_str.str().c_str(), + itemsToString(true).c_str()); + break; + default: + // Translator: all.%s = name of package,patch,... + os << str::form (_("%s is needed by %s"), + affected_str.str().c_str(), + itemsToString(true).c_str()); + } + if (_cap != Capability::noCap) + os << " (" << _cap << ")"; + return os; } @@ -63,19 +101,58 @@ string ResolverInfoNeededBy::message( ) const { string affected_str = ResolverInfo::toString(affected()); - string container_str = itemsToString( false ); - - // TranslatorExplanation: 1.%s name of package, 2.%s list of names - // TranslatorExplanation: 1.%s is needed by multiple others - return str::form (_("%s needed by %s"), - affected_str.c_str(), - container_str.c_str()); + string ret; + + switch ( _capKind.inSwitch() ) + { + case Dep::RECOMMENDS_e: + // Translator: all.%s = name of package,patch,... + ret = str::form (_("%s is recommended by %s"), + affected_str.c_str(), + itemsToString(false).c_str()); + break; + case Dep::SUGGESTS_e: + // Translator: all.%s = name of package,patch,... + ret = str::form (_("%s is suggested by %s"), + affected_str.c_str(), + itemsToString(false).c_str()); + break; + case Dep::FRESHENS_e: + // Translator: all.%s = name of package,patch,... + ret = str::form (_("%s is freshened by %s"), + affected_str.c_str(), + itemsToString(false).c_str()); + break; + case Dep::ENHANCES_e: + // Translator: all.%s = name of package,patch,... + ret = str::form (_("%s is enhanced by %s"), + affected_str.c_str(), + itemsToString(false).c_str()); + break; + case Dep::SUPPLEMENTS_e: + // Translator: all.%s = name of package,patch,... + ret = str::form (_("%s is supplemented by %s"), + affected_str.c_str(), + itemsToString(false).c_str()); + break; + default: + // Translator: all.%s = name of package,patch,... + ret = str::form (_("%s is needed by %s"), + affected_str.c_str(), + itemsToString(false).c_str()); + } + if (_cap != Capability::noCap) + ret += " (" + _cap.asString() + ")"; + + return ret; } //--------------------------------------------------------------------------- ResolverInfoNeededBy::ResolverInfoNeededBy (PoolItem_Ref item) : ResolverInfoContainer (RESOLVER_INFO_TYPE_NEEDED_BY, item, RESOLVER_INFO_PRIORITY_USER) + , _cap(Capability::noCap) + , _capKind(Dep::REQUIRES) { } diff --git a/zypp/solver/detail/ResolverInfoNeededBy.h b/zypp/solver/detail/ResolverInfoNeededBy.h index 0cac992..29df4af 100644 --- a/zypp/solver/detail/ResolverInfoNeededBy.h +++ b/zypp/solver/detail/ResolverInfoNeededBy.h @@ -44,6 +44,8 @@ class ResolverInfoNeededBy : public ResolverInfoContainer { private: + Capability _cap; + Dep _capKind; public: @@ -62,6 +64,8 @@ class ResolverInfoNeededBy : public ResolverInfoContainer { virtual std::string message (void) const; virtual ResolverInfo_Ptr copy (void) const; + void setCapability (const Capability & cap, const Dep & capKind) { _cap = cap; _capKind = capKind; } +; }; /////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/Resolver_problems.cc b/zypp/solver/detail/Resolver_problems.cc index 6581eca..9e3139e 100644 --- a/zypp/solver/detail/Resolver_problems.cc +++ b/zypp/solver/detail/Resolver_problems.cc @@ -102,7 +102,10 @@ public: // set resolvables with errors typedef struct { + // Map of errors ProblemMap problems; + // Map of additional information applied to an item + ProblemMap additionalInfo; // A map of PoolItems which provides a capability but are set // for uninstallation ItemCapabilityMap provideAndDeleteMap; @@ -123,9 +126,12 @@ collector_cb (ResolverInfo_Ptr info, void *data) { ResItemCollector *collector = (ResItemCollector *)data; PoolItem_Ref item = info->affected(); - if (item - && info->error()) { - collector->problems.insert (make_pair( item, info)); + if (item) { + if (info->error()) { + collector->problems.insert (make_pair( item, info)); + } else { + collector->additionalInfo.insert (make_pair( item, info)); + } } // Collicting items which are providing requirements but they // are set for uninstall @@ -221,6 +227,63 @@ struct AllRequires } }; +std::string logAdditionalInfo ( const ProblemMap &additionalInfo, const PoolItem_Ref item) +{ + string infoStr = "\n"; + for (ProblemMap::const_iterator iter = additionalInfo.find(item); iter != additionalInfo.end();) { + ResolverInfo_Ptr info = iter->second; + PoolItem_Ref iterItem = iter->first; + + if (iter == additionalInfo.find(item)) { + string who = ResolverInfo::toString( item ); + infoStr = "\n\n" + who + "\n"; + for (unsigned int i = 1; i <= who.length(); i++) infoStr += "="; + infoStr += "\n\n"; + + ResStatus status = iterItem.status(); + if (status.isToBeUninstalled()) { + if (status.isByUser()) + // Translator: all.%s = name of package,patch,... + infoStr += str::form (_("%s will be deleted by the user.\n"), + who.c_str()); + if (status.isByApplHigh() + || status.isByApplLow()) + // Translator: all.%s = name of package,patch,... + infoStr += str::form (_("%s will be deleted by another application. (ApplLow/ApplHigh)\n"), + who.c_str()); + } + if (status.isToBeInstalled()) { + if (status.isByUser()) + // Translator: all.%s = name of package,patch,... + infoStr += str::form (_("%s will be installed by the user.\n"), + who.c_str()); + if (status.isByApplHigh() + || status.isByApplLow()) + // Translator: all.%s = name of package,patch,... + infoStr += str::form (_("%s will be installed by another application. (ApplLow/ApplHigh)\n"), + who.c_str()); + } + } + if (iterItem == item) { + // filter out useless information + if (info->type() != RESOLVER_INFO_TYPE_INSTALLING + && info->type() != RESOLVER_INFO_TYPE_ESTABLISHING + && info->type() != RESOLVER_INFO_TYPE_UPDATING + && info->type() != RESOLVER_INFO_TYPE_SKIPPING + && info->type() != RESOLVER_INFO_TYPE_UNINSTALLABLE + && info->type() != RESOLVER_INFO_TYPE_CONFLICT_UNINSTALLABLE) { + infoStr += info->message(); + infoStr += "\n"; + } + iter++; + } else { + // exit + iter = additionalInfo.end(); + } + } + return infoStr; +} + ResolverProblemList Resolver::problems (const bool ignoreValidSolution) const @@ -305,7 +368,14 @@ Resolver::problems (const bool ignoreValidSolution) const else // TranslatorExplanation %s = name of package, patch, selection ... what = str::form (_("%s conflicts with %s"), who.c_str(), conflicts_with->itemsToString(true).c_str()); + details = str::form (_("%s conflicts with:\n%s"), who.c_str(), conflicts_with->itemsToString(false).c_str()); + details += logAdditionalInfo(collector.additionalInfo, item); + PoolItemList item_list = conflicts_with->items(); + for (PoolItemList::const_iterator it = item_list.begin(); it != item_list.end(); ++it) { + details += logAdditionalInfo(collector.additionalInfo, *it); + } + ResolverProblem_Ptr problem = new ResolverProblem (what, details); // Uninstall p problem->addSolution (new ProblemSolutionUninstall (problem, item)); @@ -335,6 +405,7 @@ Resolver::problems (const bool ignoreValidSolution) const // TranslatorExplanation %s = name of package, patch, selection ... details = str::form (_("%s obsoletes:%s"), who.c_str(), obsoletes->itemsToString(false).c_str()); details += _("\nThese resolvables will be deleted from the system."); + details += logAdditionalInfo(collector.additionalInfo, item); } break; case RESOLVER_INFO_TYPE_DEPENDS_ON: { // no solution; it is only a info @@ -384,8 +455,9 @@ Resolver::problems (const bool ignoreValidSolution) const if (it->first == item) { what = str::form (_("Cannot install %s because it is conflicting with %s"), who.c_str(), - it->second->name().c_str()); - details = ""; // no further details + it->second->name().c_str()); + details = logAdditionalInfo(collector.additionalInfo, item); + details += logAdditionalInfo(collector.additionalInfo, it->second); ResolverProblem_Ptr problem = new ResolverProblem (what, details); // Uninstall p problem->addSolution (new ProblemSolutionUninstall (problem, item)); @@ -400,6 +472,7 @@ Resolver::problems (const bool ignoreValidSolution) const what = misc_info->message(); // TranslatorExplanation %s = name of package,patch,... details = str::form (_("%s is not installed and has been marked as uninstallable"), who.c_str()); + details += logAdditionalInfo(collector.additionalInfo, item); ResolverProblem_Ptr problem = new ResolverProblem (what, details); problem->addSolution (new ProblemSolutionInstall (problem, item)); // Install resolvable again problems.push_back (problem); @@ -412,6 +485,7 @@ Resolver::problems (const bool ignoreValidSolution) const // TranslatorExplanation %s = name of package,patch,... what = str::form (_("Cannot install %s due to dependency problems"), who.c_str()); details = misc_info->message(); + details += logAdditionalInfo(collector.additionalInfo, item); ResolverProblem_Ptr problem = new ResolverProblem (what, details); // Uninstall it; problem->addSolution (new ProblemSolutionUninstall (problem, item)); @@ -424,6 +498,7 @@ Resolver::problems (const bool ignoreValidSolution) const ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast(info); // TranslatorExplanation %s = name of package,patch,... what = misc_info->message(); + details = logAdditionalInfo(collector.additionalInfo, item); ResolverProblem_Ptr problem = new ResolverProblem (what, details); problem->addSolution (new ProblemSolutionInstall (problem, item)); // Install resolvable again problems.push_back (problem); @@ -442,6 +517,8 @@ Resolver::problems (const bool ignoreValidSolution) const // TranslatorExplanation %s = name of package,patch,... what = str::form (_("Cannot install %s"), who.c_str()); details = misc_info->message(); + details += logAdditionalInfo(collector.additionalInfo, item); + details += logAdditionalInfo(collector.additionalInfo, misc_info->other()); ResolverProblem_Ptr problem = new ResolverProblem (what, details); // Uninstall the item ResStatus status = item.status(); @@ -475,6 +552,7 @@ Resolver::problems (const bool ignoreValidSolution) const what = misc_info->message(); // TranslatorExplanation %s = name of package, patch, selection ... details = str::form (_("%s has unfulfilled requirements"), who.c_str()); + details += logAdditionalInfo(collector.additionalInfo, item); ResolverProblem_Ptr problem = new ResolverProblem (what, details); // Uninstall problem->addSolution (new ProblemSolutionUninstall (problem, item)); @@ -514,6 +592,7 @@ Resolver::problems (const bool ignoreValidSolution) const // TranslatorExplanation %s = name of package, patch, selection ... what = str::form (_("%s has missing dependencies"), who.c_str()); details = misc_info->message(); + details += logAdditionalInfo(collector.additionalInfo, item); ResolverProblem_Ptr problem = new ResolverProblem (what, details); // Searching for another item which provides this requires BUT has been set to uninstall @@ -561,6 +640,7 @@ Resolver::problems (const bool ignoreValidSolution) const // TranslatorExplanation %s = name of package, patch, selection ... what = str::form (_("%s cannot be installed due to missing dependencies"), who.c_str()); details = misc_info->message(); + details += logAdditionalInfo(collector.additionalInfo, item); ResolverProblem_Ptr problem = new ResolverProblem (what, details); // Searching for another item which provides this requires BUT has been locked @@ -660,6 +740,7 @@ Resolver::problems (const bool ignoreValidSolution) const case RESOLVER_INFO_TYPE_CANT_SATISFY: { // Can't satisfy requirement c ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast(info); what = misc_info->message(); + details = logAdditionalInfo(collector.additionalInfo, item); ResolverProblem_Ptr problem = new ResolverProblem (what, details); // uninstall problem->addSolution (new ProblemSolutionUninstall (problem, item)); @@ -697,6 +778,7 @@ Resolver::problems (const bool ignoreValidSolution) const // TranslatorExplanation %s = name of package, patch, selection ... what = str::form (_("%s will not be uninstalled cause it is still required"), who.c_str()); details = misc_info->message(); + details += logAdditionalInfo(collector.additionalInfo, item); ResolverProblem_Ptr problem = new ResolverProblem (what, details); if (item.status().isInstalled()) { @@ -720,6 +802,7 @@ Resolver::problems (const bool ignoreValidSolution) const details = str::form (_("%s obsoletes %s. But %s cannot be deleted because it is locked."), misc_info->other()->name().c_str(), who.c_str(), who.c_str()); + details += logAdditionalInfo(collector.additionalInfo, item); } ResolverProblem_Ptr problem = new ResolverProblem (what, details); @@ -751,6 +834,9 @@ Resolver::problems (const bool ignoreValidSolution) const what = str::form (_("Cannot install %s because it is conflicting"), who.c_str()); details = misc_info->message(); + details += logAdditionalInfo(collector.additionalInfo, item); + if (misc_info->other()) + details += logAdditionalInfo(collector.additionalInfo, misc_info->other()); ResolverProblem_Ptr problem = new ResolverProblem (what, details); // Uninstall p problem->addSolution (new ProblemSolutionUninstall (problem, item)); -- 2.7.4