- Ignore conflicting items which are uninstallable
authorStefan Schubert <schubi@suse.de>
Wed, 20 Jun 2007 09:47:53 +0000 (09:47 +0000)
committerStefan Schubert <schubi@suse.de>
Wed, 20 Jun 2007 09:47:53 +0000 (09:47 +0000)
- 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
zypp/solver/detail/QueueItemInstall.cc
zypp/solver/detail/QueueItemInstall.h
zypp/solver/detail/QueueItemRequire.cc
zypp/solver/detail/QueueItemUninstall.cc
zypp/solver/detail/ResolverContext.cc
zypp/solver/detail/ResolverContext.h
zypp/solver/detail/ResolverInfoNeededBy.cc
zypp/solver/detail/ResolverInfoNeededBy.h
zypp/solver/detail/Resolver_problems.cc

index 7733448..c83f563 100644 (file)
@@ -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;
            }
index bf0ee53..028db2c 100644 (file)
@@ -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
index d7e85e0..d8f6480 100644 (file)
@@ -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;}
 
 };
 
index ab806dc..a71949e 100644 (file)
@@ -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 );
            }
        }
 
index 1c0b645..c7bac7a 100644 (file)
@@ -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
index 1813491..1d7f79b 100644 (file)
@@ -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<Package>::kind
@@ -1557,7 +1587,7 @@ ResolverContext::requirementIsInstalledOrUnneeded (const ResObject::Kind & kind,
        || kind != ResTraits<Message>::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;
index 41388f7..d07c670 100644 (file)
@@ -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;
index 30f6e33..22155b3 100644 (file)
@@ -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)
 {
 }
 
index 0cac992..29df4af 100644 (file)
@@ -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; }
+;
 };
 
  ///////////////////////////////////////////////////////////////////
index 6581eca..9e3139e 100644 (file)
@@ -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<const ResolverInfoMisc>(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<const ResolverInfoMisc>(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));