Imported Upstream version 16.3.2
[platform/upstream/libzypp.git] / zypp / solver / detail / Resolver.cc
index a3e9fab..7801a50 100644 (file)
  */
 #include <boost/static_assert.hpp>
 
+#define ZYPP_USE_RESOLVER_INTERNALS
+
 #include "zypp/solver/detail/Resolver.h"
-#include "zypp/solver/detail/Helper.h"
 #include "zypp/solver/detail/Testcase.h"
 #include "zypp/solver/detail/SATResolver.h"
+#include "zypp/solver/detail/ItemCapKind.h"
+#include "zypp/solver/detail/SolutionAction.h"
+#include "zypp/solver/detail/SolverQueueItem.h"
 
 #include "zypp/Capabilities.h"
 #include "zypp/ZConfig.h"
 #include "zypp/ResFilters.h"
 #include "zypp/sat/Pool.h"
 #include "zypp/sat/Solvable.h"
+#include "zypp/sat/Transaction.h"
+#include "zypp/ResolverProblem.h"
 
 #define MAXSOLVERRUNS 5
 
+using std::endl;
+using std::make_pair;
+
 /////////////////////////////////////////////////////////////////////////
 namespace zypp
 { ///////////////////////////////////////////////////////////////////////
@@ -48,18 +57,26 @@ namespace zypp
     namespace detail
     { ///////////////////////////////////////////////////////////////////
 
-using namespace std;
-
-IMPL_PTR_TYPE(Resolver);
-
+      //using namespace std;
 
 //---------------------------------------------------------------------------
 
 
-std::ostream &
-Resolver::dumpOn( std::ostream & os ) const
+std::ostream & Resolver::dumpOn( std::ostream & os ) const
 {
-    return os << "<resolver/>";
+  os << "<resolver>" << endl;
+  #define OUTS(t) os << "  " << #t << ":\t" << t << endl;
+  OUTS( _forceResolve );
+  OUTS( _upgradeMode );
+  OUTS( _updateMode );
+  OUTS( _verifying );
+  OUTS( _onlyRequires );
+  OUTS( _allowVendorChange );
+  OUTS( _solveSrcPackages );
+  OUTS( _cleandepsOnRemove );
+  OUTS( _ignoreAlreadyRecommended );
+  #undef OUT
+  return os << "<resolver/>";
 }
 
 
@@ -69,11 +86,15 @@ Resolver::Resolver (const ResPool & pool)
     : _pool(pool)
     , _satResolver(NULL)
     , _poolchanged(_pool.serial() )
-    , _testing(false)
-    , _forceResolve(false)
-    , _upgradeMode(false)
-    , _verifying(false)
-    , _onlyRequires(indeterminate)
+    , _forceResolve            (false)
+    , _upgradeMode             (false)
+    , _updateMode              (false)
+    , _verifying               (false)
+    , _onlyRequires            ( ZConfig::instance().solver_onlyRequires() )
+    , _allowVendorChange       ( ZConfig::instance().solver_allowVendorChange() )
+    , _solveSrcPackages                ( false )
+    , _cleandepsOnRemove       ( ZConfig::instance().solver_cleandepsOnRemove() )
+    , _ignoreAlreadyRecommended        ( true )
 
 {
     sat::Pool satPool( sat::Pool::instance() );
@@ -83,20 +104,48 @@ Resolver::Resolver (const ResPool & pool)
 
 Resolver::~Resolver()
 {
+  delete _satResolver;
 }
 
 //---------------------------------------------------------------------------
+// forward flags too SATResolver
+#define ZOLV_FLAG_TRIBOOL( ZSETTER, ZGETTER, ZVARNAME, ZVARDEFAULT )                   \
+    void Resolver::ZSETTER( TriBool state_r )                                          \
+    { _satResolver->ZVARNAME = indeterminate(state_r) ? ZVARDEFAULT : bool(state_r); } \
+    bool Resolver::ZGETTER() const                                                     \
+    { return _satResolver->ZVARNAME; }                                                 \
+
+ZOLV_FLAG_TRIBOOL( dupSetAllowDowngrade,       dupAllowDowngrade,      _dup_allowdowngrade,    ZConfig::instance().solver_dupAllowDowngrade() )
+ZOLV_FLAG_TRIBOOL( dupSetAllowNameChange,      dupAllowNameChange,     _dup_allownamechange,   ZConfig::instance().solver_dupAllowNameChange() )
+ZOLV_FLAG_TRIBOOL( dupSetAllowArchChange,      dupAllowArchChange,     _dup_allowarchchange,   ZConfig::instance().solver_dupAllowArchChange() )
+ZOLV_FLAG_TRIBOOL( dupSetAllowVendorChange,    dupAllowVendorChange,   _dup_allowvendorchange, ZConfig::instance().solver_dupAllowVendorChange() )
+
+#undef ZOLV_FLAG_TRIBOOL
+//---------------------------------------------------------------------------
 
-ResPool
-Resolver::pool (void) const
+void Resolver::setAllowVendorChange( TriBool state_r )
 {
-    return _pool;
+  _allowVendorChange = indeterminate(state_r) ? ZConfig::instance().solver_allowVendorChange() : bool(state_r);
 }
 
-void
-Resolver::reset (bool keepExtras )
+void Resolver::setOnlyRequires( TriBool state_r )
 {
-    _verifying = false;    
+  _onlyRequires = indeterminate(state_r) ? ZConfig::instance().solver_onlyRequires() : bool(state_r);
+}
+
+void Resolver::setCleandepsOnRemove( TriBool state_r )
+{
+  _cleandepsOnRemove = indeterminate(state_r) ? ZConfig::instance().solver_cleandepsOnRemove() : bool(state_r);
+}
+
+//---------------------------------------------------------------------------
+
+ResPool Resolver::pool() const
+{ return _pool; }
+
+void Resolver::reset( bool keepExtras )
+{
+    _verifying = false;
 
     if (!keepExtras) {
       _extra_requires.clear();
@@ -105,40 +154,39 @@ Resolver::reset (bool keepExtras )
 
     _isInstalledBy.clear();
     _installs.clear();
+    _satifiedByInstalled.clear();
+    _installedSatisfied.clear();
 }
 
-void
-Resolver::doUpdate()
+bool Resolver::doUpgrade()
 {
-    return _satResolver->doUpdate();
+  // Setting Resolver to upgrade mode. SAT solver will do the update
+  _upgradeMode = true;
+  return resolvePool();
 }
 
-void
-Resolver::addExtraRequire (const Capability & capability)
+void Resolver::doUpdate()
 {
-    _extra_requires.insert (capability);
+    _updateMode = true;
+    return _satResolver->doUpdate();
 }
 
-void
-Resolver::removeExtraRequire (const Capability & capability)
-{
-    _extra_requires.erase (capability);
-}
+PoolItemList Resolver::problematicUpdateItems() const
+{ return _satResolver->problematicUpdateItems(); }
 
-void
-Resolver::addExtraConflict (const Capability & capability)
-{
-    _extra_conflicts.insert (capability);
-}
+void Resolver::addExtraRequire( const Capability & capability )
+{ _extra_requires.insert (capability); }
 
-void
-Resolver::removeExtraConflict (const Capability & capability)
-{
-    _extra_conflicts.erase (capability);
-}
+void Resolver::removeExtraRequire( const Capability & capability )
+{ _extra_requires.erase (capability); }
 
+void Resolver::addExtraConflict( const Capability & capability )
+{ _extra_conflicts.insert (capability); }
 
-void Resolver::removeQueueItem (const SolverQueueItem_Ptr item)
+void Resolver::removeExtraConflict( const Capability & capability )
+{ _extra_conflicts.erase (capability); }
+
+void Resolver::removeQueueItem( SolverQueueItem_Ptr item )
 {
     bool found = false;
     for (SolverQueueItemList::const_iterator iter = _added_queue_items.begin();
@@ -154,7 +202,8 @@ void Resolver::removeQueueItem (const SolverQueueItem_Ptr item)
        _removed_queue_items.unique ();
     }
 }
-void Resolver::addQueueItem (const SolverQueueItem_Ptr item)
+
+void Resolver::addQueueItem( SolverQueueItem_Ptr item )
 {
     bool found = false;
     for (SolverQueueItemList::const_iterator iter = _removed_queue_items.begin();
@@ -168,14 +217,11 @@ void Resolver::addQueueItem (const SolverQueueItem_Ptr item)
     if (!found) {
        _added_queue_items.push_back (item);
        _added_queue_items.unique ();
-    }    
+    }
 }
 
-void
-Resolver::addWeak (const PoolItem item)
-{
-    _addWeak.push_back (item);
-}
+void Resolver::addWeak( const PoolItem & item )
+{ _addWeak.push_back( item ); }
 
 //---------------------------------------------------------------------------
 
@@ -209,14 +255,13 @@ struct DoTransact : public resfilter::PoolItemFilterFunctor
 };
 
 
-bool
-Resolver::verifySystem ()
+bool Resolver::verifySystem()
 {
     UndoTransact resetting (ResStatus::APPL_HIGH);
 
-    _DEBUG ("Resolver::verifySystem() ");
-    
-    _verifying = true;    
+    DBG << "Resolver::verifySystem()" << endl;
+
+    _verifying = true;
 
     invokeOnEach ( _pool.begin(), _pool.end(),
                   resfilter::ByTransact( ),                    // Resetting all transcations
@@ -228,9 +273,7 @@ Resolver::verifySystem ()
 
 //----------------------------------------------------------------------------
 // undo
-
-void
-Resolver::undo(void)
+void Resolver::undo()
 {
     UndoTransact info(ResStatus::APPL_LOW);
     MIL << "*** undo ***" << endl;
@@ -242,83 +285,71 @@ Resolver::undo(void)
 
     // Additional QueueItems which has to be regarded by the solver
     _removed_queue_items.clear();
-    _added_queue_items.clear();    
+    _added_queue_items.clear();
 
     return;
 }
 
-void
-Resolver::solverInit()
+void Resolver::solverInit()
 {
-    // Solving with the satsolver
-        static bool poolDumped = false;
-       MIL << "-------------- Calling SAT Solver -------------------" << endl;
-       if ( getenv("ZYPP_FULLLOG") ) {
-           Testcase testcase("/var/log/YaST2/autoTestcase");
-           if (!poolDumped) {
-               testcase.createTestcase (*this, true, false); // dump pool
-               poolDumped = true;
-           } else {
-               testcase.createTestcase (*this, false, false); // write control file only
-           }
+    // Solving with libsolv
+    static bool poolDumped = false;
+    MIL << "-------------- Calling SAT Solver -------------------" << endl;
+    if ( getenv("ZYPP_FULLLOG") ) {
+       Testcase testcase("/var/log/YaST2/autoTestcase");
+       if (!poolDumped) {
+           testcase.createTestcase (*this, true, false); // dump pool
+           poolDumped = true;
+       } else {
+           testcase.createTestcase (*this, false, false); // write control file only
        }
+    }
 
-       _satResolver->setFixsystem(false);
-       _satResolver->setAllowdowngrade(false);
-       _satResolver->setAllowarchchange(false);
-       _satResolver->setAllowvendorchange(false);
-       _satResolver->setAllowuninstall(false);
-       _satResolver->setUpdatesystem(false);
-       _satResolver->setAllowvirtualconflicts(false);
-       _satResolver->setNoupdateprovide(true);
-       _satResolver->setDosplitprovides(false);
-       
-       if (_upgradeMode) {
-           _satResolver->setAllowdowngrade(true);
-           _satResolver->setUpdatesystem(false); // not needed cause packages has already been evaluteted by distupgrade
-           _satResolver->setDosplitprovides(true);   
-       }
+    _satResolver->setFixsystem                 ( isVerifyingMode() );
+    _satResolver->setIgnorealreadyrecommended  ( ignoreAlreadyRecommended() );
+    _satResolver->setOnlyRequires              ( onlyRequires() );
+    _satResolver->setAllowdowngrade            (false);
+    _satResolver->setAllowarchchange           (false);
+    _satResolver->setAllowvendorchange         ( allowVendorChange() );
+    _satResolver->setAllowuninstall            ( forceResolve() );
+    _satResolver->setUpdatesystem              (false);
+    _satResolver->setNoupdateprovide           (false);
+    _satResolver->setDosplitprovides           (true);
+    _satResolver->setSolveSrcPackages          ( solveSrcPackages() );
+    _satResolver->setCleandepsOnRemove         ( cleandepsOnRemove() );
+
+    _satResolver->setDistupgrade               (_upgradeMode);
+    if (_upgradeMode) {
+      // may overwrite some settings
+      _satResolver->setDistupgrade_removeunsupported   (false);
+    }
 
-       if (_forceResolve)
-           _satResolver->setAllowuninstall(true);
-       
-       if (_onlyRequires == indeterminate)
-           _satResolver->setOnlyRequires(ZConfig::instance().solver_onlyRequires());
-       else if (_onlyRequires)
-           _satResolver->setOnlyRequires(true);
-       else
-           _satResolver->setOnlyRequires(false);
-
-       if (_verifying)
-           _satResolver->setFixsystem(true);
-
-       // Resetting additional solver information
-       _isInstalledBy.clear();
-       _installs.clear();
-       
+    // Resetting additional solver information
+    _isInstalledBy.clear();
+    _installs.clear();
+    _satifiedByInstalled.clear();
+    _installedSatisfied.clear();
 }
 
-bool
-Resolver::resolvePool()
+bool Resolver::resolvePool()
 {
     solverInit();
-    return _satResolver->resolvePool(_extra_requires, _extra_conflicts, _addWeak);
+    return _satResolver->resolvePool(_extra_requires, _extra_conflicts, _addWeak, _upgradeRepos );
 }
 
-bool
-Resolver::resolveQueue(solver::detail::SolverQueueItemList & queue)
+bool Resolver::resolveQueue( solver::detail::SolverQueueItemList & queue )
 {
     solverInit();
-    
+
     // add/remove additional SolverQueueItems
     for (SolverQueueItemList::const_iterator iter = _removed_queue_items.begin();
         iter != _removed_queue_items.end(); iter++) {
        for (SolverQueueItemList::const_iterator iterQueue = queue.begin(); iterQueue != queue.end(); iterQueue++) {
-           if ( (*iterQueue)->cmp(*iter) == 0) {           
+           if ( (*iterQueue)->cmp(*iter) == 0) {
                MIL << "remove from queue" << *iter;
                queue.remove(*iterQueue);
                break;
-           }       
+           }
        }
     }
 
@@ -329,10 +360,10 @@ Resolver::resolveQueue(solver::detail::SolverQueueItemList & queue)
            if ( (*iterQueue)->cmp(*iter) == 0) {
                found = true;
                break;
-           }       
+           }
        }
        if (!found) {
-           MIL << "add to queue" << *iter;         
+           MIL << "add to queue" << *iter;
            queue.push_back(*iter);
        }
     }
@@ -341,117 +372,73 @@ Resolver::resolveQueue(solver::detail::SolverQueueItemList & queue)
     // give the user a chance for changing these decisions again.
     _removed_queue_items.clear();
     _added_queue_items.clear();
-    
+
     return _satResolver->resolveQueue(queue, _addWeak);
 }
 
+sat::Transaction Resolver::getTransaction()
+{
+  // FIXME: That's an ugly way of pushing autoInstalled into the transaction.
+  sat::Transaction ret( sat::Transaction::loadFromPool );
+  ret.autoInstalled( _satResolver->autoInstalled() );
+  return ret;
+}
 
 
-///////////////////////////////////////////////////////////////////
-//
-//
-//     METHOD NAME : Resolver::checkUnmaintainedItems
-//     METHOD TYPE : 
-//
-//     DESCRIPTION : Unmaintained packages which does not fit to 
-//                    the updated system (broken dependencies) will be
-//                    deleted.
-//                    returns true if solving was successful
-//
-bool Resolver::checkUnmaintainedItems () {
-    int solverRuns = 1;
-    bool solverRet = resolvePool();
-    MIL << "Checking unmaintained items....." << endl;
-
-    while (!solverRet && solverRuns++ < MAXSOLVERRUNS) {
-       ResolverProblemList problemList = problems();
-       ProblemSolutionList solutionList;
-       PoolItemList problemItemList;   
-
-       for (ResolverProblemList::iterator iter = problemList.begin(); iter != problemList.end(); ++iter) {
-           ResolverProblem problem = **iter;
-           DBG << "Problem:" << endl;
-           DBG << problem.description() << endl;
-           DBG << problem.details() << endl;
-
-           ProblemSolutionList solutions = problem.solutions();
-           for (ProblemSolutionList::const_iterator iterSolution = solutions.begin();
-                iterSolution != solutions.end(); ++iterSolution) {
-               ProblemSolution_Ptr solution = *iterSolution;
-               DBG << "   Solution:" << endl;
-               DBG << "      " << solution->description() << endl;
-               DBG << "      " << solution->details() << endl;         
-               solver::detail::CSolutionActionList actionList = solution->actions();
-               bool fitUnmaintained = false;
-               PoolItemList deletedItems;
-               for (CSolutionActionList::const_iterator iterActions = actionList.begin();
-                    iterActions != actionList.end(); ++iterActions) {
-                   TransactionSolutionAction_constPtr transactionAction = dynamic_pointer_cast<const TransactionSolutionAction>(*iterActions);
-                   if (transactionAction &&
-                       transactionAction->action() == REMOVE
-                       && _unmaintained_items.find(transactionAction->item()) != _unmaintained_items.end()) {
-                       // The solution contains unmaintained items ONLY which will be deleted. So take this solution
-                       fitUnmaintained = true;
-                       deletedItems.push_back (transactionAction->item());
-                   } else {
-                       fitUnmaintained = false;
-                   }
-               }
-               if (fitUnmaintained) {
-                   MIL << "Problem:" << endl;
-                   MIL << problem.description() << endl;
-                   MIL << problem.details() << endl;
-                   MIL << "Will be solved by removing unmaintained package(s)............" << endl;
-                   MIL << "   Solution:" << endl;
-                   MIL << "      " << solution->description() << endl;
-                   MIL << "      " << solution->details() << endl;                                 
-                   solutionList.push_back (solution);
-                   problemItemList.insert (problemItemList.end(), deletedItems.begin(), deletedItems.end() );
-                   break; // not regarding the other solutions
-               }
-           }
-       }
+//----------------------------------------------------------------------------
+// Getting more information about the solve results
 
-       if (!solutionList.empty()) {
-           applySolutions (solutionList);
-           // list of problematic items after doUpgrade() which is show to the user
-           _problem_items.insert (_problem_items.end(), problemItemList.begin(), problemItemList.end());
-           _problem_items.unique();
-       } else {
-           // break cause there is no other solution available by the next run
-           solverRuns = MAXSOLVERRUNS;
-       }
-       // next try
-       solverRet = resolvePool();      
-    }
-    return solverRet;
+ResolverProblemList Resolver::problems() const
+{
+  MIL << "Resolver::problems()" << endl;
+  return _satResolver->problems();
+}
+
+void Resolver::applySolutions( const ProblemSolutionList & solutions )
+{
+  for ( ProblemSolution_Ptr solution : solutions )
+  {
+    if ( ! applySolution( *solution ) )
+      break;
+  }
 }
 
+bool Resolver::applySolution( const ProblemSolution & solution )
+{
+  bool ret = true;
+  DBG << "apply solution " << solution << endl;
+  for ( SolutionAction_Ptr action : solution.actions() )
+  {
+    if ( ! action->execute( *this ) )
+    {
+      WAR << "apply solution action failed: " << action << endl;
+      ret = false;
+      break;
+    }
+  }
+  return ret;
+}
 
 //----------------------------------------------------------------------------
-// Getting more information about the solve results
-
 
-void
-Resolver::collectResolverInfo(void)
+void Resolver::collectResolverInfo()
 {
     if ( _satResolver
         && _isInstalledBy.empty()
         && _installs.empty()) {
-       
+
        // generating new
        PoolItemList itemsToInstall = _satResolver->resultItemsToInstall();
 
        for (PoolItemList::const_iterator instIter = itemsToInstall.begin();
             instIter != itemsToInstall.end(); instIter++) {
-
            // Requires
            for (Capabilities::const_iterator capIt = (*instIter)->dep (Dep::REQUIRES).begin(); capIt != (*instIter)->dep (Dep::REQUIRES).end(); ++capIt)
            {
                sat::WhatProvides possibleProviders(*capIt);
                for_( iter, possibleProviders.begin(), possibleProviders.end() ) {
                    PoolItem provider = ResPool::instance().find( *iter );
-                   
+
                    // searching if this provider will already be installed
                    bool found = false;
                    bool alreadySetForInstallation = false;
@@ -461,7 +448,7 @@ Resolver::collectResolverInfo(void)
                           && !found) {
                        alreadySetForInstallation = true;
                        ItemCapKind capKind = pos->second;
-                       if (capKind.item == *instIter)  found = true;
+                       if (capKind.item() == *instIter)  found = true;
                        pos++;
                    }
 
@@ -472,83 +459,118 @@ Resolver::collectResolverInfo(void)
                            _isInstalledBy.insert (make_pair( provider, capKindisInstalledBy));
                        } else {
                            // no initial installation cause it has been set be e.g. user
-                           ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::REQUIRES, false ); 
-                           _isInstalledBy.insert (make_pair( provider, capKindisInstalledBy));                     
+                           ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::REQUIRES, false );
+                           _isInstalledBy.insert (make_pair( provider, capKindisInstalledBy));
                        }
                        ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::REQUIRES, !alreadySetForInstallation );
-                       _installs.insert (make_pair( *instIter, capKindisInstalledBy));                 
+                       _installs.insert (make_pair( *instIter, capKindisInstalledBy));
+                   }
+
+                   if (provider.status().staysInstalled()) { // Is already satisfied by an item which is installed
+                       ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::REQUIRES, false );
+                       _satifiedByInstalled.insert (make_pair( *instIter, capKindisInstalledBy));
+
+                       ItemCapKind installedSatisfied( *instIter, *capIt, Dep::REQUIRES, false );
+                       _installedSatisfied.insert (make_pair( provider, installedSatisfied));
                    }
                }
            }
