#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
//---------------------------------------------------------------------------
-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/>";
}
: _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() );
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, true )
+ZOLV_FLAG_TRIBOOL( dupSetAllowNameChange, dupAllowNameChange, _dup_allownamechange, true )
+ZOLV_FLAG_TRIBOOL( dupSetAllowArchChange, dupAllowArchChange, _dup_allowarchchange, true )
+ZOLV_FLAG_TRIBOOL( dupSetAllowVendorChange, dupAllowVendorChange, _dup_allowvendorchange, true )
+
+#undef ZOLV_FLAG_TRIBOOL
+//---------------------------------------------------------------------------
+
+void Resolver::setAllowVendorChange( TriBool state_r )
+{
+ _allowVendorChange = indeterminate(state_r) ? ZConfig::instance().solver_allowVendorChange() : bool(state_r);
+}
-ResPool
-Resolver::pool (void) const
+void Resolver::setOnlyRequires( TriBool state_r )
{
- return _pool;
+ _onlyRequires = indeterminate(state_r) ? ZConfig::instance().solver_onlyRequires() : bool(state_r);
}
-void
-Resolver::reset (bool keepExtras )
+void Resolver::setCleandepsOnRemove( TriBool state_r )
{
- _verifying = false;
+ _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();
_extra_conflicts.clear();
}
-}
-void
-Resolver::doUpdate()
-{
- return _satResolver->doUpdate();
+ _isInstalledBy.clear();
+ _installs.clear();
+ _satifiedByInstalled.clear();
+ _installedSatisfied.clear();
}
-void
-Resolver::addExtraRequire (const Capability & capability)
+bool Resolver::doUpgrade()
{
- _extra_requires.insert (capability);
+ // Setting Resolver to upgrade mode. SAT solver will do the update
+ _upgradeMode = true;
+ return resolvePool();
}
-void
-Resolver::removeExtraRequire (const Capability & capability)
+void Resolver::doUpdate()
{
- _extra_requires.erase (capability);
+ _updateMode = true;
+ return _satResolver->doUpdate();
}
-void
-Resolver::addExtraConflict (const Capability & capability)
-{
- _extra_conflicts.insert (capability);
-}
+PoolItemList Resolver::problematicUpdateItems() const
+{ return _satResolver->problematicUpdateItems(); }
-void
-Resolver::removeExtraConflict (const Capability & capability)
-{
- _extra_conflicts.erase (capability);
-}
+void Resolver::addExtraRequire( const Capability & capability )
+{ _extra_requires.insert (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();
_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();
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 ); }
//---------------------------------------------------------------------------
};
-bool
-Resolver::verifySystem ()
+bool Resolver::verifySystem()
{
UndoTransact resetting (ResStatus::APPL_HIGH);
_DEBUG ("Resolver::verifySystem() ");
-
- _verifying = true;
+
+ _verifying = true;
invokeOnEach ( _pool.begin(), _pool.end(),
resfilter::ByTransact( ), // Resetting all transcations
//----------------------------------------------------------------------------
// undo
-
-void
-Resolver::undo(void)
+void Resolver::undo()
{
UndoTransact info(ResStatus::APPL_LOW);
MIL << "*** undo ***" << endl;
// 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();
+ _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;
- }
+ }
}
}
if ( (*iterQueue)->cmp(*iter) == 0) {
found = true;
break;
- }
+ }
}
if (!found) {
- MIL << "add to queue" << *iter;
+ MIL << "add to queue" << *iter;
queue.push_back(*iter);
}
}
-
+
+ // The application has to take care to write these solutions back to e.g. selectables in order
+ // 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;
+//----------------------------------------------------------------------------
+// Getting more information about the solve results
+
+ResolverProblemList Resolver::problems() const
+{
+ MIL << "Resolver::problems()" << endl;
+ return _satResolver->problems();
+}
+
+void Resolver::applySolutions( const ProblemSolutionList & solutions )
+{
+ for_( iter, solutions.begin(), solutions.end() )
+ {
+ ProblemSolution_Ptr solution = *iter;
+ if ( !solution->apply( *this ) )
+ break;
+ }
+}
+
+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;
+ 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::REQUIRES, !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::REQUIRES, false );
+ _isInstalledBy.insert (make_pair( provider, capKindisInstalledBy));
+ }
+ ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::REQUIRES, !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::REQUIRES, false );
+ _satifiedByInstalled.insert (make_pair( *instIter, capKindisInstalledBy));
+
+ ItemCapKind installedSatisfied( *instIter, *capIt, Dep::REQUIRES, false );
+ _installedSatisfied.insert (make_pair( provider, installedSatisfied));
}
- }
- 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
}
}
+
+ 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));
+ }
+ }
+ }
+
+ //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 (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));
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+ItemCapKindList Resolver::isInstalledBy( const PoolItem & item )
+{
+ ItemCapKindList ret;
+ collectResolverInfo();
+
+ for (ItemCapKindMap::const_iterator iter = _isInstalledBy.find(item); iter != _isInstalledBy.end();) {
+ ItemCapKind info = iter->second;
+ PoolItem iterItem = iter->first;
+ if (iterItem == item) {
+ ret.push_back(info);
+ iter++;
+ } else {
+ // exit
+ iter = _isInstalledBy.end();
}
+ }
+ return ret;
+}
- 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();
+ItemCapKindList Resolver::installs( const PoolItem & item )
+{
+ ItemCapKindList ret;
+ collectResolverInfo();
+
+ for (ItemCapKindMap::const_iterator iter = _installs.find(item); iter != _installs.end();) {
+ ItemCapKind info = iter->second;
+ PoolItem iterItem = iter->first;
+ if (iterItem == item) {
+ ret.push_back(info);
+ iter++;
+ } else {
+ // exit
+ iter = _installs.end();
+ }
+ }
+ 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 {
- // break cause there is no other solution available by the next run
- solverRuns = MAXSOLVERRUNS;
+ // exit
+ iter = _installedSatisfied.end();
}
- // next try
- solverRet = resolvePool();
}
- return solverRet;
+ return ret;
}