libzypp 8.13.6
|
00001 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ 00002 /* SATResolver.cc 00003 * 00004 * Copyright (C) 2000-2002 Ximian, Inc. 00005 * Copyright (C) 2005 SUSE Linux Products GmbH 00006 * 00007 * This program is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU General Public License, 00009 * version 2, as published by the Free Software Foundation. 00010 * 00011 * This program is distributed in the hope that it will be useful, but 00012 * WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 00019 * 02111-1307, USA. 00020 */ 00021 extern "C" 00022 { 00023 #include <satsolver/repo_solv.h> 00024 #include <satsolver/poolarch.h> 00025 #include <satsolver/evr.h> 00026 #include <satsolver/poolvendor.h> 00027 #include <satsolver/policy.h> 00028 #include <satsolver/bitmap.h> 00029 #include <satsolver/queue.h> 00030 } 00031 00032 #include "zypp/solver/detail/Helper.h" 00033 #include "zypp/base/String.h" 00034 #include "zypp/Product.h" 00035 #include "zypp/Capability.h" 00036 #include "zypp/ResStatus.h" 00037 #include "zypp/VendorAttr.h" 00038 #include "zypp/base/LogTools.h" 00039 #include "zypp/base/String.h" 00040 #include "zypp/base/Gettext.h" 00041 #include "zypp/base/Algorithm.h" 00042 #include "zypp/ResPool.h" 00043 #include "zypp/ResFilters.h" 00044 #include "zypp/ZConfig.h" 00045 #include "zypp/sat/Pool.h" 00046 #include "zypp/sat/WhatProvides.h" 00047 #include "zypp/sat/WhatObsoletes.h" 00048 #include "zypp/solver/detail/SATResolver.h" 00049 #include "zypp/solver/detail/ProblemSolutionCombi.h" 00050 #include "zypp/solver/detail/ProblemSolutionIgnore.h" 00051 #include "zypp/solver/detail/SolverQueueItemInstall.h" 00052 #include "zypp/solver/detail/SolverQueueItemDelete.h" 00053 #include "zypp/solver/detail/SystemCheck.h" 00054 00056 namespace zypp 00057 { 00058 00059 namespace solver 00060 { 00061 00062 namespace detail 00063 { 00064 00065 using namespace std; 00066 00067 IMPL_PTR_TYPE(SATResolver); 00068 00069 #define MAYBE_CLEANDEPS (cleandepsOnRemove()?SOLVER_CLEANDEPS:0) 00070 00071 //--------------------------------------------------------------------------- 00072 // Callbacks for SAT policies 00073 //--------------------------------------------------------------------------- 00074 00075 int vendorCheck( Pool *pool, Solvable *solvable1, Solvable *solvable2 ) 00076 { 00077 return VendorAttr::instance().equivalent( IdString(solvable1->vendor), 00078 IdString(solvable2->vendor) ) ? 0 : 1; 00079 } 00080 00081 00082 inline std::string itemToString( const PoolItem & item ) 00083 { 00084 if ( !item ) 00085 return std::string(); 00086 00087 sat::Solvable slv( item.satSolvable() ); 00088 std::string ret( slv.asString() ); // n-v-r.a 00089 if ( ! slv.isSystem() ) 00090 { 00091 ret += "["; 00092 ret += slv.repository().alias(); 00093 ret += "]"; 00094 } 00095 return ret; 00096 } 00097 00098 inline PoolItem getPoolItem( Id id_r ) 00099 { 00100 PoolItem ret( (sat::Solvable( id_r )) ); 00101 if ( !ret && id_r ) 00102 INT << "id " << id_r << " not found in ZYPP pool." << endl; 00103 return ret; 00104 } 00105 00106 //--------------------------------------------------------------------------- 00107 00108 std::ostream & 00109 SATResolver::dumpOn( std::ostream & os ) const 00110 { 00111 os << "<resolver>" << endl; 00112 if (_solv) { 00113 os << " fixsystem = " << _solv->fixsystem << endl; 00114 os << " allowdowngrade = " << _solv->allowdowngrade << endl; 00115 os << " allowarchchange = " << _solv->allowarchchange << endl; 00116 os << " allowvendorchange = " << _solv->allowvendorchange << endl; 00117 os << " allowuninstall = " << _solv->allowuninstall << endl; 00118 os << " updatesystem = " << _solv->updatesystem << endl; 00119 os << " noupdateprovide = " << _solv->noupdateprovide << endl; 00120 os << " dosplitprovides = " << _solv->dosplitprovides << endl; 00121 os << " onlyRequires = " << _solv->dontinstallrecommended << endl; 00122 os << " ignorealreadyrecommended = " << _solv->ignorealreadyrecommended << endl; 00123 os << " distupgrade = " << _distupgrade << endl; 00124 os << " distupgrade_removeunsupported = " << _distupgrade_removeunsupported << endl; 00125 os << " solveSrcPackages = " << _solveSrcPackages << endl; 00126 os << " cleandepsOnRemove = " << _cleandepsOnRemove << endl; 00127 } else { 00128 os << "<NULL>"; 00129 } 00130 return os << "<resolver/>" << endl; 00131 } 00132 00133 //--------------------------------------------------------------------------- 00134 00135 SATResolver::SATResolver (const ResPool & pool, Pool *SATPool) 00136 : _pool (pool) 00137 , _SATPool (SATPool) 00138 , _solv(NULL) 00139 , _fixsystem(false) 00140 , _allowdowngrade(false) 00141 , _allowarchchange(false) 00142 , _allowvendorchange(ZConfig::instance().solver_allowVendorChange()) 00143 , _allowuninstall(false) 00144 , _updatesystem(false) 00145 , _noupdateprovide(false) 00146 , _dosplitprovides(false) 00147 , _onlyRequires(ZConfig::instance().solver_onlyRequires()) 00148 , _ignorealreadyrecommended(false) 00149 , _distupgrade(false) 00150 , _distupgrade_removeunsupported(false) 00151 , _solveSrcPackages(false) 00152 , _cleandepsOnRemove(ZConfig::instance().solver_cleandepsOnRemove()) 00153 { 00154 } 00155 00156 00157 SATResolver::~SATResolver() 00158 { 00159 } 00160 00161 //--------------------------------------------------------------------------- 00162 00163 00164 ResPool 00165 SATResolver::pool (void) const 00166 { 00167 return _pool; 00168 } 00169 00170 00171 void 00172 SATResolver::resetItemTransaction (PoolItem item) 00173 { 00174 bool found = false; 00175 for (PoolItemList::const_iterator iter = _items_to_remove.begin(); 00176 iter != _items_to_remove.end(); ++iter) { 00177 if (*iter == item) { 00178 _items_to_remove.remove(*iter); 00179 found = true; 00180 break; 00181 } 00182 } 00183 if (!found) { 00184 for (PoolItemList::const_iterator iter = _items_to_install.begin(); 00185 iter != _items_to_install.end(); ++iter) { 00186 if (*iter == item) { 00187 _items_to_install.remove(*iter); 00188 found = true; 00189 break; 00190 } 00191 } 00192 } 00193 if (!found) { 00194 for (PoolItemList::const_iterator iter = _items_to_keep.begin(); 00195 iter != _items_to_keep.end(); ++iter) { 00196 if (*iter == item) { 00197 _items_to_keep.remove(*iter); 00198 found = true; 00199 break; 00200 } 00201 } 00202 } 00203 if (!found) { 00204 for (PoolItemList::const_iterator iter = _items_to_lock.begin(); 00205 iter != _items_to_lock.end(); ++iter) { 00206 if (*iter == item) { 00207 _items_to_lock.remove(*iter); 00208 found = true; 00209 break; 00210 } 00211 } 00212 } 00213 } 00214 00215 00216 void 00217 SATResolver::addPoolItemToInstall (PoolItem item) 00218 { 00219 resetItemTransaction (item); 00220 _items_to_install.push_back (item); 00221 _items_to_install.unique (); 00222 } 00223 00224 00225 void 00226 SATResolver::addPoolItemsToInstallFromList (PoolItemList & rl) 00227 { 00228 for (PoolItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) { 00229 addPoolItemToInstall (*iter); 00230 } 00231 } 00232 00233 00234 void 00235 SATResolver::addPoolItemToRemove (PoolItem item) 00236 { 00237 resetItemTransaction (item); 00238 _items_to_remove.push_back (item); 00239 _items_to_remove.unique (); 00240 } 00241 00242 00243 void 00244 SATResolver::addPoolItemsToRemoveFromList (PoolItemList & rl) 00245 { 00246 for (PoolItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) { 00247 addPoolItemToRemove (*iter); 00248 } 00249 } 00250 00251 void 00252 SATResolver::addPoolItemToLock (PoolItem item) 00253 { 00254 resetItemTransaction (item); 00255 _items_to_lock.push_back (item); 00256 _items_to_lock.unique (); 00257 } 00258 00259 void 00260 SATResolver::addPoolItemToKeep (PoolItem item) 00261 { 00262 resetItemTransaction (item); 00263 _items_to_keep.push_back (item); 00264 _items_to_keep.unique (); 00265 } 00266 00267 //--------------------------------------------------------------------------- 00268 00269 // copy marked item from solution back to pool 00270 // if data != NULL, set as APPL_LOW (from establishPool()) 00271 00272 static void 00273 SATSolutionToPool (PoolItem item, const ResStatus & status, const ResStatus::TransactByValue causer) 00274 { 00275 // resetting 00276 item.status().resetTransact (causer); 00277 item.status().resetWeak (); 00278 00279 bool r; 00280 00281 // installation/deletion 00282 if (status.isToBeInstalled()) { 00283 r = item.status().setToBeInstalled (causer); 00284 _XDEBUG("SATSolutionToPool install returns " << item << ", " << r); 00285 } 00286 else if (status.isToBeUninstalledDueToUpgrade()) { 00287 r = item.status().setToBeUninstalledDueToUpgrade (causer); 00288 _XDEBUG("SATSolutionToPool upgrade returns " << item << ", " << r); 00289 } 00290 else if (status.isToBeUninstalled()) { 00291 r = item.status().setToBeUninstalled (causer); 00292 _XDEBUG("SATSolutionToPool remove returns " << item << ", " << r); 00293 } 00294 00295 return; 00296 } 00297 00298 //---------------------------------------------------------------------------- 00299 //---------------------------------------------------------------------------- 00300 // resolvePool 00301 //---------------------------------------------------------------------------- 00302 //---------------------------------------------------------------------------- 00303 00304 //---------------------------------------------------------------------------- 00305 // Helper functions for the ZYPP-Pool 00306 //---------------------------------------------------------------------------- 00307 00308 00309 //------------------------------------------------------------------------------------------------------------ 00310 // This function loops over the pool and grabs all items 00311 // It clears all previous bySolver() states also 00312 // 00313 // Every toBeInstalled is passed to zypp::solver:detail::Resolver.addPoolItemToInstall() 00314 // Every toBeUninstalled is passed to zypp::solver:detail::Resolver.addPoolItemToRemove() 00315 // 00316 // Solver results must be written back to the pool. 00317 //------------------------------------------------------------------------------------------------------------ 00318 00319 00320 struct SATCollectTransact : public resfilter::PoolItemFilterFunctor 00321 { 00322 SATResolver & resolver; 00323 00324 SATCollectTransact (SATResolver & r) 00325 : resolver (r) 00326 { } 00327 00328 bool operator()( PoolItem item ) // only transacts() items go here 00329 { 00330 ResStatus status = item.status(); 00331 bool by_solver = (status.isBySolver() || status.isByApplLow()); 00332 00333 if (by_solver) { 00334 item.status().resetTransact( ResStatus::APPL_LOW );// clear any solver/establish transactions 00335 return true; // back out here, dont re-queue former solver result 00336 } 00337 00338 if ( item.satSolvable().isKind<SrcPackage>() && ! resolver.solveSrcPackages() ) 00339 { 00340 // Later we may continue on a per source package base. 00341 return true; // dont process this source package. 00342 } 00343 00344 if (status.isToBeInstalled()) { 00345 resolver.addPoolItemToInstall(item); // -> install! 00346 } 00347 else if (status.isToBeUninstalled()) { 00348 resolver.addPoolItemToRemove(item); // -> remove ! 00349 } 00350 else if (status.isLocked() 00351 && !by_solver) { 00352 resolver.addPoolItemToLock (item); 00353 } 00354 else if (status.isKept() 00355 && !by_solver) { 00356 resolver.addPoolItemToKeep (item); 00357 } 00358 00359 return true; 00360 } 00361 }; 00362 00363 00364 //---------------------------------------------------------------------------- 00365 //---------------------------------------------------------------------------- 00366 // solving..... 00367 //---------------------------------------------------------------------------- 00368 //---------------------------------------------------------------------------- 00369 00370 00371 class CheckIfUpdate : public resfilter::PoolItemFilterFunctor 00372 { 00373 public: 00374 bool is_updated; 00375 bool multiversion; 00376 sat::Solvable _installed; 00377 00378 CheckIfUpdate( sat::Solvable installed_r ) 00379 : is_updated( false ) 00380 , multiversion( installed_r.multiversionInstall() ) 00381 , _installed( installed_r ) 00382 {} 00383 00384 // check this item will be updated 00385 00386 bool operator()( PoolItem item ) 00387 { 00388 if ( item.status().isToBeInstalled() ) 00389 { 00390 if ( ! multiversion || sameNVRA( _installed, item ) ) 00391 { 00392 is_updated = true; 00393 return false; 00394 } 00395 } 00396 return true; 00397 } 00398 }; 00399 00400 00401 class CollectPseudoInstalled : public resfilter::PoolItemFilterFunctor 00402 { 00403 public: 00404 Queue *solvableQueue; 00405 00406 CollectPseudoInstalled( Queue *queue ) 00407 :solvableQueue (queue) 00408 {} 00409 00410 // collecting PseudoInstalled items 00411 bool operator()( PoolItem item ) 00412 { 00413 if ( traits::isPseudoInstalled( item.satSolvable().kind() ) ) 00414 queue_push( solvableQueue, item.satSolvable().id() ); 00415 return true; 00416 } 00417 }; 00418 00419 bool 00420 SATResolver::solving(const CapabilitySet & requires_caps, 00421 const CapabilitySet & conflict_caps) 00422 { 00423 _solv = solver_create( _SATPool ); 00424 _solv->vendorCheckCb = &vendorCheck; 00425 _solv->fixsystem = _fixsystem; 00426 _solv->ignorealreadyrecommended = _ignorealreadyrecommended; 00427 _solv->updatesystem = _updatesystem; 00428 _solv->allowdowngrade = _allowdowngrade; 00429 _solv->allowuninstall = _allowuninstall; 00430 _solv->allowarchchange = _allowarchchange; 00431 _solv->allowvendorchange = _allowvendorchange; 00432 _solv->dosplitprovides = _dosplitprovides; 00433 _solv->noupdateprovide = _noupdateprovide; 00434 _solv->dontinstallrecommended = _onlyRequires; 00435 _solv->distupgrade = _distupgrade; 00436 _solv->distupgrade_removeunsupported = _distupgrade_removeunsupported; 00437 00438 sat::Pool::instance().prepare(); 00439 00440 // Solve ! 00441 MIL << "Starting solving...." << endl; 00442 MIL << *this; 00443 solver_solve( _solv, &(_jobQueue) ); 00444 MIL << "....Solver end" << endl; 00445 00446 // copying solution back to zypp pool 00447 //----------------------------------------- 00448 _result_items_to_install.clear(); 00449 _result_items_to_remove.clear(); 00450 00451 /* solvables to be installed */ 00452 for ( int i = 0; i < _solv->decisionq.count; ++i ) 00453 { 00454 sat::Solvable slv( _solv->decisionq.elements[i] ); 00455 if ( !slv || slv.isSystem() ) 00456 continue; 00457 00458 PoolItem poolItem( slv ); 00459 SATSolutionToPool (poolItem, ResStatus::toBeInstalled, ResStatus::SOLVER); 00460 _result_items_to_install.push_back (poolItem); 00461 } 00462 00463 /* solvables to be erased */ 00464 Repository systemRepo( sat::Pool::instance().findSystemRepo() ); // don't create if it does not exist 00465 if ( systemRepo && ! systemRepo.solvablesEmpty() ) 00466 { 00467 bool mustCheckObsoletes = false; 00468 for_( it, systemRepo.solvablesBegin(), systemRepo.solvablesEnd() ) 00469 { 00470 if (_solv->decisionmap[it->id()] > 0) 00471 continue; 00472 00473 // Check if this is an update 00474 CheckIfUpdate info( *it ); 00475 PoolItem poolItem( *it ); 00476 invokeOnEach( _pool.byIdentBegin( poolItem ), 00477 _pool.byIdentEnd( poolItem ), 00478 resfilter::ByUninstalled(), // ByUninstalled 00479 functor::functorRef<bool,PoolItem> (info) ); 00480 00481 if (info.is_updated) { 00482 SATSolutionToPool( poolItem, ResStatus::toBeUninstalledDueToUpgrade, ResStatus::SOLVER ); 00483 } else { 00484 SATSolutionToPool( poolItem, ResStatus::toBeUninstalled, ResStatus::SOLVER ); 00485 if ( ! mustCheckObsoletes ) 00486 mustCheckObsoletes = true; // lazy check for UninstalledDueToObsolete 00487 } 00488 _result_items_to_remove.push_back (poolItem); 00489 } 00490 if ( mustCheckObsoletes ) 00491 { 00492 sat::WhatObsoletes obsoleted( _result_items_to_install.begin(), _result_items_to_install.end() ); 00493 for_( it, obsoleted.poolItemBegin(), obsoleted.poolItemEnd() ) 00494 { 00495 ResStatus & status( it->status() ); 00496 // WhatObsoletes contains installed items only! 00497 if ( status.transacts() && ! status.isToBeUninstalledDueToUpgrade() ) 00498 status.setToBeUninstalledDueToObsolete(); 00499 } 00500 } 00501 } 00502 00503 /* solvables which are recommended */ 00504 for ( int i = 0; i < _solv->recommendations.count; ++i ) 00505 { 00506 PoolItem poolItem( getPoolItem( _solv->recommendations.elements[i] ) ); 00507 poolItem.status().setRecommended( true ); 00508 } 00509 00510 /* solvables which are suggested */ 00511 for ( int i = 0; i < _solv->suggestions.count; ++i ) 00512 { 00513 PoolItem poolItem( getPoolItem( _solv->suggestions.elements[i] ) ); 00514 poolItem.status().setSuggested( true ); 00515 } 00516 00517 _problem_items.clear(); 00518 /* solvables which are orphaned */ 00519 for ( int i = 0; i < _solv->orphaned.count; ++i ) 00520 { 00521 PoolItem poolItem( getPoolItem( _solv->orphaned.elements[i] ) ); 00522 poolItem.status().setOrphaned( true ); 00523 _problem_items.push_back( poolItem ); 00524 } 00525 00526 /* Write validation state back to pool */ 00527 Queue flags, solvableQueue; 00528 00529 queue_init(&flags); 00530 queue_init(&solvableQueue); 00531 00532 CollectPseudoInstalled collectPseudoInstalled(&solvableQueue); 00533 invokeOnEach( _pool.begin(), 00534 _pool.end(), 00535 functor::functorRef<bool,PoolItem> (collectPseudoInstalled) ); 00536 solver_trivial_installable(_solv, &solvableQueue, &flags ); 00537 for (int i = 0; i < solvableQueue.count; i++) { 00538 PoolItem item = _pool.find (sat::Solvable(solvableQueue.elements[i])); 00539 item.status().setUndetermined(); 00540 00541 if (flags.elements[i] == -1) { 00542 item.status().setNonRelevant(); 00543 _XDEBUG("SATSolutionToPool(" << item << " ) nonRelevant !"); 00544 } else if (flags.elements[i] == 1) { 00545 item.status().setSatisfied(); 00546 _XDEBUG("SATSolutionToPool(" << item << " ) satisfied !"); 00547 } else if (flags.elements[i] == 0) { 00548 item.status().setBroken(); 00549 _XDEBUG("SATSolutionToPool(" << item << " ) broken !"); 00550 } 00551 } 00552 00553 // Solvables which were selected due requirements which have been made by the user will 00554 // be selected by APPL_LOW. We can't use any higher level, because this setting must 00555 // not serve as a request for the next solver run. APPL_LOW is reset before solving. 00556 for (CapabilitySet::const_iterator iter = requires_caps.begin(); iter != requires_caps.end(); iter++) { 00557 sat::WhatProvides rpmProviders(*iter); 00558 for_( iter2, rpmProviders.begin(), rpmProviders.end() ) { 00559 PoolItem poolItem(*iter2); 00560 if (poolItem.status().isToBeInstalled()) { 00561 MIL << "User requirement " << *iter << " sets " << poolItem << endl; 00562 poolItem.status().setTransactByValue (ResStatus::APPL_LOW); 00563 } 00564 } 00565 } 00566 for (CapabilitySet::const_iterator iter = conflict_caps.begin(); iter != conflict_caps.end(); iter++) { 00567 sat::WhatProvides rpmProviders(*iter); 00568 for_( iter2, rpmProviders.begin(), rpmProviders.end() ) { 00569 PoolItem poolItem(*iter2); 00570 if (poolItem.status().isToBeUninstalled()) { 00571 MIL << "User conflict " << *iter << " sets " << poolItem << endl; 00572 poolItem.status().setTransactByValue (ResStatus::APPL_LOW); 00573 } 00574 } 00575 } 00576 00577 if (_solv->problems.count > 0 ) 00578 { 00579 ERR << "Solverrun finished with an ERROR" << endl; 00580 return false; 00581 } 00582 00583 queue_free(&(solvableQueue)); 00584 queue_free(&flags); 00585 00586 return true; 00587 } 00588 00589 00590 void 00591 SATResolver::solverInit(const PoolItemList & weakItems) 00592 { 00593 SATCollectTransact info (*this); 00594 00595 MIL << "SATResolver::solverInit()" << endl; 00596 00597 if (_solv) { 00598 // remove old stuff 00599 solver_free(_solv); 00600 _solv = NULL; 00601 queue_free( &(_jobQueue) ); 00602 } 00603 00604 queue_init( &_jobQueue ); 00605 _items_to_install.clear(); 00606 _items_to_remove.clear(); 00607 _items_to_lock.clear(); 00608 _items_to_keep.clear(); 00609 00610 invokeOnEach ( _pool.begin(), _pool.end(), 00611 functor::functorRef<bool,PoolItem>(info) ); 00612 00613 for (PoolItemList::const_iterator iter = weakItems.begin(); iter != weakItems.end(); iter++) { 00614 Id id = (*iter)->satSolvable().id(); 00615 if (id == ID_NULL) { 00616 ERR << "Weaken: " << *iter << " not found" << endl; 00617 } 00618 MIL << "Weaken dependencies of " << *iter << endl; 00619 queue_push( &(_jobQueue), SOLVER_WEAKENDEPS | SOLVER_SOLVABLE ); 00620 queue_push( &(_jobQueue), id ); 00621 } 00622 00623 // Add rules for parallel installable resolvables with different versions 00624 for_( it, sat::Pool::instance().multiversionBegin(), sat::Pool::instance().multiversionEnd() ) 00625 { 00626 queue_push( &(_jobQueue), SOLVER_NOOBSOLETES | SOLVER_SOLVABLE_NAME ); 00627 queue_push( &(_jobQueue), it->id() ); 00628 } 00629 00630 if ( cleandepsOnRemove() ) 00631 { 00632 // Add all items known to be installed by user request (not solver selected). 00633 for_( it, sat::Pool::instance().onSystemByUserBegin(), sat::Pool::instance().onSystemByUserEnd() ) 00634 { 00635 queue_push( &(_jobQueue), SOLVER_USERINSTALLED | SOLVER_SOLVABLE_NAME ); 00636 queue_push( &(_jobQueue), it->id() ); 00637 } 00638 } 00639 00640 if ( _distupgrade ) 00641 { 00642 if ( ZConfig::instance().solverUpgradeRemoveDroppedPackages() ) 00643 { 00644 MIL << "Checking droplists ..." << endl; 00645 // Dropped packages: look for 'weakremover()' provides 00646 // in dup candidates of installed products. 00647 ResPoolProxy proxy( ResPool::instance().proxy() ); 00648 for_( it, proxy.byKindBegin<Product>(), proxy.byKindEnd<Product>() ) 00649 { 00650 if ( (*it)->onSystem() ) // (to install) or (not to delete) 00651 { 00652 Product::constPtr prodCand( (*it)->candidateAsKind<Product>() ); 00653 if ( ! prodCand || (*it)->identicalInstalledCandidate() ) 00654 continue; // product no longer available or unchanged 00655 00656 CapabilitySet droplist( prodCand->droplist() ); 00657 dumpRangeLine( MIL << "Droplist for " << (*it)->candidateObj() << ": " << droplist.size() << " ", droplist.begin(), droplist.end() ) << endl; 00658 for_( cap, droplist.begin(), droplist.end() ) 00659 { 00660 queue_push( &_jobQueue, SOLVER_DROP_ORPHANED | SOLVER_SOLVABLE_NAME ); 00661 queue_push( &_jobQueue, cap->id() ); 00662 } 00663 } 00664 } 00665 } 00666 else 00667 { 00668 MIL << "Droplist processing is disabled." << endl; 00669 } 00670 } 00671 } 00672 00673 void 00674 SATResolver::solverEnd() 00675 { 00676 // cleanup 00677 solver_free(_solv); 00678 _solv = NULL; 00679 queue_free( &(_jobQueue) ); 00680 } 00681 00682 00683 bool 00684 SATResolver::resolvePool(const CapabilitySet & requires_caps, 00685 const CapabilitySet & conflict_caps, 00686 const PoolItemList & weakItems, 00687 const std::set<Repository> & upgradeRepos) 00688 { 00689 MIL << "SATResolver::resolvePool()" << endl; 00690 00691 // initialize 00692 solverInit(weakItems); 00693 00694 for (PoolItemList::const_iterator iter = _items_to_install.begin(); iter != _items_to_install.end(); iter++) { 00695 Id id = (*iter)->satSolvable().id(); 00696 if (id == ID_NULL) { 00697 ERR << "Install: " << *iter << " not found" << endl; 00698 } else { 00699 MIL << "Install " << *iter << endl; 00700 queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE ); 00701 queue_push( &(_jobQueue), id ); 00702 } 00703 } 00704 00705 for (PoolItemList::const_iterator iter = _items_to_remove.begin(); iter != _items_to_remove.end(); iter++) { 00706 Id id = (*iter)->satSolvable().id(); 00707 if (id == ID_NULL) { 00708 ERR << "Delete: " << *iter << " not found" << endl; 00709 } else { 00710 MIL << "Delete " << *iter << endl; 00711 queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE | MAYBE_CLEANDEPS ); 00712 queue_push( &(_jobQueue), id); 00713 } 00714 } 00715 00716 for_( iter, upgradeRepos.begin(), upgradeRepos.end() ) 00717 { 00718 queue_push( &(_jobQueue), SOLVER_DISTUPGRADE | SOLVER_SOLVABLE_REPO ); 00719 queue_push( &(_jobQueue), iter->get()->repoid ); 00720 MIL << "Upgrade repo " << *iter << endl; 00721 } 00722 00723 for (CapabilitySet::const_iterator iter = requires_caps.begin(); iter != requires_caps.end(); iter++) { 00724 queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES ); 00725 queue_push( &(_jobQueue), iter->id() ); 00726 MIL << "Requires " << *iter << endl; 00727 } 00728 00729 for (CapabilitySet::const_iterator iter = conflict_caps.begin(); iter != conflict_caps.end(); iter++) { 00730 queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE_PROVIDES | MAYBE_CLEANDEPS ); 00731 queue_push( &(_jobQueue), iter->id() ); 00732 MIL << "Conflicts " << *iter << endl; 00733 } 00734 00735 // set requirements for a running system 00736 setSystemRequirements(); 00737 00738 // set locks for the solver 00739 setLocks(); 00740 00741 // solving 00742 bool ret = solving(requires_caps, conflict_caps); 00743 // cleanup 00744 if (ret) 00745 solverEnd(); // remove solver only if no errors happend. Need it for solving problems 00746 00747 (ret?MIL:WAR) << "SATResolver::resolvePool() done. Ret:" << ret << endl; 00748 return ret; 00749 } 00750 00751 00752 bool 00753 SATResolver::resolveQueue(const SolverQueueItemList &requestQueue, 00754 const PoolItemList & weakItems) 00755 { 00756 MIL << "SATResolver::resolvQueue()" << endl; 00757 00758 // initialize 00759 solverInit(weakItems); 00760 00761 // generate solver queue 00762 for (SolverQueueItemList::const_iterator iter = requestQueue.begin(); iter != requestQueue.end(); iter++) { 00763 (*iter)->addRule(_jobQueue); 00764 } 00765 00766 // Add addition item status to the resolve-queue cause these can be set by problem resolutions 00767 for (PoolItemList::const_iterator iter = _items_to_install.begin(); iter != _items_to_install.end(); iter++) { 00768 Id id = (*iter)->satSolvable().id(); 00769 if (id == ID_NULL) { 00770 ERR << "Install: " << *iter << " not found" << endl; 00771 } else { 00772 MIL << "Install " << *iter << endl; 00773 queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE ); 00774 queue_push( &(_jobQueue), id ); 00775 } 00776 } 00777 for (PoolItemList::const_iterator iter = _items_to_remove.begin(); iter != _items_to_remove.end(); iter++) { 00778 sat::detail::IdType ident( (*iter)->satSolvable().ident().id() ); 00779 MIL << "Delete " << *iter << ident << endl; 00780 queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE_NAME | MAYBE_CLEANDEPS ); 00781 queue_push( &(_jobQueue), ident); 00782 } 00783 00784 // set requirements for a running system 00785 setSystemRequirements(); 00786 00787 // set locks for the solver 00788 setLocks(); 00789 00790 // solving 00791 bool ret = solving(); 00792 00793 // cleanup 00794 if (ret) 00795 solverEnd(); // remove solver only if no errors happend. Need it for solving problems 00796 00797 MIL << "SATResolver::resolveQueue() done. Ret:" << ret << endl; 00798 return ret; 00799 } 00800 00802 void SATResolver::doUpdate() 00803 { 00804 MIL << "SATResolver::doUpdate()" << endl; 00805 00806 // initialize 00807 solverInit(PoolItemList()); 00808 00809 // set requirements for a running system 00810 setSystemRequirements(); 00811 00812 // set locks for the solver 00813 setLocks(); 00814 00815 _solv = solver_create( _SATPool ); 00816 _solv->vendorCheckCb = &vendorCheck; 00817 _solv->fixsystem = _fixsystem; 00818 _solv->ignorealreadyrecommended = _ignorealreadyrecommended; 00819 _solv->updatesystem = true; 00820 _solv->allowdowngrade = _allowdowngrade; 00821 _solv->allowuninstall = _allowuninstall; 00822 _solv->allowarchchange = _allowarchchange; 00823 _solv->allowvendorchange = _allowvendorchange; 00824 _solv->dosplitprovides = true; 00825 _solv->noupdateprovide = _noupdateprovide; 00826 _solv->dontinstallrecommended = _onlyRequires; 00827 _solv->distupgrade = _distupgrade; 00828 _solv->distupgrade_removeunsupported = _distupgrade_removeunsupported; 00829 00830 sat::Pool::instance().prepare(); 00831 00832 // Solve ! 00833 MIL << "Starting solving for update...." << endl; 00834 MIL << *this; 00835 solver_solve( _solv, &(_jobQueue) ); 00836 MIL << "....Solver end" << endl; 00837 00838 // copying solution back to zypp pool 00839 //----------------------------------------- 00840 00841 /* solvables to be installed */ 00842 for (int i = 0; i < _solv->decisionq.count; i++) 00843 { 00844 Id p; 00845 p = _solv->decisionq.elements[i]; 00846 if (p < 0 || !sat::Solvable(p)) 00847 continue; 00848 if (sat::Solvable(p).repository().get() == _solv->installed) 00849 continue; 00850 00851 PoolItem poolItem = _pool.find (sat::Solvable(p)); 00852 if (poolItem) { 00853 SATSolutionToPool (poolItem, ResStatus::toBeInstalled, ResStatus::SOLVER); 00854 } else { 00855 ERR << "id " << p << " not found in ZYPP pool." << endl; 00856 } 00857 } 00858 00859 /* solvables to be erased */ 00860 for (int i = _solv->installed->start; i < _solv->installed->start + _solv->installed->nsolvables; i++) 00861 { 00862 if (_solv->decisionmap[i] > 0) 00863 continue; 00864 00865 PoolItem poolItem( _pool.find( sat::Solvable(i) ) ); 00866 if (poolItem) { 00867 // Check if this is an update 00868 CheckIfUpdate info( (sat::Solvable(i)) ); 00869 invokeOnEach( _pool.byIdentBegin( poolItem ), 00870 _pool.byIdentEnd( poolItem ), 00871 resfilter::ByUninstalled(), // ByUninstalled 00872 functor::functorRef<bool,PoolItem> (info) ); 00873 00874 if (info.is_updated) { 00875 SATSolutionToPool (poolItem, ResStatus::toBeUninstalledDueToUpgrade , ResStatus::SOLVER); 00876 } else { 00877 SATSolutionToPool (poolItem, ResStatus::toBeUninstalled, ResStatus::SOLVER); 00878 } 00879 } else { 00880 ERR << "id " << i << " not found in ZYPP pool." << endl; 00881 } 00882 } 00883 00884 // cleanup 00885 solverEnd(); 00886 00887 MIL << "SATResolver::doUpdate() done" << endl; 00888 } 00889 00890 00891 00892 //---------------------------------------------------------------------------- 00893 //---------------------------------------------------------------------------- 00894 // error handling 00895 //---------------------------------------------------------------------------- 00896 //---------------------------------------------------------------------------- 00897 00898 //---------------------------------------------------------------------------- 00899 // helper function 00900 //---------------------------------------------------------------------------- 00901 00902 struct FindPackage : public resfilter::ResObjectFilterFunctor 00903 { 00904 ProblemSolutionCombi *problemSolution; 00905 TransactionKind action; 00906 FindPackage (ProblemSolutionCombi *p, const TransactionKind act) 00907 : problemSolution (p) 00908 , action (act) 00909 { 00910 } 00911 00912 bool operator()( PoolItem p) 00913 { 00914 problemSolution->addSingleAction (p, action); 00915 return true; 00916 } 00917 }; 00918 00919 00920 //---------------------------------------------------------------------------- 00921 // Checking if this solvable/item has a buddy which reflect the real 00922 // user visible description of an item 00923 // e.g. The release package has a buddy to the concerning product item. 00924 // This user want's the message "Product foo conflicts with product bar" and 00925 // NOT "package release-foo conflicts with package release-bar" 00926 //---------------------------------------------------------------------------- 00927 00928 00929 PoolItem SATResolver::mapItem (const PoolItem &item) 00930 { 00931 sat::Solvable buddy = item.buddy(); 00932 if (buddy != sat::Solvable()) 00933 { 00934 return _pool.find (buddy); 00935 } 00936 else 00937 { 00938 return item; 00939 } 00940 } 00941 00942 sat::Solvable SATResolver::mapSolvable (const Id &id) 00943 { 00944 PoolItem item = _pool.find (sat::Solvable(id)); 00945 return mapItem(item).satSolvable(); 00946 } 00947 00948 string SATResolver::SATprobleminfoString(Id problem, string &detail, Id &ignoreId) 00949 { 00950 string ret; 00951 Pool *pool = _solv->pool; 00952 Id probr; 00953 Id dep, source, target; 00954 sat::Solvable s, s2; 00955 00956 ignoreId = 0; 00957 probr = solver_findproblemrule(_solv, problem); 00958 switch (solver_ruleinfo(_solv, probr, &source, &target, &dep)) 00959 { 00960 case SOLVER_RULE_DISTUPGRADE: 00961 s = mapSolvable (source); 00962 ret = str::form (_("%s does not belong to a distupgrade repository"), s.asString().c_str()); 00963 break; 00964 case SOLVER_RULE_INFARCH: 00965 s = mapSolvable (source); 00966 ret = str::form (_("%s has inferior architecture"), s.asString().c_str()); 00967 break; 00968 case SOLVER_RULE_UPDATE: 00969 s = mapSolvable (source); 00970 ret = str::form (_("problem with installed package %s"), s.asString().c_str()); 00971 break; 00972 case SOLVER_RULE_JOB: 00973 ret = _("conflicting requests"); 00974 break; 00975 case SOLVER_RULE_RPM: 00976 ret = _("some dependency problem"); 00977 break; 00978 case SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP: 00979 ret = str::form (_("nothing provides requested %s"), dep2str(pool, dep)); 00980 detail += _("Have you enabled all requested repositories?"); 00981 break; 00982 case SOLVER_RULE_RPM_NOT_INSTALLABLE: 00983 s = mapSolvable (source); 00984 ret = str::form (_("%s is not installable"), s.asString().c_str()); 00985 break; 00986 case SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP: 00987 ignoreId = source; // for setting weak dependencies 00988 s = mapSolvable (source); 00989 ret = str::form (_("nothing provides %s needed by %s"), dep2str(pool, dep), s.asString().c_str()); 00990 break; 00991 case SOLVER_RULE_RPM_SAME_NAME: 00992 s = mapSolvable (source); 00993 s2 = mapSolvable (target); 00994 ret = str::form (_("cannot install both %s and %s"), s.asString().c_str(), s2.asString().c_str()); 00995 break; 00996 case SOLVER_RULE_RPM_PACKAGE_CONFLICT: 00997 s = mapSolvable (source); 00998 s2 = mapSolvable (target); 00999 ret = str::form (_("%s conflicts with %s provided by %s"), s.asString().c_str(), dep2str(pool, dep), s2.asString().c_str()); 01000 break; 01001 case SOLVER_RULE_RPM_PACKAGE_OBSOLETES: 01002 s = mapSolvable (source); 01003 s2 = mapSolvable (target); 01004 ret = str::form (_("%s obsoletes %s provided by %s"), s.asString().c_str(), dep2str(pool, dep), s2.asString().c_str()); 01005 break; 01006 case SOLVER_RULE_RPM_INSTALLEDPKG_OBSOLETES: 01007 s = mapSolvable (source); 01008 s2 = mapSolvable (target); 01009 ret = str::form (_("installed %s obsoletes %s provided by %s"), s.asString().c_str(), dep2str(pool, dep), s2.asString().c_str()); 01010 break; 01011 case SOLVER_RULE_RPM_SELF_CONFLICT: 01012 s = mapSolvable (source); 01013 ret = str::form (_("solvable %s conflicts with %s provided by itself"), s.asString().c_str(), dep2str(pool, dep)); 01014 break; 01015 case SOLVER_RULE_RPM_PACKAGE_REQUIRES: 01016 ignoreId = source; // for setting weak dependencies 01017 s = mapSolvable (source); 01018 Capability cap(dep); 01019 sat::WhatProvides possibleProviders(cap); 01020 01021 // check, if a provider will be deleted 01022 typedef list<PoolItem> ProviderList; 01023 ProviderList providerlistInstalled, providerlistUninstalled; 01024 for_( iter1, possibleProviders.begin(), possibleProviders.end() ) { 01025 PoolItem provider1 = ResPool::instance().find( *iter1 ); 01026 // find pair of an installed/uninstalled item with the same NVR 01027 bool found = false; 01028 for_( iter2, possibleProviders.begin(), possibleProviders.end() ) { 01029 PoolItem provider2 = ResPool::instance().find( *iter2 ); 01030 if (compareByNVR (provider1.resolvable(),provider2.resolvable()) == 0 01031 && ( (provider1.status().isInstalled() && provider2.status().isUninstalled()) 01032 || (provider2.status().isInstalled() && provider1.status().isUninstalled()) )) { 01033 found = true; 01034 break; 01035 } 01036 } 01037 if (!found) { 01038 if (provider1.status().isInstalled()) 01039 providerlistInstalled.push_back(provider1); 01040 else 01041 providerlistUninstalled.push_back(provider1); 01042 } 01043 } 01044 01045 ret = str::form (_("%s requires %s, but this requirement cannot be provided"), s.asString().c_str(), dep2str(pool, dep)); 01046 if (providerlistInstalled.size() > 0) { 01047 detail += _("deleted providers: "); 01048 for (ProviderList::const_iterator iter = providerlistInstalled.begin(); iter != providerlistInstalled.end(); iter++) { 01049 if (iter == providerlistInstalled.begin()) 01050 detail += itemToString( *iter ); 01051 else 01052 detail += "\n " + itemToString( mapItem(*iter) ); 01053 } 01054 } 01055 if (providerlistUninstalled.size() > 0) { 01056 if (detail.size() > 0) 01057 detail += _("\nuninstallable providers: "); 01058 else 01059 detail = _("uninstallable providers: "); 01060 for (ProviderList::const_iterator iter = providerlistUninstalled.begin(); iter != providerlistUninstalled.end(); iter++) { 01061 if (iter == providerlistUninstalled.begin()) 01062 detail += itemToString( *iter ); 01063 else 01064 detail += "\n " + itemToString( mapItem(*iter) ); 01065 } 01066 } 01067 break; 01068 } 01069 01070 return ret; 01071 } 01072 01073 ResolverProblemList 01074 SATResolver::problems () 01075 { 01076 ResolverProblemList resolverProblems; 01077 if (_solv && _solv->problems.count) { 01078 Pool *pool = _solv->pool; 01079 int pcnt; 01080 Id p, rp, what; 01081 Id problem, solution, element; 01082 sat::Solvable s, sd; 01083 01084 CapabilitySet system_requires = SystemCheck::instance().requiredSystemCap(); 01085 CapabilitySet system_conflicts = SystemCheck::instance().conflictSystemCap(); 01086 01087 MIL << "Encountered problems! Here are the solutions:\n" << endl; 01088 pcnt = 1; 01089 problem = 0; 01090 while ((problem = solver_next_problem(_solv, problem)) != 0) { 01091 MIL << "Problem " << pcnt++ << ":" << endl; 01092 MIL << "====================================" << endl; 01093 string detail; 01094 Id ignoreId; 01095 string whatString = SATprobleminfoString (problem,detail,ignoreId); 01096 MIL << whatString << endl; 01097 MIL << "------------------------------------" << endl; 01098 ResolverProblem_Ptr resolverProblem = new ResolverProblem (whatString, detail); 01099 01100 solution = 0; 01101 while ((solution = solver_next_solution(_solv, problem, solution)) != 0) { 01102 element = 0; 01103 ProblemSolutionCombi *problemSolution = new ProblemSolutionCombi(resolverProblem); 01104 while ((element = solver_next_solutionelement(_solv, problem, solution, element, &p, &rp)) != 0) { 01105 if (p == SOLVER_SOLUTION_JOB) { 01106 /* job, rp is index into job queue */ 01107 what = _jobQueue.elements[rp]; 01108 switch (_jobQueue.elements[rp-1]&(SOLVER_SELECTMASK|SOLVER_JOBMASK)) 01109 { 01110 case SOLVER_INSTALL | SOLVER_SOLVABLE: { 01111 s = mapSolvable (what); 01112 PoolItem poolItem = _pool.find (s); 01113 if (poolItem) { 01114 if (_solv->installed && s.get()->repo == _solv->installed) { 01115 problemSolution->addSingleAction (poolItem, REMOVE); 01116 string description = str::form (_("do not keep %s installed"), s.asString().c_str() ); 01117 MIL << description << endl; 01118 problemSolution->addDescription (description); 01119 } else { 01120 problemSolution->addSingleAction (poolItem, KEEP); 01121 string description = str::form (_("do not install %s"), s.asString().c_str()); 01122 MIL << description << endl; 01123 problemSolution->addDescription (description); 01124 } 01125 } else { 01126 ERR << "SOLVER_INSTALL_SOLVABLE: No item found for " << s.asString() << endl; 01127 } 01128 } 01129 break; 01130 case SOLVER_ERASE | SOLVER_SOLVABLE: { 01131 s = mapSolvable (what); 01132 PoolItem poolItem = _pool.find (s); 01133 if (poolItem) { 01134 if (_solv->installed && s.get()->repo == _solv->installed) { 01135 problemSolution->addSingleAction (poolItem, KEEP); 01136 string description = str::form (_("keep %s"), s.asString().c_str()); 01137 MIL << description << endl; 01138 problemSolution->addDescription (description); 01139 } else { 01140 problemSolution->addSingleAction (poolItem, UNLOCK); 01141 string description = str::form (_("do not forbid installation of %s"), itemToString( poolItem ).c_str()); 01142 MIL << description << endl; 01143 problemSolution->addDescription (description); 01144 } 01145 } else { 01146 ERR << "SOLVER_ERASE_SOLVABLE: No item found for " << s.asString() << endl; 01147 } 01148 } 01149 break; 01150 case SOLVER_INSTALL | SOLVER_SOLVABLE_NAME: 01151 { 01152 IdString ident( what ); 01153 SolverQueueItemInstall_Ptr install = 01154 new SolverQueueItemInstall(_pool, ident.asString(), false ); 01155 problemSolution->addSingleAction (install, REMOVE_SOLVE_QUEUE_ITEM); 01156 01157 string description = str::form (_("do not install %s"), ident.c_str() ); 01158 MIL << description << endl; 01159 problemSolution->addDescription (description); 01160 } 01161 break; 01162 case SOLVER_ERASE | SOLVER_SOLVABLE_NAME: 01163 { 01164 // As we do not know, if this request has come from resolvePool or 01165 // resolveQueue we will have to take care for both cases. 01166 IdString ident( what ); 01167 FindPackage info (problemSolution, KEEP); 01168 invokeOnEach( _pool.byIdentBegin( ident ), 01169 _pool.byIdentEnd( ident ), 01170 functor::chain (resfilter::ByInstalled (), // ByInstalled 01171 resfilter::ByTransact ()), // will be deinstalled 01172 functor::functorRef<bool,PoolItem> (info) ); 01173 01174 SolverQueueItemDelete_Ptr del = 01175 new SolverQueueItemDelete(_pool, ident.asString(), false ); 01176 problemSolution->addSingleAction (del, REMOVE_SOLVE_QUEUE_ITEM); 01177 01178 string description = str::form (_("keep %s"), ident.c_str()); 01179 MIL << description << endl; 01180 problemSolution->addDescription (description); 01181 } 01182 break; 01183 case SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES: 01184 { 01185 problemSolution->addSingleAction (Capability(what), REMOVE_EXTRA_REQUIRE); 01186 string description = ""; 01187 01188 // Checking if this problem solution would break your system 01189 if (system_requires.find(Capability(what)) != system_requires.end()) { 01190 // Show a better warning 01191 resolverProblem->setDetails( resolverProblem->description() + "\n" + resolverProblem->details() ); 01192 resolverProblem->setDescription(_("This request will break your system!")); 01193 description = _("ignore the warning of a broken system"); 01194 description += string(" (requires:")+dep2str(pool, what)+")"; 01195 MIL << description << endl; 01196 problemSolution->addFrontDescription (description); 01197 } else { 01198 description = str::form (_("do not ask to install a solvable providing %s"), dep2str(pool, what)); 01199 MIL << description << endl; 01200 problemSolution->addDescription (description); 01201 } 01202 } 01203 break; 01204 case SOLVER_ERASE | SOLVER_SOLVABLE_PROVIDES: 01205 { 01206 problemSolution->addSingleAction (Capability(what), REMOVE_EXTRA_CONFLICT); 01207 string description = ""; 01208 01209 // Checking if this problem solution would break your system 01210 if (system_conflicts.find(Capability(what)) != system_conflicts.end()) { 01211 // Show a better warning 01212 resolverProblem->setDetails( resolverProblem->description() + "\n" + resolverProblem->details() ); 01213 resolverProblem->setDescription(_("This request will break your system!")); 01214 description = _("ignore the warning of a broken system"); 01215 description += string(" (conflicts:")+dep2str(pool, what)+")"; 01216 MIL << description << endl; 01217 problemSolution->addFrontDescription (description); 01218 01219 } else { 01220 description = str::form (_("do not ask to delete all solvables providing %s"), dep2str(pool, what)); 01221 MIL << description << endl; 01222 problemSolution->addDescription (description); 01223 } 01224 } 01225 break; 01226 case SOLVER_UPDATE | SOLVER_SOLVABLE: 01227 { 01228 s = mapSolvable (what); 01229 PoolItem poolItem = _pool.find (s); 01230 if (poolItem) { 01231 if (_solv->installed && s.get()->repo == _solv->installed) { 01232 problemSolution->addSingleAction (poolItem, KEEP); 01233 string description = str::form (_("do not install most recent version of %s"), s.asString().c_str()); 01234 MIL << description << endl; 01235 problemSolution->addDescription (description); 01236 } else { 01237 ERR << "SOLVER_INSTALL_SOLVABLE_UPDATE " << poolItem << " is not selected for installation" << endl; 01238 } 01239 } else { 01240 ERR << "SOLVER_INSTALL_SOLVABLE_UPDATE: No item found for " << s.asString() << endl; 01241 } 01242 } 01243 break; 01244 default: 01245 MIL << "- do something different" << endl; 01246 ERR << "No valid solution available" << endl; 01247 break; 01248 } 01249 } else if (p == SOLVER_SOLUTION_INFARCH) { 01250 s = mapSolvable (rp); 01251 PoolItem poolItem = _pool.find (s); 01252 if (_solv->installed && s.get()->repo == _solv->installed) { 01253 problemSolution->addSingleAction (poolItem, LOCK); 01254 string description = str::form (_("keep %s despite the inferior architecture"), s.asString().c_str()); 01255 MIL << description << endl; 01256 problemSolution->addDescription (description); 01257 } else { 01258 problemSolution->addSingleAction (poolItem, INSTALL); 01259 string description = str::form (_("install %s despite the inferior architecture"), s.asString().c_str()); 01260 MIL << description << endl; 01261 problemSolution->addDescription (description); 01262 } 01263 } else if (p == SOLVER_SOLUTION_DISTUPGRADE) { 01264 s = mapSolvable (rp); 01265 PoolItem poolItem = _pool.find (s); 01266 if (_solv->installed && s.get()->repo == _solv->installed) { 01267 problemSolution->addSingleAction (poolItem, LOCK); 01268 string description = str::form (_("keep obsolete %s"), s.asString().c_str()); 01269 MIL << description << endl; 01270 problemSolution->addDescription (description); 01271 } else { 01272 problemSolution->addSingleAction (poolItem, INSTALL); 01273 string description = str::form (_("install %s from excluded repository"), s.asString().c_str()); 01274 MIL << description << endl; 01275 problemSolution->addDescription (description); 01276 } 01277 } else { 01278 /* policy, replace p with rp */ 01279 s = mapSolvable (p); 01280 if (rp) 01281 sd = mapSolvable (rp); 01282 01283 PoolItem itemFrom = _pool.find (s); 01284 if (s == sd && _solv->distupgrade) 01285 { 01286 PoolItem poolItem = _pool.find (s); 01287 if (poolItem) { 01288 problemSolution->addSingleAction (poolItem, LOCK); // for solver reason: NOT weak lock. 01289 string description = str::form (_("keep obsolete %s"), s.asString().c_str()); 01290 MIL << description << endl; 01291 problemSolution->addDescription (description); 01292 } else { 01293 ERR << "SOLVER_INSTALL_SOLVABLE: No item found for " << s.asString() << endl; 01294 } 01295 } 01296 else if (rp) 01297 { 01298 int gotone = 0; 01299 01300 PoolItem itemTo = _pool.find (sd); 01301 if (itemFrom && itemTo) { 01302 problemSolution->addSingleAction (itemTo, INSTALL); 01303 01304 if (evrcmp(pool, s.get()->evr, sd.get()->evr, EVRCMP_COMPARE ) > 0) 01305 { 01306 string description = str::form (_("downgrade of %s to %s"), s.asString().c_str(), sd.asString().c_str()); 01307 MIL << description << endl; 01308 problemSolution->addDescription (description); 01309 gotone = 1; 01310 } 01311 if (!_solv->allowarchchange && s.get()->name == sd.get()->name && s.get()->arch != sd.get()->arch 01312 && policy_illegal_archchange(_solv, s.get(), sd.get())) 01313 { 01314 string description = str::form (_("architecture change of %s to %s"), s.asString().c_str(), sd.asString().c_str()); 01315 MIL << description << endl; 01316 problemSolution->addDescription (description); 01317 gotone = 1; 01318 } 01319 if (!_solv->allowvendorchange && s.get()->name == sd.get()->name && s.get()->vendor != sd.get()->vendor 01320 && policy_illegal_vendorchange(_solv, s.get(), sd.get())) 01321 { 01322 IdString s_vendor( s.vendor() ); 01323 IdString sd_vendor( sd.vendor() ); 01324 string description = str::form (_("install %s (with vendor change)\n %s --> %s") , 01325 sd.asString().c_str(), 01326 ( s_vendor ? s_vendor.c_str() : " (no vendor) " ), 01327 ( sd_vendor ? sd_vendor.c_str() : " (no vendor) " ) ); 01328 MIL << description << endl; 01329 problemSolution->addDescription (description); 01330 gotone = 1; 01331 } 01332 if (!gotone) { 01333 string description = str::form (_("replacement of %s with %s"), s.asString().c_str(), sd.asString().c_str()); 01334 MIL << description << endl; 01335 problemSolution->addDescription (description); 01336 } 01337 } else { 01338 ERR << s.asString() << " or " << sd.asString() << " not found" << endl; 01339 } 01340 } 01341 else 01342 { 01343 if (itemFrom) { 01344 string description = str::form (_("deinstallation of %s"), s.asString().c_str()); 01345 MIL << description << endl; 01346 problemSolution->addDescription (description); 01347 problemSolution->addSingleAction (itemFrom, REMOVE); 01348 } 01349 } 01350 } 01351 } 01352 resolverProblem->addSolution (problemSolution, 01353 problemSolution->actionCount() > 1 ? true : false); // Solutions with more than 1 action will be shown first. 01354 MIL << "------------------------------------" << endl; 01355 } 01356 01357 if (ignoreId > 0) { 01358 // There is a possibility to ignore this error by setting weak dependencies 01359 PoolItem item = _pool.find (sat::Solvable(ignoreId)); 01360 ProblemSolutionIgnore *problemSolution = new ProblemSolutionIgnore(resolverProblem, item); 01361 resolverProblem->addSolution (problemSolution, 01362 false); // Solutions will be shown at the end 01363 MIL << "ignore some dependencies of " << item << endl; 01364 MIL << "------------------------------------" << endl; 01365 } 01366 01367 // save problem 01368 resolverProblems.push_back (resolverProblem); 01369 } 01370 } 01371 return resolverProblems; 01372 } 01373 01374 void 01375 SATResolver::applySolutions (const ProblemSolutionList & solutions) 01376 { 01377 for (ProblemSolutionList::const_iterator iter = solutions.begin(); 01378 iter != solutions.end(); ++iter) { 01379 ProblemSolution_Ptr solution = *iter; 01380 Resolver dummyResolver(_pool); 01381 if (!solution->apply (dummyResolver)) 01382 break; 01383 } 01384 } 01385 01386 void SATResolver::setLocks() 01387 { 01388 for (PoolItemList::const_iterator iter = _items_to_lock.begin(); iter != _items_to_lock.end(); ++iter) { 01389 sat::detail::SolvableIdType ident( (*iter)->satSolvable().id() ); 01390 if (iter->status().isInstalled()) { 01391 MIL << "Lock installed item " << *iter << endl; 01392 queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE ); 01393 queue_push( &(_jobQueue), ident ); 01394 } else { 01395 MIL << "Lock NOT installed item " << *iter << endl; 01396 queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE | MAYBE_CLEANDEPS ); 01397 queue_push( &(_jobQueue), ident ); 01398 } 01399 } 01400 01402 // Weak locks: Ignore if an item with this name is already installed. 01403 // If it's not installed try to keep it this way using a weak delete 01405 std::set<IdString> unifiedByName; 01406 for (PoolItemList::const_iterator iter = _items_to_keep.begin(); iter != _items_to_keep.end(); ++iter) { 01407 IdString ident( (*iter)->satSolvable().ident() ); 01408 if ( unifiedByName.insert( ident ).second ) 01409 { 01410 if ( ! ui::Selectable::get( *iter )->hasInstalledObj() ) 01411 { 01412 MIL << "Keep NOT installed name " << ident << " (" << *iter << ")" << endl; 01413 queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE_NAME | SOLVER_WEAK | MAYBE_CLEANDEPS ); 01414 queue_push( &(_jobQueue), ident.id() ); 01415 } 01416 } 01417 } 01418 } 01419 01420 void SATResolver::setSystemRequirements() 01421 { 01422 CapabilitySet system_requires = SystemCheck::instance().requiredSystemCap(); 01423 CapabilitySet system_conflicts = SystemCheck::instance().conflictSystemCap(); 01424 01425 for (CapabilitySet::const_iterator iter = system_requires.begin(); iter != system_requires.end(); ++iter) { 01426 queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES ); 01427 queue_push( &(_jobQueue), iter->id() ); 01428 MIL << "SYSTEM Requires " << *iter << endl; 01429 } 01430 01431 for (CapabilitySet::const_iterator iter = system_conflicts.begin(); iter != system_conflicts.end(); ++iter) { 01432 queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE_PROVIDES | MAYBE_CLEANDEPS ); 01433 queue_push( &(_jobQueue), iter->id() ); 01434 MIL << "SYSTEM Conflicts " << *iter << endl; 01435 } 01436 01437 // Lock the architecture of the running systems rpm 01438 // package on distupgrade. 01439 if ( _distupgrade && ZConfig::instance().systemRoot() == "/" ) 01440 { 01441 ResPool pool( ResPool::instance() ); 01442 IdString rpm( "rpm" ); 01443 for_( it, pool.byIdentBegin(rpm), pool.byIdentEnd(rpm) ) 01444 { 01445 if ( (*it)->isSystem() ) 01446 { 01447 Capability archrule( (*it)->arch(), rpm.c_str(), Capability::PARSED ); 01448 queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE_NAME | SOLVER_ESSENTIAL ); 01449 queue_push( &(_jobQueue), archrule.id() ); 01450 01451 } 01452 } 01453 } 01454 } 01455 01456 01458 };// namespace detail 01461 };// namespace solver 01464 };// namespace zypp 01466