-           
-           //Recommends
-           for (Capabilities::const_iterator capIt = (*instIter)->dep (Dep::RECOMMENDS).begin(); capIt != (*instIter)->dep (Dep::RECOMMENDS).end(); ++capIt)
-           {
-               sat::WhatProvides possibleProviders(*capIt);
-               for_( iter, possibleProviders.begin(), possibleProviders.end() ) {
-                   PoolItem provider = ResPool::instance().find( *iter );
-                   
-                   // searching if this provider will already be installed
-                   bool found = false;
-                   bool alreadySetForInstallation = false;
-                   ItemCapKindMap::const_iterator pos = _isInstalledBy.find(provider);
-                   while (pos != _isInstalledBy.end()
-                          && pos->first == provider
-                          && !found) {
-                       alreadySetForInstallation = true;
-                       ItemCapKind capKind = pos->second;
-                       if (capKind.item == *instIter)  found = true;
-                       pos++;
-                   }
 
-                   if (!found
-                       && provider.status().isToBeInstalled()) {
-                       if (provider.status().isBySolver()) {
-                           ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::RECOMMENDS, !alreadySetForInstallation );
-                           _isInstalledBy.insert (make_pair( provider, capKindisInstalledBy));
-                       } else {
-                           // no initial installation cause it has been set be e.g. user
-                           ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::RECOMMENDS, false ); 
-                           _isInstalledBy.insert (make_pair( provider, capKindisInstalledBy));                     
+           if (!(_satResolver->onlyRequires())) {
+               //Recommends
+               for (Capabilities::const_iterator capIt = (*instIter)->dep (Dep::RECOMMENDS).begin(); capIt != (*instIter)->dep (Dep::RECOMMENDS).end(); ++capIt)
+               {
+                   sat::WhatProvides possibleProviders(*capIt);
+                   for_( iter, possibleProviders.begin(), possibleProviders.end() ) {
+                       PoolItem provider = ResPool::instance().find( *iter );
+
+                       // searching if this provider will already be installed
+                       bool found = false;
+                       bool alreadySetForInstallation = false;
+                       ItemCapKindMap::const_iterator pos = _isInstalledBy.find(provider);
+                       while (pos != _isInstalledBy.end()
+                              && pos->first == provider
+                              && !found) {
+                           alreadySetForInstallation = true;
+                           ItemCapKind capKind = pos->second;
+                           if (capKind.item() == *instIter)  found = true;
+                           pos++;
+                       }
+
+                       if (!found
+                           && provider.status().isToBeInstalled()) {
+                           if (provider.status().isBySolver()) {
+                               ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::RECOMMENDS, !alreadySetForInstallation );
+                               _isInstalledBy.insert (make_pair( provider, capKindisInstalledBy));
+                           } else {
+                               // no initial installation cause it has been set be e.g. user
+                               ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::RECOMMENDS, false );
+                               _isInstalledBy.insert (make_pair( provider, capKindisInstalledBy));
+                           }
+                           ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::RECOMMENDS, !alreadySetForInstallation );
+                           _installs.insert (make_pair( *instIter, capKindisInstalledBy));
+                       }
+
+                       if (provider.status().staysInstalled()) { // Is already satisfied by an item which is installed
+                           ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::RECOMMENDS, false );
+                           _satifiedByInstalled.insert (make_pair( *instIter, capKindisInstalledBy));
+
+                           ItemCapKind installedSatisfied( *instIter, *capIt, Dep::RECOMMENDS, false );
+                           _installedSatisfied.insert (make_pair( provider, installedSatisfied));
                        }
-                       ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::RECOMMENDS, !alreadySetForInstallation );
-                       _installs.insert (make_pair( *instIter, capKindisInstalledBy));                 
                    }
                }
