X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=zypp%2Fsolver%2Fdetail%2FSATResolver.cc;h=f1e17539510f1b225cfa5b4803cd149b3b46e142;hb=83ae0a03ba583b177a13e092f34d715b42c17d45;hp=16c913b3b9ca3baeef4d15dc02ebc3b07ce89ba2;hpb=7206bae69870e7d73380d9692998448f232ba6f0;p=platform%2Fupstream%2Flibzypp.git diff --git a/zypp/solver/detail/SATResolver.cc b/zypp/solver/detail/SATResolver.cc index 16c913b..f1e1753 100644 --- a/zypp/solver/detail/SATResolver.cc +++ b/zypp/solver/detail/SATResolver.cc @@ -18,13 +18,24 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307, USA. */ -#include +extern "C" +{ +#include +#include +#include +#include +#include +#include +#include +} + #include "zypp/solver/detail/Helper.h" #include "zypp/base/String.h" +#include "zypp/Product.h" #include "zypp/Capability.h" #include "zypp/ResStatus.h" #include "zypp/VendorAttr.h" -#include "zypp/base/Logger.h" +#include "zypp/base/LogTools.h" #include "zypp/base/String.h" #include "zypp/base/Gettext.h" #include "zypp/base/Algorithm.h" @@ -33,26 +44,38 @@ #include "zypp/ZConfig.h" #include "zypp/sat/Pool.h" #include "zypp/sat/WhatProvides.h" +#include "zypp/sat/WhatObsoletes.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" - -extern "C" { -#include "satsolver/repo_solv.h" -#include "satsolver/poolarch.h" -#include "satsolver/evr.h" -#include "satsolver/poolvendor.h" -#include "satsolver/policy.h" -#include "satsolver/bitmap.h" -#include "satsolver/queue.h" -} +#include "zypp/sat/Transaction.h" +#include "zypp/sat/Queue.h" ///////////////////////////////////////////////////////////////////////// namespace zypp { /////////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////////////// + namespace env + { + inline bool HACKENV( const char * var_r, bool default_r ) + { + bool ret = default_r; + const char * val = ::getenv( var_r ); + if ( val ) + { + ret = str::strToBool( val, default_r ); + if ( ret != default_r ) + INT << "HACKENV " << var_r << " = " << ret << endl; + } + return ret; + } + } // namespace env + ///////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// namespace solver { ///////////////////////////////////////////////////////////////////// @@ -64,62 +87,78 @@ using namespace std; IMPL_PTR_TYPE(SATResolver); +#define MAYBE_CLEANDEPS (cleandepsOnRemove()?SOLVER_CLEANDEPS:0) + //--------------------------------------------------------------------------- // Callbacks for SAT policies //--------------------------------------------------------------------------- -int vendorCheck (Pool *pool, Solvable *solvable1, Solvable *solvable2) { -// DBG << "vendorCheck: " << id2str(pool, solvable1->vendor) << " <--> " << id2str(pool, solvable1->vendor) << endl; - return VendorAttr::instance().equivalent(id2str(pool, solvable1->vendor), id2str(pool, solvable2->vendor)) ? 0:1; +int vendorCheck( Pool *pool, Solvable *solvable1, Solvable *solvable2 ) +{ + return VendorAttr::instance().equivalent( IdString(solvable1->vendor), + IdString(solvable2->vendor) ) ? 0 : 1; } -string -itemToString (PoolItem item, bool shortVersion) +inline std::string itemToString( const PoolItem & item ) { - ostringstream os; - if (!item) return ""; - - if (item->kind() != ResTraits::kind) - os << item->kind() << ':'; - os << item->name(); - if (!shortVersion) { - os << '-' << item->edition(); - if (item->arch() != "") { - os << '.' << item->arch(); - } - Repository s = item->repository(); - if (s) { - string alias = s.info().alias(); - if (!alias.empty() - && alias != "@system") - { - os << '[' << s.info().alias() << ']'; - } - } - } - return os.str(); + if ( !item ) + return std::string(); + + sat::Solvable slv( item.satSolvable() ); + std::string ret( slv.asString() ); // n-v-r.a + if ( ! slv.isSystem() ) + { + ret += "["; + ret += slv.repository().alias(); + ret += "]"; + } + return ret; +} + +inline PoolItem getPoolItem( Id id_r ) +{ + PoolItem ret( (sat::Solvable( id_r )) ); + if ( !ret && id_r ) + INT << "id " << id_r << " not found in ZYPP pool." << endl; + return ret; } - //--------------------------------------------------------------------------- std::ostream & SATResolver::dumpOn( std::ostream & os ) const { - os << "" << endl; + os << "" << endl; if (_solv) { - os << " fixsystem = " << _solv->fixsystem << endl; - os << " allowdowngrade = " << _solv->allowdowngrade << endl; - os << " allowarchchange = " << _solv->allowarchchange << endl; - os << " allowvendorchange = " << _solv->allowvendorchange << endl; - os << " allowuninstall = " << _solv->allowuninstall << endl; - os << " updatesystem = " << _solv->updatesystem << endl; - os << " allowvirtualconflicts = " << _solv->allowvirtualconflicts << endl; - os << " noupdateprovide = " << _solv->noupdateprovide << endl; - os << " dosplitprovides = " << _solv->dosplitprovides << endl; - os << " onlyRequires = " << _solv->dontinstallrecommended << endl; - os << " ignorealreadyrecommended = " << _solv->ignorealreadyrecommended << endl; +#define OUTS(X) os << " " << #X << "\t= " << solver_get_flag(_solv, SOLVER_FLAG_##X) << endl + OUTS( ALLOW_DOWNGRADE ); + OUTS( ALLOW_ARCHCHANGE ); + OUTS( ALLOW_VENDORCHANGE ); + OUTS( ALLOW_UNINSTALL ); + OUTS( NO_UPDATEPROVIDE ); + OUTS( SPLITPROVIDES ); + OUTS( IGNORE_RECOMMENDED ); + OUTS( ADD_ALREADY_RECOMMENDED ); + OUTS( NO_INFARCHCHECK ); + OUTS( ALLOW_NAMECHANGE ); + OUTS( KEEP_EXPLICIT_OBSOLETES ); + OUTS( BEST_OBEY_POLICY ); + OUTS( NO_AUTOTARGET ); + OUTS( DUP_ALLOW_DOWNGRADE ); + OUTS( DUP_ALLOW_ARCHCHANGE ); + OUTS( DUP_ALLOW_VENDORCHANGE ); + OUTS( DUP_ALLOW_NAMECHANGE ); + OUTS( KEEP_ORPHANS ); + OUTS( BREAK_ORPHANS ); + OUTS( FOCUS_INSTALLED ); + OUTS( YUM_OBSOLETES ); +#undef OUTS + os << " distupgrade = " << _distupgrade << endl; + os << " distupgrade_removeunsupported = " << _distupgrade_removeunsupported << endl; + os << " solveSrcPackages = " << _solveSrcPackages << endl; + os << " cleandepsOnRemove = " << _cleandepsOnRemove << endl; + os << " fixsystem = " << _fixsystem << endl; } else { os << ""; } @@ -135,39 +174,40 @@ SATResolver::SATResolver (const ResPool & pool, Pool *SATPool) , _fixsystem(false) , _allowdowngrade(false) , _allowarchchange(false) - , _allowvendorchange(false) + , _allowvendorchange(ZConfig::instance().solver_allowVendorChange()) , _allowuninstall(false) , _updatesystem(false) - , _allowvirtualconflicts(false) , _noupdateprovide(false) , _dosplitprovides(false) , _onlyRequires(ZConfig::instance().solver_onlyRequires()) - , _ignorealreadyrecommended(false) - + , _ignorealreadyrecommended(true) + , _distupgrade(false) + , _distupgrade_removeunsupported(false) + , _solveSrcPackages(false) + , _cleandepsOnRemove(ZConfig::instance().solver_cleandepsOnRemove()) { } SATResolver::~SATResolver() { + solverEnd(); } //--------------------------------------------------------------------------- - ResPool 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++) { + iter != _items_to_remove.end(); ++iter) { if (*iter == item) { _items_to_remove.remove(*iter); found = true; @@ -176,7 +216,7 @@ SATResolver::resetItemTransaction (PoolItem item) } if (!found) { for (PoolItemList::const_iterator iter = _items_to_install.begin(); - iter != _items_to_install.end(); iter++) { + iter != _items_to_install.end(); ++iter) { if (*iter == item) { _items_to_install.remove(*iter); found = true; @@ -186,7 +226,7 @@ SATResolver::resetItemTransaction (PoolItem item) } if (!found) { for (PoolItemList::const_iterator iter = _items_to_keep.begin(); - iter != _items_to_keep.end(); iter++) { + iter != _items_to_keep.end(); ++iter) { if (*iter == item) { _items_to_keep.remove(*iter); found = true; @@ -196,14 +236,14 @@ SATResolver::resetItemTransaction (PoolItem item) } if (!found) { for (PoolItemList::const_iterator iter = _items_to_lock.begin(); - iter != _items_to_lock.end(); iter++) { + iter != _items_to_lock.end(); ++iter) { if (*iter == item) { _items_to_lock.remove(*iter); found = true; break; } } - } + } } @@ -228,7 +268,7 @@ SATResolver::addPoolItemsToInstallFromList (PoolItemList & rl) void SATResolver::addPoolItemToRemove (PoolItem item) { - resetItemTransaction (item); + resetItemTransaction (item); _items_to_remove.push_back (item); _items_to_remove.unique (); } @@ -245,22 +285,15 @@ SATResolver::addPoolItemsToRemoveFromList (PoolItemList & rl) void SATResolver::addPoolItemToLock (PoolItem item) { - resetItemTransaction (item); + resetItemTransaction (item); _items_to_lock.push_back (item); _items_to_lock.unique (); } void -SATResolver::addPoolItemParallelInstall(PoolItem item) -{ - _items_parallel_install.push_back (item); - _items_parallel_install.unique (); -} - -void SATResolver::addPoolItemToKeep (PoolItem item) { - resetItemTransaction (item); + resetItemTransaction (item); _items_to_keep.push_back (item); _items_to_keep.unique (); } @@ -273,7 +306,7 @@ SATResolver::addPoolItemToKeep (PoolItem item) static void SATSolutionToPool (PoolItem item, const ResStatus & status, const ResStatus::TransactByValue causer) { - // resetting + // resetting item.status().resetTransact (causer); item.status().resetWeak (); @@ -282,44 +315,18 @@ SATSolutionToPool (PoolItem item, const ResStatus & status, const ResStatus::Tra // installation/deletion if (status.isToBeInstalled()) { r = item.status().setToBeInstalled (causer); - _XDEBUG("SATSolutionToPool(" << item << ", " << status << ") install !" << r); + _XDEBUG("SATSolutionToPool install returns " << item << ", " << r); } else if (status.isToBeUninstalledDueToUpgrade()) { r = item.status().setToBeUninstalledDueToUpgrade (causer); - _XDEBUG("SATSolutionToPool(" << item << ", " << status << ") upgrade !" << r); + _XDEBUG("SATSolutionToPool upgrade returns " << item << ", " << r); } else if (status.isToBeUninstalled()) { r = item.status().setToBeUninstalled (causer); - _XDEBUG("SATSolutionToPool(" << item << ", " << status << ") remove !" << r); + _XDEBUG("SATSolutionToPool remove returns " << item << ", " << r); } - - return; -} - -//---------------------------------------------------------------------------- -// helper functions for distupgrade -//---------------------------------------------------------------------------- - -bool SATResolver::doesObsoleteItem (PoolItem candidate, PoolItem installed) { - Solvable *sCandidate = _SATPool->solvables + candidate.satSolvable().id(); - ::_Repo *installedRepo = sat::Pool::instance().systemRepo().get(); - - Id p, *pp, obsolete, *obsoleteIt; - - if ((!installedRepo || sCandidate->repo != installedRepo) && sCandidate->obsoletes) { - obsoleteIt = sCandidate->repo->idarraydata + sCandidate->obsoletes; - while ((obsolete = *obsoleteIt++) != 0) - { - for (pp = pool_whatprovides(_SATPool, obsolete) ; (p = *pp++) != 0; ) { - if (p > 0 && installed.satSolvable().id() == (sat::detail::SolvableIdType)p) { - MIL << candidate << " obsoletes " << installed << endl; - return true; - } - } - } - } - return false; + return; } //---------------------------------------------------------------------------- @@ -354,19 +361,20 @@ struct SATCollectTransact : public resfilter::PoolItemFilterFunctor bool operator()( PoolItem item ) // only transacts() items go here { - if (item->installOnly()) { - resolver. addPoolItemParallelInstall(item); - } - ResStatus status = item.status(); bool by_solver = (status.isBySolver() || status.isByApplLow()); if (by_solver) { - _XDEBUG("Resetting " << item ); item.status().resetTransact( ResStatus::APPL_LOW );// clear any solver/establish transactions return true; // back out here, dont re-queue former solver result } + if ( item.satSolvable().isKind() && ! resolver.solveSrcPackages() ) + { + // Later we may continue on a per source package base. + return true; // dont process this source package. + } + if (status.isToBeInstalled()) { resolver.addPoolItemToInstall(item); // -> install! } @@ -398,62 +406,89 @@ class CheckIfUpdate : public resfilter::PoolItemFilterFunctor { public: bool is_updated; + bool multiversion; + sat::Solvable _installed; - CheckIfUpdate() + CheckIfUpdate( sat::Solvable installed_r ) : is_updated( false ) + , multiversion( installed_r.multiversionInstall() ) + , _installed( installed_r ) {} - // check this item will be installed + // check this item will be updated bool operator()( PoolItem item ) { - if (item.status().isToBeInstalled()) - { - is_updated = true; - return false; + if ( item.status().isToBeInstalled() ) + { + if ( ! multiversion || sameNVRA( _installed, item ) ) + { + is_updated = true; + return false; + } } return true; } }; -class CollectNonePackages : public resfilter::PoolItemFilterFunctor +class CollectPseudoInstalled : public resfilter::PoolItemFilterFunctor { public: Queue *solvableQueue; - CollectNonePackages( Queue *queue ) + CollectPseudoInstalled( Queue *queue ) :solvableQueue (queue) {} - - // collecting none packges + // collecting PseudoInstalled items bool operator()( PoolItem item ) { - queue_push(solvableQueue, item.satSolvable().id()); - return true; + if ( traits::isPseudoInstalled( item.satSolvable().kind() ) ) + queue_push( solvableQueue, item.satSolvable().id() ); + return true; } }; bool -SATResolver::solving() +SATResolver::solving(const CapabilitySet & requires_caps, + const CapabilitySet & conflict_caps) { - _solv = solver_create( _SATPool, sat::Pool::instance().systemRepo().get() ); - _solv->vendorCheckCb = &vendorCheck; - _solv->fixsystem = _fixsystem; - _solv->ignorealreadyrecommended = _ignorealreadyrecommended; - _solv->updatesystem = _updatesystem; - _solv->allowdowngrade = _allowdowngrade; - _solv->allowuninstall = _allowuninstall; - _solv->allowarchchange = _allowarchchange; - _solv->dosplitprovides = _dosplitprovides; - _solv->noupdateprovide = _noupdateprovide; - _solv->dontinstallrecommended = _onlyRequires; - - sat::Pool::instance().prepare(); - - // Add ignoring request - + _solv = solver_create( _SATPool ); + ::pool_set_custom_vendorcheck( _SATPool, &vendorCheck ); + if (_fixsystem) { + queue_push( &(_jobQueue), SOLVER_VERIFY|SOLVER_SOLVABLE_ALL); + queue_push( &(_jobQueue), 0 ); + } + if (_updatesystem) { + queue_push( &(_jobQueue), SOLVER_UPDATE|SOLVER_SOLVABLE_ALL); + queue_push( &(_jobQueue), 0 ); + } + if (_distupgrade) { + queue_push( &(_jobQueue), SOLVER_DISTUPGRADE|SOLVER_SOLVABLE_ALL); + queue_push( &(_jobQueue), 0 ); + } + if (_distupgrade_removeunsupported) { + queue_push( &(_jobQueue), SOLVER_DROP_ORPHANED|SOLVER_SOLVABLE_ALL); + queue_push( &(_jobQueue), 0 ); + } + solver_set_flag(_solv, SOLVER_FLAG_ADD_ALREADY_RECOMMENDED, !_ignorealreadyrecommended); + solver_set_flag(_solv, SOLVER_FLAG_ALLOW_DOWNGRADE, _allowdowngrade); + solver_set_flag(_solv, SOLVER_FLAG_ALLOW_UNINSTALL, _allowuninstall); + solver_set_flag(_solv, SOLVER_FLAG_ALLOW_ARCHCHANGE, _allowarchchange); + solver_set_flag(_solv, SOLVER_FLAG_ALLOW_VENDORCHANGE, _allowvendorchange); + solver_set_flag(_solv, SOLVER_FLAG_SPLITPROVIDES, _dosplitprovides); + solver_set_flag(_solv, SOLVER_FLAG_NO_UPDATEPROVIDE, _noupdateprovide); + solver_set_flag(_solv, SOLVER_FLAG_IGNORE_RECOMMENDED, _onlyRequires); + +#define HACKENV(X,D) solver_set_flag(_solv, X, env::HACKENV( #X, D ) ); + HACKENV( SOLVER_FLAG_DUP_ALLOW_DOWNGRADE, true ); + HACKENV( SOLVER_FLAG_DUP_ALLOW_ARCHCHANGE, true ); + HACKENV( SOLVER_FLAG_DUP_ALLOW_VENDORCHANGE,true ); + HACKENV( SOLVER_FLAG_DUP_ALLOW_NAMECHANGE, true ); +#undef HACKENV + + sat::Pool::instance().prepareForSolving(); // Solve ! MIL << "Starting solving...." << endl; @@ -467,102 +502,122 @@ SATResolver::solving() _result_items_to_remove.clear(); /* solvables to be installed */ - for (int i = 0; i < _solv->decisionq.count; i++) + Queue decisionq; + queue_init(&decisionq); + solver_get_decisionqueue(_solv, &decisionq); + for ( int i = 0; i < decisionq.count; ++i ) { - Id p; - p = _solv->decisionq.elements[i]; - if (p < 0 || !sat::Solvable(p)) - continue; - if (sat::Solvable(p).repository().get() == _solv->installed) + sat::Solvable slv( decisionq.elements[i] ); + if ( !slv || slv.isSystem() ) continue; - PoolItem poolItem = _pool.find (sat::Solvable(p)); - if (poolItem) { - SATSolutionToPool (poolItem, ResStatus::toBeInstalled, ResStatus::SOLVER); - _result_items_to_install.push_back (poolItem); - } else { - ERR << "id " << p << " not found in ZYPP pool." << endl; - } + PoolItem poolItem( slv ); + SATSolutionToPool (poolItem, ResStatus::toBeInstalled, ResStatus::SOLVER); + _result_items_to_install.push_back (poolItem); } + queue_free(&decisionq); /* solvables to be erased */ - for (int i = _solv->installed->start; i < _solv->installed->start + _solv->installed->nsolvables; i++) + Repository systemRepo( sat::Pool::instance().findSystemRepo() ); // don't create if it does not exist + if ( systemRepo && ! systemRepo.solvablesEmpty() ) { - if (_solv->decisionmap[i] > 0) - continue; - - PoolItem poolItem = _pool.find (sat::Solvable(i)); - if (poolItem) { - // Check if this is an update - CheckIfUpdate info; - invokeOnEach( _pool.byIdentBegin( poolItem ), - _pool.byIdentEnd( poolItem ), - resfilter::ByUninstalled(), // ByUninstalled - functor::functorRef (info) ); - - if (info.is_updated) { - SATSolutionToPool (poolItem, ResStatus::toBeUninstalledDueToUpgrade , ResStatus::SOLVER); - } else { - SATSolutionToPool (poolItem, ResStatus::toBeUninstalled, ResStatus::SOLVER); - } - _result_items_to_remove.push_back (poolItem); - } else { - ERR << "id " << i << " not found in ZYPP pool." << endl; + bool mustCheckObsoletes = false; + for_( it, systemRepo.solvablesBegin(), systemRepo.solvablesEnd() ) + { + if (solver_get_decisionlevel(_solv, it->id()) > 0) + continue; + + // Check if this is an update + CheckIfUpdate info( *it ); + PoolItem poolItem( *it ); + invokeOnEach( _pool.byIdentBegin( poolItem ), + _pool.byIdentEnd( poolItem ), + resfilter::ByUninstalled(), // ByUninstalled + functor::functorRef (info) ); + + if (info.is_updated) { + SATSolutionToPool( poolItem, ResStatus::toBeUninstalledDueToUpgrade, ResStatus::SOLVER ); + } else { + SATSolutionToPool( poolItem, ResStatus::toBeUninstalled, ResStatus::SOLVER ); + if ( ! mustCheckObsoletes ) + mustCheckObsoletes = true; // lazy check for UninstalledDueToObsolete + } + _result_items_to_remove.push_back (poolItem); + } + if ( mustCheckObsoletes ) + { + sat::WhatObsoletes obsoleted( _result_items_to_install.begin(), _result_items_to_install.end() ); + for_( it, obsoleted.poolItemBegin(), obsoleted.poolItemEnd() ) + { + ResStatus & status( it->status() ); + // WhatObsoletes contains installed items only! + if ( status.transacts() && ! status.isToBeUninstalledDueToUpgrade() ) + status.setToBeUninstalledDueToObsolete(); + } } } + Queue recommendations; + Queue suggestions; + Queue orphaned; + Queue unneeded; + queue_init(&recommendations); + queue_init(&suggestions); + queue_init(&orphaned); + queue_init(&unneeded); + solver_get_recommendations(_solv, &recommendations, &suggestions, 0); + solver_get_orphaned(_solv, &orphaned); + solver_get_unneeded(_solv, &unneeded, 1); /* solvables which are recommended */ - for (int i = 0; i < _solv->recommendations.count; i++) + for ( int i = 0; i < recommendations.count; ++i ) { - Id p; - p = _solv->recommendations.elements[i]; - if (p < 0 || !sat::Solvable(p)) - continue; - - PoolItem poolItem = _pool.find (sat::Solvable(p)); - if (poolItem) { - poolItem.status().setRecommended(true); - _XDEBUG("SATSolutionToPool(" << poolItem << ") recommended !"); - } else { - ERR << "id " << p << " not found in ZYPP pool." << endl; - } + PoolItem poolItem( getPoolItem( recommendations.elements[i] ) ); + poolItem.status().setRecommended( true ); } /* solvables which are suggested */ - for (int i = 0; i < _solv->suggestions.count; i++) + for ( int i = 0; i < suggestions.count; ++i ) { - Id p; - p = _solv->suggestions.elements[i]; - if (p < 0 || !sat::Solvable(p)) - continue; + PoolItem poolItem( getPoolItem( suggestions.elements[i] ) ); + poolItem.status().setSuggested( true ); + } - PoolItem poolItem = _pool.find (sat::Solvable(p)); - if (poolItem) { - poolItem.status().setSuggested(true); - _XDEBUG("SATSolutionToPool(" << poolItem << ") suggested !"); - } else { - ERR << "id " << p << " not found in ZYPP pool." << endl; - } + _problem_items.clear(); + /* solvables which are orphaned */ + for ( int i = 0; i < orphaned.count; ++i ) + { + PoolItem poolItem( getPoolItem( orphaned.elements[i] ) ); + poolItem.status().setOrphaned( true ); + _problem_items.push_back( poolItem ); } + /* solvables which are unneeded */ + for ( int i = 0; i < unneeded.count; ++i ) + { + PoolItem poolItem( getPoolItem( unneeded.elements[i] ) ); + poolItem.status().setUnneeded( true ); + } + + queue_free(&recommendations); + queue_free(&suggestions); + queue_free(&orphaned); + queue_free(&unneeded); + /* Write validation state back to pool */ - Map installedmap; Queue flags, solvableQueue; - queue_init(&flags); + queue_init(&flags); queue_init(&solvableQueue); - CollectNonePackages collectNonePackages(&solvableQueue); + CollectPseudoInstalled collectPseudoInstalled(&solvableQueue); invokeOnEach( _pool.begin(), _pool.end(), - functor::not_c(resfilter::byKind()), // every solvable BUT packages - functor::functorRef (collectNonePackages) ); - solver_create_state_maps(_solv, &installedmap, 0); - pool_trivial_installable(_solv->pool, _solv->installed, &installedmap, &solvableQueue, &flags); + functor::functorRef (collectPseudoInstalled) ); + solver_trivial_installable(_solv, &solvableQueue, &flags ); for (int i = 0; i < solvableQueue.count; i++) { PoolItem item = _pool.find (sat::Solvable(solvableQueue.elements[i])); - item.status().setUndetermined(); - + item.status().setUndetermined(); + if (flags.elements[i] == -1) { item.status().setNonRelevant(); _XDEBUG("SATSolutionToPool(" << item << " ) nonRelevant !"); @@ -571,19 +626,42 @@ SATResolver::solving() _XDEBUG("SATSolutionToPool(" << item << " ) satisfied !"); } else if (flags.elements[i] == 0) { item.status().setBroken(); - _XDEBUG("SATSolutionToPool(" << item << " ) broken !"); + _XDEBUG("SATSolutionToPool(" << item << " ) broken !"); } } + queue_free(&(solvableQueue)); + queue_free(&flags); + - if (_solv->problems.count > 0 ) + // Solvables which were selected due requirements which have been made by the user will + // be selected by APPL_LOW. We can't use any higher level, because this setting must + // not serve as a request for the next solver run. APPL_LOW is reset before solving. + for (CapabilitySet::const_iterator iter = requires_caps.begin(); iter != requires_caps.end(); iter++) { + sat::WhatProvides rpmProviders(*iter); + for_( iter2, rpmProviders.begin(), rpmProviders.end() ) { + PoolItem poolItem(*iter2); + if (poolItem.status().isToBeInstalled()) { + MIL << "User requirement " << *iter << " sets " << poolItem << endl; + poolItem.status().setTransactByValue (ResStatus::APPL_LOW); + } + } + } + for (CapabilitySet::const_iterator iter = conflict_caps.begin(); iter != conflict_caps.end(); iter++) { + sat::WhatProvides rpmProviders(*iter); + for_( iter2, rpmProviders.begin(), rpmProviders.end() ) { + PoolItem poolItem(*iter2); + if (poolItem.status().isToBeUninstalled()) { + MIL << "User conflict " << *iter << " sets " << poolItem << endl; + poolItem.status().setTransactByValue (ResStatus::APPL_LOW); + } + } + } + + if (solver_problem_count(_solv) > 0 ) { ERR << "Solverrun finished with an ERROR" << endl; return false; } - - map_free(&installedmap); - queue_free(&(solvableQueue)); - queue_free(&flags); return true; } @@ -593,94 +671,134 @@ void SATResolver::solverInit(const PoolItemList & weakItems) { SATCollectTransact info (*this); - + MIL << "SATResolver::solverInit()" << endl; - if (_solv) { - // remove old stuff - solver_free(_solv); - _solv = NULL; - queue_free( &(_jobQueue) ); - } + // remove old stuff + solverEnd(); queue_init( &_jobQueue ); _items_to_install.clear(); _items_to_remove.clear(); _items_to_lock.clear(); _items_to_keep.clear(); - _items_parallel_install.clear(); invokeOnEach ( _pool.begin(), _pool.end(), functor::functorRef(info) ); - + for (PoolItemList::const_iterator iter = weakItems.begin(); iter != weakItems.end(); iter++) { Id id = (*iter)->satSolvable().id(); if (id == ID_NULL) { ERR << "Weaken: " << *iter << " not found" << endl; } MIL << "Weaken dependencies of " << *iter << endl; - queue_push( &(_jobQueue), SOLVER_WEAKEN_SOLVABLE_DEPS ); - queue_push( &(_jobQueue), id ); + queue_push( &(_jobQueue), SOLVER_WEAKENDEPS | SOLVER_SOLVABLE ); + queue_push( &(_jobQueue), id ); } - for (PoolItemList::iterator it = _items_parallel_install.begin(); it != _items_parallel_install.end(); ++it) { - Id id = (*it)->satSolvable().id(); - if (id == ID_NULL) { - ERR << "Item " << *it << " not found" << endl; - } else { - MIL << "Ignore Obsoletes of item: " << *it << endl; - queue_push( &(_jobQueue), SOLVER_NOOBSOLETES_SOLVABLE ); - queue_push( &(_jobQueue), id ); - } + // Add rules for parallel installable resolvables with different versions + for_( it, sat::Pool::instance().multiversionBegin(), sat::Pool::instance().multiversionEnd() ) + { + queue_push( &(_jobQueue), SOLVER_NOOBSOLETES | SOLVER_SOLVABLE_NAME ); + queue_push( &(_jobQueue), it->id() ); + } + + ::pool_add_userinstalled_jobs(_SATPool, sat::Pool::instance().autoInstalled(), &(_jobQueue), GET_USERINSTALLED_NAMES|GET_USERINSTALLED_INVERTED); + + if ( _distupgrade ) + { + if ( ZConfig::instance().solverUpgradeRemoveDroppedPackages() ) + { + MIL << "Checking droplists ..." << endl; + // Dropped packages: look for 'weakremover()' provides + // in dup candidates of installed products. + ResPoolProxy proxy( ResPool::instance().proxy() ); + for_( it, proxy.byKindBegin(), proxy.byKindEnd() ) + { + if ( (*it)->onSystem() ) // (to install) or (not to delete) + { + Product::constPtr prodCand( (*it)->candidateAsKind() ); + if ( ! prodCand ) + continue; // product no longer available + + CapabilitySet droplist( prodCand->droplist() ); + dumpRangeLine( MIL << "Droplist for " << (*it)->candidateObj() << ": " << droplist.size() << " ", droplist.begin(), droplist.end() ) << endl; + for_( cap, droplist.begin(), droplist.end() ) + { + queue_push( &_jobQueue, SOLVER_DROP_ORPHANED | SOLVER_SOLVABLE_NAME ); + queue_push( &_jobQueue, cap->id() ); + } + } + } + } + else + { + MIL << "Droplist processing is disabled." << endl; + } } } void SATResolver::solverEnd() { - // cleanup + // cleanup + if ( _solv ) + { solver_free(_solv); _solv = NULL; - queue_free( &(_jobQueue) ); + queue_free( &(_jobQueue) ); + } } bool SATResolver::resolvePool(const CapabilitySet & requires_caps, const CapabilitySet & conflict_caps, - const PoolItemList & weakItems) + const PoolItemList & weakItems, + const std::set & upgradeRepos) { MIL << "SATResolver::resolvePool()" << endl; - + // initialize solverInit(weakItems); - + for (PoolItemList::const_iterator iter = _items_to_install.begin(); iter != _items_to_install.end(); iter++) { Id id = (*iter)->satSolvable().id(); if (id == ID_NULL) { ERR << "Install: " << *iter << " not found" << endl; } else { MIL << "Install " << *iter << endl; - queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE ); + queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE ); queue_push( &(_jobQueue), id ); } } for (PoolItemList::const_iterator iter = _items_to_remove.begin(); iter != _items_to_remove.end(); iter++) { - sat::detail::IdType ident( (*iter)->satSolvable().ident().id() ); - MIL << "Delete " << *iter << endl; - queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE_NAME ); - queue_push( &(_jobQueue), ident); + Id id = (*iter)->satSolvable().id(); + if (id == ID_NULL) { + ERR << "Delete: " << *iter << " not found" << endl; + } else { + MIL << "Delete " << *iter << endl; + queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE | MAYBE_CLEANDEPS ); + queue_push( &(_jobQueue), id); + } + } + + for_( iter, upgradeRepos.begin(), upgradeRepos.end() ) + { + queue_push( &(_jobQueue), SOLVER_DISTUPGRADE | SOLVER_SOLVABLE_REPO ); + queue_push( &(_jobQueue), iter->get()->repoid ); + MIL << "Upgrade repo " << *iter << endl; } for (CapabilitySet::const_iterator iter = requires_caps.begin(); iter != requires_caps.end(); iter++) { - queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE_PROVIDES ); + queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES ); queue_push( &(_jobQueue), iter->id() ); MIL << "Requires " << *iter << endl; } for (CapabilitySet::const_iterator iter = conflict_caps.begin(); iter != conflict_caps.end(); iter++) { - queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE_PROVIDES); + queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE_PROVIDES | MAYBE_CLEANDEPS ); queue_push( &(_jobQueue), iter->id() ); MIL << "Conflicts " << *iter << endl; } @@ -692,12 +810,9 @@ SATResolver::resolvePool(const CapabilitySet & requires_caps, setLocks(); // solving - bool ret = solving(); - // cleanup - if (ret) - solverEnd(); // remove solver only if no errors happend. Need it for solving problems - - MIL << "SATResolver::resolvePool() done. Ret:" << ret << endl; + bool ret = solving(requires_caps, conflict_caps); + + (ret?MIL:WAR) << "SATResolver::resolvePool() done. Ret:" << ret << endl; return ret; } @@ -707,7 +822,7 @@ SATResolver::resolveQueue(const SolverQueueItemList &requestQueue, const PoolItemList & weakItems) { MIL << "SATResolver::resolvQueue()" << endl; - + // initialize solverInit(weakItems); @@ -715,7 +830,7 @@ SATResolver::resolveQueue(const SolverQueueItemList &requestQueue, for (SolverQueueItemList::const_iterator iter = requestQueue.begin(); iter != requestQueue.end(); iter++) { (*iter)->addRule(_jobQueue); } - + // Add addition item status to the resolve-queue cause these can be set by problem resolutions for (PoolItemList::const_iterator iter = _items_to_install.begin(); iter != _items_to_install.end(); iter++) { Id id = (*iter)->satSolvable().id(); @@ -723,35 +838,31 @@ SATResolver::resolveQueue(const SolverQueueItemList &requestQueue, ERR << "Install: " << *iter << " not found" << endl; } else { MIL << "Install " << *iter << endl; - queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE ); + queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE ); queue_push( &(_jobQueue), id ); } } for (PoolItemList::const_iterator iter = _items_to_remove.begin(); iter != _items_to_remove.end(); iter++) { sat::detail::IdType ident( (*iter)->satSolvable().ident().id() ); MIL << "Delete " << *iter << ident << endl; - queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE_NAME ); + queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE_NAME | MAYBE_CLEANDEPS ); queue_push( &(_jobQueue), ident); } // set requirements for a running system setSystemRequirements(); - + // set locks for the solver setLocks(); // solving bool ret = solving(); - // cleanup - if (ret) - solverEnd(); // remove solver only if no errors happend. Need it for solving problems - MIL << "SATResolver::resolveQueue() done. Ret:" << ret << endl; return ret; } - +/** \todo duplicate code to be joined with \ref solving. */ void SATResolver::doUpdate() { MIL << "SATResolver::doUpdate()" << endl; @@ -761,21 +872,42 @@ void SATResolver::doUpdate() // set requirements for a running system setSystemRequirements(); - + // set locks for the solver - void setLocks(); + setLocks(); - _solv = solver_create( _SATPool, sat::Pool::instance().systemRepo().get() ); - _solv->vendorCheckCb = &vendorCheck; + _solv = solver_create( _SATPool ); + ::pool_set_custom_vendorcheck( _SATPool, &vendorCheck ); + if (_fixsystem) { + queue_push( &(_jobQueue), SOLVER_VERIFY|SOLVER_SOLVABLE_ALL); + queue_push( &(_jobQueue), 0 ); + } + if (1) { + queue_push( &(_jobQueue), SOLVER_UPDATE|SOLVER_SOLVABLE_ALL); + queue_push( &(_jobQueue), 0 ); + } + if (_distupgrade) { + queue_push( &(_jobQueue), SOLVER_DISTUPGRADE|SOLVER_SOLVABLE_ALL); + queue_push( &(_jobQueue), 0 ); + } + if (_distupgrade_removeunsupported) { + queue_push( &(_jobQueue), SOLVER_DROP_ORPHANED|SOLVER_SOLVABLE_ALL); + queue_push( &(_jobQueue), 0 ); + } + solver_set_flag(_solv, SOLVER_FLAG_ADD_ALREADY_RECOMMENDED, !_ignorealreadyrecommended); + solver_set_flag(_solv, SOLVER_FLAG_ALLOW_DOWNGRADE, _allowdowngrade); + solver_set_flag(_solv, SOLVER_FLAG_ALLOW_UNINSTALL, _allowuninstall); + solver_set_flag(_solv, SOLVER_FLAG_ALLOW_ARCHCHANGE, _allowarchchange); + solver_set_flag(_solv, SOLVER_FLAG_ALLOW_VENDORCHANGE, _allowvendorchange); + solver_set_flag(_solv, SOLVER_FLAG_SPLITPROVIDES, _dosplitprovides); + solver_set_flag(_solv, SOLVER_FLAG_NO_UPDATEPROVIDE, _noupdateprovide); + solver_set_flag(_solv, SOLVER_FLAG_IGNORE_RECOMMENDED, _onlyRequires); - _solv->updatesystem = true; - _solv->dontinstallrecommended = true; // #FIXME dontinstallrecommended maybe set to false if it works correctly - - sat::Pool::instance().prepare(); + sat::Pool::instance().prepareForSolving(); // Solve ! MIL << "Starting solving for update...." << endl; - MIL << *this; + MIL << *this; solver_solve( _solv, &(_jobQueue) ); MIL << "....Solver end" << endl; @@ -783,13 +915,16 @@ void SATResolver::doUpdate() //----------------------------------------- /* solvables to be installed */ - for (int i = 0; i < _solv->decisionq.count; i++) + Queue decisionq; + queue_init(&decisionq); + solver_get_decisionqueue(_solv, &decisionq); + for (int i = 0; i < decisionq.count; i++) { Id p; - p = _solv->decisionq.elements[i]; + p = decisionq.elements[i]; if (p < 0 || !sat::Solvable(p)) continue; - if (sat::Solvable(p).repository().get() == _solv->installed) + if (sat::Solvable(p).repository().get() == _solv->pool->installed) continue; PoolItem poolItem = _pool.find (sat::Solvable(p)); @@ -799,17 +934,18 @@ void SATResolver::doUpdate() ERR << "id " << p << " not found in ZYPP pool." << endl; } } + queue_free(&decisionq); /* solvables to be erased */ - for (int i = _solv->installed->start; i < _solv->installed->start + _solv->installed->nsolvables; i++) + for (int i = _solv->pool->installed->start; i < _solv->pool->installed->start + _solv->pool->installed->nsolvables; i++) { - if (_solv->decisionmap[i] > 0) - continue; + if (solver_get_decisionlevel(_solv, i) > 0) + continue; - PoolItem poolItem = _pool.find (sat::Solvable(i)); + PoolItem poolItem( _pool.find( sat::Solvable(i) ) ); if (poolItem) { // Check if this is an update - CheckIfUpdate info; + CheckIfUpdate info( (sat::Solvable(i)) ); invokeOnEach( _pool.byIdentBegin( poolItem ), _pool.byIdentEnd( poolItem ), resfilter::ByUninstalled(), // ByUninstalled @@ -824,10 +960,6 @@ void SATResolver::doUpdate() ERR << "id " << i << " not found in ZYPP pool." << endl; } } - - // cleanup - solverEnd(); - MIL << "SATResolver::doUpdate() done" << endl; } @@ -852,7 +984,7 @@ struct FindPackage : public resfilter::ResObjectFilterFunctor , action (act) { } - + bool operator()( PoolItem p) { problemSolution->addSingleAction (p, action); @@ -861,6 +993,32 @@ struct FindPackage : public resfilter::ResObjectFilterFunctor }; +//---------------------------------------------------------------------------- +// Checking if this solvable/item has a buddy which reflect the real +// user visible description of an item +// e.g. The release package has a buddy to the concerning product item. +// This user want's the message "Product foo conflicts with product bar" and +// NOT "package release-foo conflicts with package release-bar" +// (ma: that's why we should map just packages to buddies, not vice versa) +//---------------------------------------------------------------------------- +inline sat::Solvable mapBuddy( const PoolItem & item_r ) +{ + if ( item_r.satSolvable().isKind() ) + { + sat::Solvable buddy = item_r.buddy(); + if ( buddy ) + return buddy; + } + return item_r.satSolvable(); +} +inline sat::Solvable mapBuddy( sat::Solvable item_r ) +{ return mapBuddy( PoolItem( item_r ) ); } + +PoolItem SATResolver::mapItem ( const PoolItem & item ) +{ return PoolItem( mapBuddy( item ) ); } + +sat::Solvable SATResolver::mapSolvable ( const Id & id ) +{ return mapBuddy( sat::Solvable(id) ); } string SATResolver::SATprobleminfoString(Id problem, string &detail, Id &ignoreId) { @@ -868,56 +1026,83 @@ string SATResolver::SATprobleminfoString(Id problem, string &detail, Id &ignoreI Pool *pool = _solv->pool; Id probr; Id dep, source, target; - Solvable *s, *s2; + sat::Solvable s, s2; ignoreId = 0; + + // FIXME: solver_findallproblemrules to get all rules for this problem + // (the 'most relevabt' one returned by solver_findproblemrule is embedded probr = solver_findproblemrule(_solv, problem); - switch (solver_problemruleinfo(_solv, &(_jobQueue), probr, &dep, &source, &target)) + switch (solver_ruleinfo(_solv, probr, &source, &target, &dep)) { - case SOLVER_PROBLEM_UPDATE_RULE: - s = pool_id2solvable(pool, source); - ret = str::form (_("problem with installed package %s"), solvable2str(pool, s)); + case SOLVER_RULE_DISTUPGRADE: + s = mapSolvable (source); + ret = str::form (_("%s does not belong to a distupgrade repository"), s.asString().c_str()); + break; + case SOLVER_RULE_INFARCH: + s = mapSolvable (source); + ret = str::form (_("%s has inferior architecture"), s.asString().c_str()); break; - case SOLVER_PROBLEM_JOB_RULE: - ret = str::form (_("conflicting requests")); + case SOLVER_RULE_UPDATE: + s = mapSolvable (source); + ret = str::form (_("problem with installed package %s"), s.asString().c_str()); break; - case SOLVER_PROBLEM_RPM_RULE: - ret = str::form (_("some dependency problem")); + case SOLVER_RULE_JOB: + ret = _("conflicting requests"); break; - case SOLVER_PROBLEM_JOB_NOTHING_PROVIDES_DEP: - ret = str::form (_("nothing provides requested %s"), dep2str(pool, dep)); - detail += _("Have you enabled all requested repositories ?"); + case SOLVER_RULE_RPM: + ret = _("some dependency problem"); break; - case SOLVER_PROBLEM_NOT_INSTALLABLE: - s = pool_id2solvable(pool, source); - ret = str::form (_("%s is not installable"), solvable2str(pool, s)); + case SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP: + ret = str::form (_("nothing provides requested %s"), pool_dep2str(pool, dep)); + detail += _("Have you enabled all requested repositories?"); break; - case SOLVER_PROBLEM_NOTHING_PROVIDES_DEP: - s = pool_id2solvable(pool, source); - ret = str::form (_("nothing provides %s needed by %s"), dep2str(pool, dep), solvable2str(pool, s)); + case SOLVER_RULE_JOB_UNKNOWN_PACKAGE: + ret = str::form (_("package %s does not exist"), pool_dep2str(pool, dep)); + detail += _("Have you enabled all requested repositories?"); break; - case SOLVER_PROBLEM_SAME_NAME: - s = pool_id2solvable(pool, source); - s2 = pool_id2solvable(pool, target); - ret = str::form (_("cannot install both %s and %s"), solvable2str(pool, s), solvable2str(pool, s2)); + case SOLVER_RULE_JOB_UNSUPPORTED: + ret = _("unsupported request"); break; - case SOLVER_PROBLEM_PACKAGE_CONFLICT: - s = pool_id2solvable(pool, source); - s2 = pool_id2solvable(pool, target); - ret = str::form (_("%s conflicts with %s provided by %s"), solvable2str(pool, s), dep2str(pool, dep), solvable2str(pool, s2)); + case SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM: + ret = str::form (_("%s is provided by the system and cannot be erased"), pool_dep2str(pool, dep)); break; - case SOLVER_PROBLEM_PACKAGE_OBSOLETES: - s = pool_id2solvable(pool, source); - s2 = pool_id2solvable(pool, target); - ret = str::form (_("%s obsoletes %s provided by %s"), solvable2str(pool, s), dep2str(pool, dep), solvable2str(pool, s2)); + case SOLVER_RULE_RPM_NOT_INSTALLABLE: + s = mapSolvable (source); + ret = str::form (_("%s is not installable"), s.asString().c_str()); break; - case SOLVER_PROBLEM_SELF_CONFLICT: - s = pool_id2solvable(pool, source); - ret = str::form (_("Solvable %s conflicts with %s provided by itself"), solvable2str(pool, s), dep2str(pool, dep)); - break; - case SOLVER_PROBLEM_DEP_PROVIDERS_NOT_INSTALLABLE: + case SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP: ignoreId = source; // for setting weak dependencies - s = pool_id2solvable(pool, source); + s = mapSolvable (source); + ret = str::form (_("nothing provides %s needed by %s"), pool_dep2str(pool, dep), s.asString().c_str()); + break; + case SOLVER_RULE_RPM_SAME_NAME: + s = mapSolvable (source); + s2 = mapSolvable (target); + ret = str::form (_("cannot install both %s and %s"), s.asString().c_str(), s2.asString().c_str()); + break; + case SOLVER_RULE_RPM_PACKAGE_CONFLICT: + s = mapSolvable (source); + s2 = mapSolvable (target); + ret = str::form (_("%s conflicts with %s provided by %s"), s.asString().c_str(), pool_dep2str(pool, dep), s2.asString().c_str()); + break; + case SOLVER_RULE_RPM_PACKAGE_OBSOLETES: + s = mapSolvable (source); + s2 = mapSolvable (target); + ret = str::form (_("%s obsoletes %s provided by %s"), s.asString().c_str(), pool_dep2str(pool, dep), s2.asString().c_str()); + break; + case SOLVER_RULE_RPM_INSTALLEDPKG_OBSOLETES: + s = mapSolvable (source); + s2 = mapSolvable (target); + ret = str::form (_("installed %s obsoletes %s provided by %s"), s.asString().c_str(), pool_dep2str(pool, dep), s2.asString().c_str()); + break; + case SOLVER_RULE_RPM_SELF_CONFLICT: + s = mapSolvable (source); + ret = str::form (_("solvable %s conflicts with %s provided by itself"), s.asString().c_str(), pool_dep2str(pool, dep)); + break; + case SOLVER_RULE_RPM_PACKAGE_REQUIRES: + ignoreId = source; // for setting weak dependencies + s = mapSolvable (source); Capability cap(dep); sat::WhatProvides possibleProviders(cap); @@ -929,7 +1114,7 @@ string SATResolver::SATprobleminfoString(Id problem, string &detail, Id &ignoreI // find pair of an installed/uninstalled item with the same NVR bool found = false; for_( iter2, possibleProviders.begin(), possibleProviders.end() ) { - PoolItem provider2 = ResPool::instance().find( *iter2 ); + PoolItem provider2 = ResPool::instance().find( *iter2 ); if (compareByNVR (provider1.resolvable(),provider2.resolvable()) == 0 && ( (provider1.status().isInstalled() && provider2.status().isUninstalled()) || (provider2.status().isInstalled() && provider1.status().isUninstalled()) )) { @@ -945,28 +1130,28 @@ string SATResolver::SATprobleminfoString(Id problem, string &detail, Id &ignoreI } } - ret = str::form (_("%s requires %s, but this requirement cannot be provided"), solvable2str(pool, s), dep2str(pool, dep)); + ret = str::form (_("%s requires %s, but this requirement cannot be provided"), s.asString().c_str(), pool_dep2str(pool, dep)); if (providerlistInstalled.size() > 0) { detail += _("deleted providers: "); for (ProviderList::const_iterator iter = providerlistInstalled.begin(); iter != providerlistInstalled.end(); iter++) { if (iter == providerlistInstalled.begin()) - detail += itemToString (*iter, false); + detail += itemToString( *iter ); else - detail += "\n " + itemToString (*iter, false); + detail += "\n " + itemToString( mapItem(*iter) ); } } if (providerlistUninstalled.size() > 0) { if (detail.size() > 0) detail += _("\nuninstallable providers: "); else - detail = _("uninstallable providers: "); + detail = _("uninstallable providers: "); for (ProviderList::const_iterator iter = providerlistUninstalled.begin(); iter != providerlistUninstalled.end(); iter++) { if (iter == providerlistUninstalled.begin()) - detail += itemToString (*iter, false); + detail += itemToString( *iter ); else - detail += "\n " + itemToString (*iter, false); + detail += "\n " + itemToString( mapItem(*iter) ); } - } + } break; } @@ -977,12 +1162,12 @@ ResolverProblemList SATResolver::problems () { ResolverProblemList resolverProblems; - if (_solv && _solv->problems.count) { + if (_solv && solver_problem_count(_solv)) { Pool *pool = _solv->pool; int pcnt; Id p, rp, what; Id problem, solution, element; - Solvable *s, *sd; + sat::Solvable s, sd; CapabilitySet system_requires = SystemCheck::instance().requiredSystemCap(); CapabilitySet system_conflicts = SystemCheck::instance().conflictSystemCap(); @@ -1005,69 +1190,67 @@ SATResolver::problems () element = 0; ProblemSolutionCombi *problemSolution = new ProblemSolutionCombi(resolverProblem); while ((element = solver_next_solutionelement(_solv, problem, solution, element, &p, &rp)) != 0) { - if (p == 0) { + if (p == SOLVER_SOLUTION_JOB) { /* job, rp is index into job queue */ what = _jobQueue.elements[rp]; - switch (_jobQueue.elements[rp-1]) + switch (_jobQueue.elements[rp-1]&(SOLVER_SELECTMASK|SOLVER_JOBMASK)) { - case SOLVER_INSTALL_SOLVABLE: { - s = pool->solvables + what; - PoolItem poolItem = _pool.find (sat::Solvable(what)); + case SOLVER_INSTALL | SOLVER_SOLVABLE: { + s = mapSolvable (what); + PoolItem poolItem = _pool.find (s); if (poolItem) { - if (_solv->installed && s->repo == _solv->installed) { + if (pool->installed && s.get()->repo == pool->installed) { problemSolution->addSingleAction (poolItem, REMOVE); - string description = str::form (_("do not keep %s installed"), solvable2str(pool, s) ); + string description = str::form (_("do not keep %s installed"), s.asString().c_str() ); MIL << description << endl; problemSolution->addDescription (description); } else { - problemSolution->addSingleAction (poolItem, REMOVE); - string description = str::form (_("do not install %s"), solvable2str(pool, s)); + problemSolution->addSingleAction (poolItem, KEEP); + string description = str::form (_("do not install %s"), s.asString().c_str()); MIL << description << endl; problemSolution->addDescription (description); } } else { - ERR << "SOLVER_INSTALL_SOLVABLE: No item found for " << id2str(pool, s->name) << "-" - << id2str(pool, s->evr) << "." << id2str(pool, s->arch) << endl; + ERR << "SOLVER_INSTALL_SOLVABLE: No item found for " << s.asString() << endl; } } break; - case SOLVER_ERASE_SOLVABLE: { - s = pool->solvables + what; - PoolItem poolItem = _pool.find (sat::Solvable(what)); + case SOLVER_ERASE | SOLVER_SOLVABLE: { + s = mapSolvable (what); + PoolItem poolItem = _pool.find (s); if (poolItem) { - if (_solv->installed && s->repo == _solv->installed) { + if (pool->installed && s.get()->repo == pool->installed) { problemSolution->addSingleAction (poolItem, KEEP); - string description = str::form (_("keep %s"), solvable2str(pool, s)); + string description = str::form (_("keep %s"), s.asString().c_str()); MIL << description << endl; problemSolution->addDescription (description); } else { - problemSolution->addSingleAction (poolItem, INSTALL); - string description = str::form (_("do not forbid installation of %s"), solvable2str(pool, s)); + problemSolution->addSingleAction (poolItem, UNLOCK); + string description = str::form (_("do not forbid installation of %s"), itemToString( poolItem ).c_str()); MIL << description << endl; problemSolution->addDescription (description); } } else { - ERR << "SOLVER_ERASE_SOLVABLE: No item found for " << id2str(pool, s->name) << "-" << id2str(pool, s->evr) << "." << - id2str(pool, s->arch) << endl; + ERR << "SOLVER_ERASE_SOLVABLE: No item found for " << s.asString() << endl; } } break; - case SOLVER_INSTALL_SOLVABLE_NAME: + case SOLVER_INSTALL | SOLVER_SOLVABLE_NAME: { IdString ident( what ); SolverQueueItemInstall_Ptr install = new SolverQueueItemInstall(_pool, ident.asString(), false ); - problemSolution->addSingleAction (install, REMOVE_SOLVE_QUEUE_ITEM); - + problemSolution->addSingleAction (install, REMOVE_SOLVE_QUEUE_ITEM); + string description = str::form (_("do not install %s"), ident.c_str() ); MIL << description << endl; problemSolution->addDescription (description); } break; - case SOLVER_ERASE_SOLVABLE_NAME: + case SOLVER_ERASE | SOLVER_SOLVABLE_NAME: { // As we do not know, if this request has come from resolvePool or - // resolveQueue we will have to take care for both cases. + // resolveQueue we will have to take care for both cases. IdString ident( what ); FindPackage info (problemSolution, KEEP); invokeOnEach( _pool.byIdentBegin( ident ), @@ -1075,17 +1258,17 @@ SATResolver::problems () functor::chain (resfilter::ByInstalled (), // ByInstalled resfilter::ByTransact ()), // will be deinstalled functor::functorRef (info) ); - + SolverQueueItemDelete_Ptr del = new SolverQueueItemDelete(_pool, ident.asString(), false ); - problemSolution->addSingleAction (del, REMOVE_SOLVE_QUEUE_ITEM); - + problemSolution->addSingleAction (del, REMOVE_SOLVE_QUEUE_ITEM); + string description = str::form (_("keep %s"), ident.c_str()); MIL << description << endl; problemSolution->addDescription (description); } break; - case SOLVER_INSTALL_SOLVABLE_PROVIDES: + case SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES: { problemSolution->addSingleAction (Capability(what), REMOVE_EXTRA_REQUIRE); string description = ""; @@ -1096,14 +1279,17 @@ SATResolver::problems () resolverProblem->setDetails( resolverProblem->description() + "\n" + resolverProblem->details() ); resolverProblem->setDescription(_("This request will break your system!")); description = _("ignore the warning of a broken system"); + description += string(" (requires:")+pool_dep2str(pool, what)+")"; + MIL << description << endl; + problemSolution->addFrontDescription (description); } else { - description = str::form (_("do not ask to install a solvable providing %s"), dep2str(pool, what)); + description = str::form (_("do not ask to install a solvable providing %s"), pool_dep2str(pool, what)); + MIL << description << endl; + problemSolution->addDescription (description); } - MIL << description << endl; - problemSolution->addDescription (description); } break; - case SOLVER_ERASE_SOLVABLE_PROVIDES: + case SOLVER_ERASE | SOLVER_SOLVABLE_PROVIDES: { problemSolution->addSingleAction (Capability(what), REMOVE_EXTRA_CONFLICT); string description = ""; @@ -1114,29 +1300,32 @@ SATResolver::problems () resolverProblem->setDetails( resolverProblem->description() + "\n" + resolverProblem->details() ); resolverProblem->setDescription(_("This request will break your system!")); description = _("ignore the warning of a broken system"); + description += string(" (conflicts:")+pool_dep2str(pool, what)+")"; + MIL << description << endl; + problemSolution->addFrontDescription (description); + } else { - description = str::form (_("do not ask to delete all solvables providing %s"), dep2str(pool, what)); + description = str::form (_("do not ask to delete all solvables providing %s"), pool_dep2str(pool, what)); + MIL << description << endl; + problemSolution->addDescription (description); } - MIL << description << endl; - problemSolution->addDescription (description); } break; - case SOLVER_INSTALL_SOLVABLE_UPDATE: + case SOLVER_UPDATE | SOLVER_SOLVABLE: { - PoolItem poolItem = _pool.find (sat::Solvable(what)); - s = pool->solvables + what; + s = mapSolvable (what); + PoolItem poolItem = _pool.find (s); if (poolItem) { - if (_solv->installed && s->repo == _solv->installed) { + if (pool->installed && s.get()->repo == pool->installed) { problemSolution->addSingleAction (poolItem, KEEP); - string description = str::form (_("do not install most recent version of %s"), solvable2str(pool, s)); + string description = str::form (_("do not install most recent version of %s"), s.asString().c_str()); MIL << description << endl; problemSolution->addDescription (description); } else { ERR << "SOLVER_INSTALL_SOLVABLE_UPDATE " << poolItem << " is not selected for installation" << endl; } } else { - ERR << "SOLVER_INSTALL_SOLVABLE_UPDATE: No item found for " << id2str(pool, s->name) << "-" << id2str(pool, s->evr) << "." << - id2str(pool, s->arch) << endl; + ERR << "SOLVER_INSTALL_SOLVABLE_UPDATE: No item found for " << s.asString() << endl; } } break; @@ -1145,57 +1334,87 @@ SATResolver::problems () ERR << "No valid solution available" << endl; break; } + } else if (p == SOLVER_SOLUTION_INFARCH) { + s = mapSolvable (rp); + PoolItem poolItem = _pool.find (s); + if (pool->installed && s.get()->repo == pool->installed) { + problemSolution->addSingleAction (poolItem, LOCK); + string description = str::form (_("keep %s despite the inferior architecture"), s.asString().c_str()); + MIL << description << endl; + problemSolution->addDescription (description); + } else { + problemSolution->addSingleAction (poolItem, INSTALL); + string description = str::form (_("install %s despite the inferior architecture"), s.asString().c_str()); + MIL << description << endl; + problemSolution->addDescription (description); + } + } else if (p == SOLVER_SOLUTION_DISTUPGRADE) { + s = mapSolvable (rp); + PoolItem poolItem = _pool.find (s); + if (pool->installed && s.get()->repo == pool->installed) { + problemSolution->addSingleAction (poolItem, LOCK); + string description = str::form (_("keep obsolete %s"), s.asString().c_str()); + MIL << description << endl; + problemSolution->addDescription (description); + } else { + problemSolution->addSingleAction (poolItem, INSTALL); + string description = str::form (_("install %s from excluded repository"), s.asString().c_str()); + MIL << description << endl; + problemSolution->addDescription (description); + } } else { /* policy, replace p with rp */ - s = pool->solvables + p; - sd = rp ? pool->solvables + rp : 0; - - PoolItem itemFrom = _pool.find (sat::Solvable(p)); + s = mapSolvable (p); + PoolItem itemFrom = _pool.find (s); if (rp) { int gotone = 0; - PoolItem itemTo = _pool.find (sat::Solvable(rp)); + sd = mapSolvable (rp); + PoolItem itemTo = _pool.find (sd); if (itemFrom && itemTo) { problemSolution->addSingleAction (itemTo, INSTALL); + int illegal = policy_is_illegal(_solv, s.get(), sd.get(), 0); - if (evrcmp(pool, s->evr, sd->evr, EVRCMP_COMPARE ) > 0) + if ((illegal & POLICY_ILLEGAL_DOWNGRADE) != 0) { - string description = str::form (_("downgrade of %s to %s"), solvable2str(pool, s), solvable2str(pool, sd)); + string description = str::form (_("downgrade of %s to %s"), s.asString().c_str(), sd.asString().c_str()); MIL << description << endl; problemSolution->addDescription (description); gotone = 1; } - if (!_solv->allowarchchange && s->name == sd->name && s->arch != sd->arch && policy_illegal_archchange(_solv, s, sd)) + if ((illegal & POLICY_ILLEGAL_ARCHCHANGE) != 0) { - string description = str::form (_("architecture change of %s to %s"), solvable2str(pool, s), solvable2str(pool, sd)); + string description = str::form (_("architecture change of %s to %s"), s.asString().c_str(), sd.asString().c_str()); MIL << description << endl; problemSolution->addDescription (description); gotone = 1; } - if (!_solv->allowvendorchange && s->name == sd->name && s->vendor != sd->vendor && policy_illegal_vendorchange(_solv, s, sd)) + if ((illegal & POLICY_ILLEGAL_VENDORCHANGE) != 0) { - string description = str::form (_("install %s (with vendor change)\n %s\n-->\n %s") , - solvable2str(pool, sd) , id2str(pool, s->vendor), - string(sd->vendor ? id2str(pool, sd->vendor) : " (no vendor) ").c_str() ); + IdString s_vendor( s.vendor() ); + IdString sd_vendor( sd.vendor() ); + string description = str::form (_("install %s (with vendor change)\n %s --> %s") , + sd.asString().c_str(), + ( s_vendor ? s_vendor.c_str() : " (no vendor) " ), + ( sd_vendor ? sd_vendor.c_str() : " (no vendor) " ) ); MIL << description << endl; problemSolution->addDescription (description); gotone = 1; } if (!gotone) { - string description = str::form (_("replacement of %s with %s"), solvable2str(pool, s), solvable2str(pool, sd)); + string description = str::form (_("replacement of %s with %s"), s.asString().c_str(), sd.asString().c_str()); MIL << description << endl; problemSolution->addDescription (description); } } else { - ERR << id2str(pool, s->name) << "-" << id2str(pool, s->evr) << "." << id2str(pool, s->arch) - << " or " << id2str(pool, sd->name) << "-" << id2str(pool, sd->evr) << "." << id2str(pool, sd->arch) << " not found" << endl; + ERR << s.asString() << " or " << sd.asString() << " not found" << endl; } } else { if (itemFrom) { - string description = str::form (_("deinstallation of %s"), solvable2str(pool, s)); + string description = str::form (_("deinstallation of %s"), s.asString().c_str()); MIL << description << endl; problemSolution->addDescription (description); problemSolution->addSingleAction (itemFrom, REMOVE); @@ -1210,14 +1429,14 @@ 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); + PoolItem item = _pool.find (sat::Solvable(ignoreId)); + ProblemSolutionIgnore *problemSolution = new ProblemSolutionIgnore(resolverProblem, item); resolverProblem->addSolution (problemSolution, false); // Solutions will be shown at the end - MIL << "Ignore some dependencies of " << item << endl; - MIL << "------------------------------------" << endl; - } - + MIL << "ignore some dependencies of " << item << endl; + MIL << "------------------------------------" << endl; + } + // save problem resolverProblems.push_back (resolverProblem); } @@ -1239,51 +1458,90 @@ SATResolver::applySolutions (const ProblemSolutionList & solutions) void SATResolver::setLocks() { - for (PoolItemList::const_iterator iter = _items_to_lock.begin(); iter != _items_to_lock.end(); iter++) { + for (PoolItemList::const_iterator iter = _items_to_lock.begin(); iter != _items_to_lock.end(); ++iter) { sat::detail::SolvableIdType ident( (*iter)->satSolvable().id() ); if (iter->status().isInstalled()) { MIL << "Lock installed item " << *iter << endl; - queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE ); + queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE ); queue_push( &(_jobQueue), ident ); } else { MIL << "Lock NOT installed item " << *iter << endl; - queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE ); + queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE | MAYBE_CLEANDEPS ); queue_push( &(_jobQueue), ident ); } } - for (PoolItemList::const_iterator iter = _items_to_keep.begin(); iter != _items_to_keep.end(); iter++) { - sat::detail::SolvableIdType ident( (*iter)->satSolvable().id() ); - if (iter->status().isInstalled()) { - MIL << "Keep installed item " << *iter << endl; - queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE | SOLVER_WEAK); - queue_push( &(_jobQueue), ident ); - } else { - MIL << "Keep NOT installed item " << *iter << ident << endl; - queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE | SOLVER_WEAK); - queue_push( &(_jobQueue), ident ); + /////////////////////////////////////////////////////////////////// + // Weak locks: Ignore if an item with this name is already installed. + // If it's not installed try to keep it this way using a weak delete + /////////////////////////////////////////////////////////////////// + std::set unifiedByName; + for (PoolItemList::const_iterator iter = _items_to_keep.begin(); iter != _items_to_keep.end(); ++iter) { + IdString ident( (*iter)->satSolvable().ident() ); + if ( unifiedByName.insert( ident ).second ) + { + if ( ! ui::Selectable::get( *iter )->hasInstalledObj() ) + { + MIL << "Keep NOT installed name " << ident << " (" << *iter << ")" << endl; + queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE_NAME | SOLVER_WEAK | MAYBE_CLEANDEPS ); + queue_push( &(_jobQueue), ident.id() ); } - } + } + } } void SATResolver::setSystemRequirements() { CapabilitySet system_requires = SystemCheck::instance().requiredSystemCap(); CapabilitySet system_conflicts = SystemCheck::instance().conflictSystemCap(); - - for (CapabilitySet::const_iterator iter = system_requires.begin(); iter != system_requires.end(); iter++) { - queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE_PROVIDES ); + + for (CapabilitySet::const_iterator iter = system_requires.begin(); iter != system_requires.end(); ++iter) { + queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES ); queue_push( &(_jobQueue), iter->id() ); MIL << "SYSTEM Requires " << *iter << endl; } - for (CapabilitySet::const_iterator iter = system_conflicts.begin(); iter != system_conflicts.end(); iter++) { - queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE_PROVIDES); + for (CapabilitySet::const_iterator iter = system_conflicts.begin(); iter != system_conflicts.end(); ++iter) { + queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE_PROVIDES | MAYBE_CLEANDEPS ); queue_push( &(_jobQueue), iter->id() ); MIL << "SYSTEM Conflicts " << *iter << endl; } + + // Lock the architecture of the running systems rpm + // package on distupgrade. + if ( _distupgrade && ZConfig::instance().systemRoot() == "/" ) + { + ResPool pool( ResPool::instance() ); + IdString rpm( "rpm" ); + for_( it, pool.byIdentBegin(rpm), pool.byIdentEnd(rpm) ) + { + if ( (*it)->isSystem() ) + { + Capability archrule( (*it)->arch(), rpm.c_str(), Capability::PARSED ); + queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE_NAME | SOLVER_ESSENTIAL ); + queue_push( &(_jobQueue), archrule.id() ); + + } + } + } +} + +sat::StringQueue SATResolver::autoInstalled() const +{ + sat::StringQueue ret; + if ( _solv ) + ::solver_get_userinstalled( _solv, ret, GET_USERINSTALLED_NAMES|GET_USERINSTALLED_INVERTED ); + return ret; } - + +sat::StringQueue SATResolver::userInstalled() const +{ + sat::StringQueue ret; + if ( _solv ) + ::solver_get_userinstalled( _solv, ret, GET_USERINSTALLED_NAMES ); + return ret; +} + /////////////////////////////////////////////////////////////////// };// namespace detail