Imported Upstream version 16.3.2
[platform/upstream/libzypp.git] / zypp / solver / detail / SATResolver.cc
index 677eee2..1a3c92d 100644 (file)
@@ -29,7 +29,8 @@ extern "C"
 #include <solv/queue.h>
 }
 
-#include "zypp/solver/detail/Helper.h"
+#define ZYPP_USE_RESOLVER_INTERNALS
+
 #include "zypp/base/String.h"
 #include "zypp/Product.h"
 #include "zypp/Capability.h"
@@ -45,15 +46,22 @@ extern "C"
 #include "zypp/sat/Pool.h"
 #include "zypp/sat/WhatProvides.h"
 #include "zypp/sat/WhatObsoletes.h"
+#include "zypp/solver/detail/Resolver.h"
 #include "zypp/solver/detail/SATResolver.h"
 #include "zypp/solver/detail/ProblemSolutionCombi.h"
 #include "zypp/solver/detail/ProblemSolutionIgnore.h"
 #include "zypp/solver/detail/SolverQueueItemInstall.h"
 #include "zypp/solver/detail/SolverQueueItemDelete.h"
 #include "zypp/solver/detail/SystemCheck.h"
+#include "zypp/solver/detail/SolutionAction.h"
+#include "zypp/solver/detail/SolverQueueItem.h"
 #include "zypp/sat/Transaction.h"
 #include "zypp/sat/Queue.h"
 