-           }
 
-           //Suggests
-           for (Capabilities::const_iterator capIt = (*instIter)->dep (Dep::SUGGESTS).begin(); capIt != (*instIter)->dep (Dep::SUGGESTS).end(); ++capIt)
-           {
-               sat::WhatProvides possibleProviders(*capIt);
-               for_( iter, possibleProviders.begin(), possibleProviders.end() ) {
-                   PoolItem provider = ResPool::instance().find( *iter );
-                   
-                   // searching if this provider will already be installed
-                   bool found = false;
-                   bool alreadySetForInstallation = false;
-                   ItemCapKindMap::const_iterator pos = _isInstalledBy.find(provider);
-                   while (pos != _isInstalledBy.end()
-                          && pos->first == provider
-                          && !found) {
-                       alreadySetForInstallation = true;
-                       ItemCapKind capKind = pos->second;
-                       if (capKind.item == *instIter)  found = true;
-                       pos++;
-                   }
+               //Supplements
+               for (Capabilities::const_iterator capIt = (*instIter)->dep (Dep::SUPPLEMENTS).begin(); capIt != (*instIter)->dep (Dep::SUPPLEMENTS).end(); ++capIt)
+               {
+                   sat::WhatProvides possibleProviders(*capIt);
+                   for_( iter, possibleProviders.begin(), possibleProviders.end() ) {
+                       PoolItem provider = ResPool::instance().find( *iter );
+                       // searching if this item will already be installed
+                       bool found = false;
+                       bool alreadySetForInstallation = false;
+                       ItemCapKindMap::const_iterator pos = _isInstalledBy.find(*instIter);
+                       while (pos != _isInstalledBy.end()
+                              && pos->first == *instIter
+                              && !found) {
+                           alreadySetForInstallation = true;
+                           ItemCapKind capKind = pos->second;
+                           if (capKind.item() == provider)  found = true;
+                           pos++;
+                       }
+
+                       if (!found
+                           && instIter->status().isToBeInstalled()) {
+                           if (instIter->status().isBySolver()) {
+                               ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::SUPPLEMENTS, !alreadySetForInstallation );
+                               _isInstalledBy.insert (make_pair( *instIter, capKindisInstalledBy));
+                           } else {
+                               // no initial installation cause it has been set be e.g. user
+                               ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::SUPPLEMENTS, false );
+                               _isInstalledBy.insert (make_pair( *instIter, capKindisInstalledBy));
+                           }
+                           ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::SUPPLEMENTS, !alreadySetForInstallation );
+                           _installs.insert (make_pair( provider, capKindisInstalledBy));
+                       }
 
-                   if (!found) {
-                       ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::SUGGESTS, !alreadySetForInstallation );
-                       _isInstalledBy.insert (make_pair( provider, capKindisInstalledBy));
+                       if (instIter->status().staysInstalled()) { // Is already satisfied by an item which is installed
+                           ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::SUPPLEMENTS, !alreadySetForInstallation );
+                           _satifiedByInstalled.insert (make_pair( provider, capKindisInstalledBy));
+
+                           ItemCapKind installedSatisfied( provider, *capIt, Dep::SUPPLEMENTS, false );
+                           _installedSatisfied.insert (make_pair( *instIter, installedSatisfied));
+                       }
                    }
                }
-           }               
+           }
        }
     }
 }
 
 
-const ItemCapKindList Resolver::isInstalledBy (const PoolItem item) {
+ItemCapKindList Resolver::isInstalledBy( const PoolItem & item )
+{
     ItemCapKindList ret;
     collectResolverInfo();
 
@@ -566,7 +588,8 @@ const ItemCapKindList Resolver::isInstalledBy (const PoolItem item) {
     return ret;
 }
 
-const ItemCapKindList Resolver::installs (const PoolItem item) {
+ItemCapKindList Resolver::installs( const PoolItem & item )
+{
     ItemCapKindList ret;
     collectResolverInfo();
 
@@ -584,7 +607,43 @@ const ItemCapKindList Resolver::installs (const PoolItem item) {
     return ret;
 }
 
+ItemCapKindList Resolver::satifiedByInstalled( const PoolItem & item )
+{
+    ItemCapKindList ret;
+    collectResolverInfo();
 
+    for (ItemCapKindMap::const_iterator iter = _satifiedByInstalled.find(item); iter != _satifiedByInstalled.end();) {
+       ItemCapKind info = iter->second;
+       PoolItem iterItem = iter->first;
+       if (iterItem == item) {
+           ret.push_back(info);
+           iter++;
+       } else {
+           // exit
+           iter = _satifiedByInstalled.end();
+       }
+    }
+    return ret;
+}
+
+ItemCapKindList Resolver::installedSatisfied( const PoolItem & item )
+{
+    ItemCapKindList ret;
+    collectResolverInfo();
+
+    for (ItemCapKindMap::const_iterator iter = _installedSatisfied.find(item); iter != _installedSatisfied.end();) {
+       ItemCapKind info = iter->second;
+       PoolItem iterItem = iter->first;
+       if (iterItem == item) {
+           ret.push_back(info);
+           iter++;
+       } else {
+           // exit
+           iter = _installedSatisfied.end();
+       }
+    }
+    return ret;
+}
 
 
 ///////////////////////////////////////////////////////////////////