+#include "zypp/sat/detail/PoolImpl.h"
+
+#define XDEBUG(x) do { if (base::logger::isExcessive()) XXX << x << std::endl;} while (0)
+
 /////////////////////////////////////////////////////////////////////////
 namespace zypp
 { ///////////////////////////////////////////////////////////////////////
@@ -176,10 +184,6 @@ SATResolver::SATResolver (const ResPool & pool, sat::detail::CPool *satPool)
     , _allowarchchange(false)
     , _allowvendorchange(ZConfig::instance().solver_allowVendorChange())
     , _allowuninstall(false)
-    , _dup_allowdowngrade( true )
-    , _dup_allownamechange( true )
-    , _dup_allowarchchange( true )
-    , _dup_allowvendorchange( true )
     , _updatesystem(false)
     , _noupdateprovide(false)
     , _dosplitprovides(true)
@@ -187,6 +191,10 @@ SATResolver::SATResolver (const ResPool & pool, sat::detail::CPool *satPool)
     , _ignorealreadyrecommended(true)
     , _distupgrade(false)
     , _distupgrade_removeunsupported(false)
+    , _dup_allowdowngrade      ( ZConfig::instance().solver_dupAllowDowngrade() )
+    , _dup_allownamechange     ( ZConfig::instance().solver_dupAllowNameChange() )
+    , _dup_allowarchchange     ( ZConfig::instance().solver_dupAllowArchChange() )
+    , _dup_allowvendorchange   ( ZConfig::instance().solver_dupAllowVendorChange() )
     , _solveSrcPackages(false)
     , _cleandepsOnRemove(ZConfig::instance().solver_cleandepsOnRemove())
 {
@@ -206,102 +214,6 @@ SATResolver::pool (void) const
     return _pool;
 }
 
-void
-SATResolver::resetItemTransaction (PoolItem item)
-{
-    bool found = false;
-    for (PoolItemList::const_iterator iter = _items_to_remove.begin();
-        iter != _items_to_remove.end(); ++iter) {
-       if (*iter == item) {
-           _items_to_remove.remove(*iter);
-           found = true;
-           break;
-       }
-    }
-    if (!found) {
-       for (PoolItemList::const_iterator iter = _items_to_install.begin();
-            iter != _items_to_install.end(); ++iter) {
-           if (*iter == item) {
-               _items_to_install.remove(*iter);
-               found = true;
-               break;
-           }
-       }
-    }
-    if (!found) {
-       for (PoolItemList::const_iterator iter = _items_to_keep.begin();
-            iter != _items_to_keep.end(); ++iter) {
-           if (*iter == item) {
-               _items_to_keep.remove(*iter);
-               found = true;
-               break;
-           }
-       }
-    }
-    if (!found) {
-       for (PoolItemList::const_iterator iter = _items_to_lock.begin();
-            iter != _items_to_lock.end(); ++iter) {
-           if (*iter == item) {
-               _items_to_lock.remove(*iter);
-               found = true;
-               break;
-           }
-       }
-    }
-}
-
-
-void
-SATResolver::addPoolItemToInstall (PoolItem item)
-{
-    resetItemTransaction (item);
-    _items_to_install.push_back (item);
-    _items_to_install.unique ();
-}
-
-
-void
-SATResolver::addPoolItemsToInstallFromList (PoolItemList & rl)
-{
-    for (PoolItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) {
-       addPoolItemToInstall (*iter);
-    }
-}
-
-
-void
-SATResolver::addPoolItemToRemove (PoolItem item)
-{
-    resetItemTransaction (item);
-    _items_to_remove.push_back (item);
-    _items_to_remove.unique ();
-}
-
-
-void
-SATResolver::addPoolItemsToRemoveFromList (PoolItemList & rl)
-{
-    for (PoolItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) {
-       addPoolItemToRemove (*iter);
-    }
-}
-
-void
-SATResolver::addPoolItemToLock (PoolItem item)
-{
-    resetItemTransaction (item);
-    _items_to_lock.push_back (item);
-    _items_to_lock.unique ();
-}
-
-void
-SATResolver::addPoolItemToKeep (PoolItem item)
-{
-    resetItemTransaction (item);
-    _items_to_keep.push_back (item);
-    _items_to_keep.unique ();
-}
-
 //---------------------------------------------------------------------------
 
 // copy marked item from solution back to pool
@@ -319,15 +231,15 @@ SATSolutionToPool (PoolItem item, const ResStatus & status, const ResStatus::Tra
     // installation/deletion
     if (status.isToBeInstalled()) {
        r = item.status().setToBeInstalled (causer);
-       _XDEBUG("SATSolutionToPool install returns " << item << ", " << r);
+       XDEBUG("SATSolutionToPool install returns " << item << ", " << r);
     }
     else if (status.isToBeUninstalledDueToUpgrade()) {
        r = item.status().setToBeUninstalledDueToUpgrade (causer);
-       _XDEBUG("SATSolutionToPool upgrade returns " << item << ", " <<  r);
+       XDEBUG("SATSolutionToPool upgrade returns " << item << ", " <<  r);
     }
     else if (status.isToBeUninstalled()) {
        r = item.status().setToBeUninstalled (causer);
-       _XDEBUG("SATSolutionToPool remove returns " << item << ", " <<  r);
+       XDEBUG("SATSolutionToPool remove returns " << item << ", " <<  r);
     }
 
     return;
@@ -338,65 +250,71 @@ SATSolutionToPool (PoolItem item, const ResStatus & status, const ResStatus::Tra
 // resolvePool
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
-
-//----------------------------------------------------------------------------
-// Helper functions for the ZYPP-Pool
-//----------------------------------------------------------------------------
-
-
-//------------------------------------------------------------------------------------------------------------
-//  This function loops over the pool and grabs all items
-//  It clears all previous bySolver() states also
-//
-//  Every toBeInstalled is passed to zypp::solver:detail::Resolver.addPoolItemToInstall()
-//  Every toBeUninstalled is passed to zypp::solver:detail::Resolver.addPoolItemToRemove()
-//
-//  Solver results must be written back to the pool.
-//------------------------------------------------------------------------------------------------------------
-
-
+/////////////////////////////////////////////////////////////////////////
+/// \class SATCollectTransact
+/// \brief Commit helper functor distributing PoolItem by status into lists
+///
+/// On the fly it clears all PoolItem bySolver/ByApplLow status.
+/// The lists are cleared in the Ctor, populated by \ref operator().
+/////////////////////////////////////////////////////////////////////////
 struct SATCollectTransact : public resfilter::PoolItemFilterFunctor
 {
-    SATResolver & resolver;
+  SATCollectTransact( PoolItemList & items_to_install_r,
+                     PoolItemList & items_to_remove_r,
+                     PoolItemList & items_to_lock_r,
+                     PoolItemList & items_to_keep_r,
+                     bool solveSrcPackages_r )
+  : _items_to_install( items_to_install_r )
+  , _items_to_remove( items_to_remove_r )
+  , _items_to_lock( items_to_lock_r )
+  , _items_to_keep( items_to_keep_r )
+  , _solveSrcPackages( solveSrcPackages_r )
+  {
+    _items_to_install.clear();
+    _items_to_remove.clear();
+    _items_to_lock.clear();
+    _items_to_keep.clear();
+  }
 
-    SATCollectTransact (SATResolver & r)
-       : resolver (r)
-    { }
+  bool operator()( const PoolItem & item_r )
+  {
+
+    ResStatus & itemStatus( item_r.status() );
+    bool by_solver = ( itemStatus.isBySolver() || itemStatus.isByApplLow() );
 
-    bool operator()( PoolItem item )           // only transacts() items go here
+    if ( by_solver )
     {
-       ResStatus status = item.status();
-       bool by_solver = (status.isBySolver() || status.isByApplLow());
+      // Clear former solver/establish resultd
+      itemStatus.resetTransact( ResStatus::APPL_LOW );
+      return true;     // -> back out here, don't re-queue former results
+    }
 
-       if (by_solver) {
-           item.status().resetTransact( ResStatus::APPL_LOW );// clear any solver/establish transactions
-           return true;                                // back out here, dont re-queue former solver result
-       }
+    if ( !_solveSrcPackages && item_r.isKind<SrcPackage>() )
+    {
+      // Later we may continue on a per source package base.
+      return true; // dont process this source package.
+    }
 
-       if ( item.satSolvable().isKind<SrcPackage>() && ! resolver.solveSrcPackages() )
-       {
-         // Later we may continue on a per source package base.
-         return true; // dont process this source package.
-       }
+    switch ( itemStatus.getTransactValue() )
+    {
+      case ResStatus::TRANSACT:
+       itemStatus.isUninstalled() ?    _items_to_install.push_back( item_r )
+                                  :    _items_to_remove.push_back( item_r );   break;
+      case ResStatus::LOCKED:          _items_to_lock.push_back( item_r );     break;
+      case ResStatus::KEEP_STATE:      _items_to_keep.push_back( item_r );     break;
+    }
+    return true;
+  }
 
-       if (status.isToBeInstalled()) {
-           resolver.addPoolItemToInstall(item);        // -> install!
-       }
-       else if (status.isToBeUninstalled()) {
-           resolver.addPoolItemToRemove(item);         // -> remove !
-       }
-        else if (status.isLocked()
-                && !by_solver) {
-           resolver.addPoolItemToLock (item);
-        }
-        else if (status.isKept()
-                && !by_solver) {
-           resolver.addPoolItemToKeep (item);
-        }
+private:
+  PoolItemList & _items_to_install;
+  PoolItemList & _items_to_remove;
+  PoolItemList & _items_to_lock;
+  PoolItemList & _items_to_keep;
+  bool _solveSrcPackages;
 
-       return true;
-    }
 };
+/////////////////////////////////////////////////////////////////////////
 
 
 //----------------------------------------------------------------------------
@@ -410,22 +328,20 @@ class CheckIfUpdate : public resfilter::PoolItemFilterFunctor
 {
   public:
     bool is_updated;
-    bool multiversion;
     sat::Solvable _installed;
 
-    CheckIfUpdate( sat::Solvable installed_r )
-       : is_updated( false )
-        , multiversion( installed_r.multiversionInstall() )
-        , _installed( installed_r )
+    CheckIfUpdate( const sat::Solvable & installed_r )
+    : is_updated( false )
+    , _installed( installed_r )
     {}
 
     // check this item will be updated
 
-    bool operator()( PoolItem item )
+    bool operator()( const PoolItem & item )
     {
        if ( item.status().isToBeInstalled() )
         {
-          if ( ! multiversion || sameNVRA( _installed, item ) )
+          if ( ! item.multiversionInstall() || sameNVRA( _installed, item ) )
           {
             is_updated = true;
             return false;
@@ -496,7 +412,7 @@ SATResolver::solving(const CapabilitySet & requires_caps,
     HACKENV( SOLVER_FLAG_DUP_ALLOW_VENDORCHANGE,_dup_allowvendorchange );
 #undef HACKENV
 #endif
-    sat::Pool::instance().prepareForSolving();
+    sat::Pool::instance().prepare();
 
     // Solve !
     MIL << "Starting solving...." << endl;
@@ -521,7 +437,7 @@ SATResolver::solving(const CapabilitySet & requires_caps,
 
       PoolItem poolItem( slv );
       SATSolutionToPool (poolItem, ResStatus::toBeInstalled, ResStatus::SOLVER);
-      _result_items_to_install.push_back (poolItem);
+      _result_items_to_install.push_back( poolItem );
     }
     queue_free(&decisionq);
 
@@ -628,13 +544,13 @@ SATResolver::solving(const CapabilitySet & requires_caps,
 
        if (flags.elements[i] == -1) {
            item.status().setNonRelevant();
-           _XDEBUG("SATSolutionToPool(" << item << " ) nonRelevant !");
+           XDEBUG("SATSolutionToPool(" << item << " ) nonRelevant !");
        } else if (flags.elements[i] == 1) {
            item.status().setSatisfied();
-           _XDEBUG("SATSolutionToPool(" << item << " ) satisfied !");
+           XDEBUG("SATSolutionToPool(" << item << " ) satisfied !");
        } else if (flags.elements[i] == 0) {
            item.status().setBroken();
-           _XDEBUG("SATSolutionToPool(" << item << " ) broken !");
+           XDEBUG("SATSolutionToPool(" << item << " ) broken !");
        }
     }
     queue_free(&(solvableQueue));
@@ -678,21 +594,18 @@ SATResolver::solving(const CapabilitySet & requires_caps,
 void
 SATResolver::solverInit(const PoolItemList & weakItems)
 {
-    SATCollectTransact info (*this);
 
     MIL << "SATResolver::solverInit()" << endl;
 
     // remove old stuff
     solverEnd();
-
     queue_init( &_jobQueue );
-    _items_to_install.clear();
-    _items_to_remove.clear();
-    _items_to_lock.clear();
-    _items_to_keep.clear();
 
-    invokeOnEach ( _pool.begin(), _pool.end(),
-                  functor::functorRef<bool,PoolItem>(info) );
+    // clear and rebuild: _items_to_install, _items_to_remove, _items_to_lock, _items_to_keep
+    {
+      SATCollectTransact collector( _items_to_install, _items_to_remove, _items_to_lock, _items_to_keep, solveSrcPackages() );
+      invokeOnEach ( _pool.begin(), _pool.end(), functor::functorRef<bool,PoolItem>( collector ) );
+    }
 
     for (PoolItemList::const_iterator iter = weakItems.begin(); iter != weakItems.end(); iter++) {
        Id id = (*iter)->satSolvable().id();
@@ -704,11 +617,25 @@ SATResolver::solverInit(const PoolItemList & weakItems)
         queue_push( &(_jobQueue), id );
     }
 
+    // Ad rules for changed requestedLocales
+    const auto & trackedLocaleIds( myPool().trackedLocaleIds() );
+    for ( const auto & locale : trackedLocaleIds.added() )
+    {
+      queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES );
+      queue_push( &(_jobQueue), Capability( ResolverNamespace::language, IdString(locale) ).id() );
+    }
+
+    for ( const auto & locale : trackedLocaleIds.removed() )
+    {
+      queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE_PROVIDES | SOLVER_CLEANDEPS );  // needs uncond. SOLVER_CLEANDEPS!
+      queue_push( &(_jobQueue), Capability( ResolverNamespace::language, IdString(locale) ).id() );
+    }
+
     // Add rules for parallel installable resolvables with different versions
-    for_( it, sat::Pool::instance().multiversionBegin(), sat::Pool::instance().multiversionEnd() )
+    for ( const sat::Solvable & solv : myPool().multiversionList() )
     {
-      queue_push( &(_jobQueue), SOLVER_NOOBSOLETES | SOLVER_SOLVABLE_NAME );
-      queue_push( &(_jobQueue), it->id() );
+      queue_push( &(_jobQueue), SOLVER_NOOBSOLETES | SOLVER_SOLVABLE );
+      queue_push( &(_jobQueue), solv.id() );
     }
 
     ::pool_add_userinstalled_jobs(_satPool, sat::Pool::instance().autoInstalled(), &(_jobQueue), GET_USERINSTALLED_NAMES|GET_USERINSTALLED_INVERTED);
@@ -911,7 +838,7 @@ void SATResolver::doUpdate()
     solver_set_flag(_satSolver, SOLVER_FLAG_NO_UPDATEPROVIDE, _noupdateprovide);
     solver_set_flag(_satSolver, SOLVER_FLAG_IGNORE_RECOMMENDED, _onlyRequires);
 
-    sat::Pool::instance().prepareForSolving();
+    sat::Pool::instance().prepare();
 
     // Solve !
     MIL << "Starting solving for update...." << endl;
@@ -1123,7 +1050,7 @@ string SATResolver::SATprobleminfoString(Id problem, string &detail, Id &ignoreI
              bool found = false;
              for_( iter2, possibleProviders.begin(), possibleProviders.end() ) {
                  PoolItem provider2 = ResPool::instance().find( *iter2 );
-                 if (compareByNVR (provider1.resolvable(),provider2.resolvable()) == 0
+                 if (compareByNVR (provider1,provider2) == 0
                      && ( (provider1.status().isInstalled() && provider2.status().isUninstalled())
                          || (provider2.status().isInstalled() && provider1.status().isUninstalled()) ))  {
                      found = true;
@@ -1150,8 +1077,10 @@ string SATResolver::SATprobleminfoString(Id problem, string &detail, Id &ignoreI
          }
          if (providerlistUninstalled.size() > 0) {
              if (detail.size() > 0)
+                 // translators: 'uninstallable' == 'not installable'
                  detail += _("\nuninstallable providers: ");
              else
+                 // translators: 'uninstallable' == 'not installable'
                  detail = _("uninstallable providers: ");
              for (ProviderList::const_iterator iter = providerlistUninstalled.begin(); iter != providerlistUninstalled.end(); iter++) {
                  if (iter == providerlistUninstalled.begin())
@@ -1196,7 +1125,7 @@ SATResolver::problems ()
            solution = 0;
            while ((solution = solver_next_solution(_satSolver, problem, solution)) != 0) {
                element = 0;
-               ProblemSolutionCombi *problemSolution = new ProblemSolutionCombi(resolverProblem);
+               ProblemSolutionCombi *problemSolution = new ProblemSolutionCombi;
                while ((element = solver_next_solutionelement(_satSolver, problem, solution, element, &p, &rp)) != 0) {
                    if (p == SOLVER_SOLUTION_JOB) {
                        /* job, rp is index into job queue */
@@ -1438,7 +1367,7 @@ SATResolver::problems ()
            if (ignoreId > 0) {
                // There is a possibility to ignore this error by setting weak dependencies
                PoolItem item = _pool.find (sat::Solvable(ignoreId));
-               ProblemSolutionIgnore *problemSolution = new ProblemSolutionIgnore(resolverProblem, item);
+               ProblemSolutionIgnore *problemSolution = new ProblemSolutionIgnore(item);
                resolverProblem->addSolution (problemSolution,
                                              false); // Solutions will be shown at the end
                MIL << "ignore some dependencies of " << item << endl;
@@ -1452,17 +1381,8 @@ SATResolver::problems ()
     return resolverProblems;
 }
 
-void
-SATResolver::applySolutions (const ProblemSolutionList & solutions)
-{
-    for (ProblemSolutionList::const_iterator iter = solutions.begin();
-        iter != solutions.end(); ++iter) {
-       ProblemSolution_Ptr solution = *iter;
-       Resolver dummyResolver(_pool);
-       if (!solution->apply (dummyResolver))
-           break;
-    }
-}
+void SATResolver::applySolutions( const ProblemSolutionList & solutions )
+{ Resolver( _pool ).applySolutions( solutions ); }
 
 void SATResolver::setLocks()
 {