00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <sstream>
00023
00024 #include "zypp/CapFactory.h"
00025 #include "zypp/CapMatch.h"
00026 #include "zypp/CapSet.h"
00027 #include "zypp/base/Logger.h"
00028 #include "zypp/base/String.h"
00029 #include "zypp/base/Gettext.h"
00030 #include "zypp/VendorAttr.h"
00031 #include "zypp/base/Algorithm.h"
00032 #include "zypp/ResPool.h"
00033 #include "zypp/ResFilters.h"
00034 #include "zypp/CapFilters.h"
00035 #include "zypp/ResStatus.h"
00036 #include "zypp/Dep.h"
00037
00038 #include "zypp/ZYppFactory.h"
00039
00040 #include "zypp/solver/detail/QueueItemRequire.h"
00041 #include "zypp/solver/detail/QueueItemBranch.h"
00042 #include "zypp/solver/detail/QueueItemUninstall.h"
00043 #include "zypp/solver/detail/QueueItemInstall.h"
00044 #include "zypp/solver/detail/QueueItem.h"
00045 #include "zypp/solver/detail/ResolverContext.h"
00046 #include "zypp/solver/detail/ResolverInfoDependsOn.h"
00047 #include "zypp/solver/detail/ResolverInfoMisc.h"
00048 #include "zypp/solver/detail/ResolverInfoNeededBy.h"
00049 #include "zypp/solver/detail/ResolverInfoMissingReq.h"
00050 #include "zypp/solver/detail/Helper.h"
00051
00053 namespace zypp
00054 {
00055
00056 namespace solver
00057 {
00058
00059 namespace detail
00060 {
00061
00062 using namespace std;
00063
00064 IMPL_PTR_TYPE(QueueItemRequire);
00065
00066
00067
00068 std::ostream &
00069 QueueItemRequire::dumpOn( std::ostream & os ) const
00070 {
00071 os << "[" << (_soft?"Soft":"") << "Require: ";
00072 os << _capability;
00073 if (_requiring_item) {
00074 os << ", Required by " << _requiring_item;
00075 }
00076 if (_upgraded_item) {
00077 os << ", Upgrades " << _upgraded_item;
00078 }
00079 if (_lost_item) {
00080 os << ", Lost " << _lost_item;
00081 }
00082 if (_remove_only) os << ", Remove Only";
00083 return os << "]";
00084 }
00085
00086
00087
00088 QueueItemRequire::QueueItemRequire (const ResPool & pool, const Capability & cap, bool soft)
00089 : QueueItem (QUEUE_ITEM_TYPE_REQUIRE, pool)
00090 , _capability (cap)
00091 , _soft (soft)
00092 , _remove_only (false)
00093 {
00094 _XDEBUG("QueueItemRequire::QueueItemRequire(" << cap << (soft?", soft":"") << ")");
00095 }
00096
00097
00098 QueueItemRequire::~QueueItemRequire()
00099 {
00100 }
00101
00102
00103
00104 void
00105 QueueItemRequire::addPoolItem (PoolItem_Ref item)
00106 {
00107 assert (!_requiring_item);
00108 _requiring_item = item;
00109 }
00110
00111
00112
00113 struct UniqTable
00114 {
00116 struct Order
00117 {
00119 bool operator()( PoolItem_Ref lhs, PoolItem_Ref rhs ) const
00120 {
00121 int res = lhs->name().compare( rhs->name() );
00122 if ( res )
00123 return res == -1;
00124
00125 return lhs->edition() < rhs->edition();
00126 }
00127 };
00129 typedef std::set<PoolItem,Order> UTable;
00130
00131
00133 bool has( PoolItem_Ref item_r ) const
00134 { return _table.find( item_r ) != _table.end(); }
00135
00139 void remember( PoolItem_Ref item_r )
00140 { _table.insert( item_r ); }
00141
00142
00144 UTable _table;
00145 };
00146
00147
00148 struct RequireProcess
00149 {
00150 PoolItem_Ref _requirer;
00151 const Capability _capability;
00152 ResolverContext_Ptr _context;
00153 ResPool _pool;
00154
00155 PoolItemList providers;
00156
00157
00158 typedef map<string,PoolItem_Ref> UniqMap;
00159 UniqMap uniq;
00160
00161 RequireProcess (PoolItem_Ref r, const Capability & c, ResolverContext_Ptr ctx, const ResPool & p)
00162 : _requirer (r)
00163 , _capability (c)
00164 , _context (ctx)
00165 , _pool (p)
00166 { }
00167
00168 bool operator()( const CapAndItem & cai )
00169 {
00170 PoolItem provider = cai.item;
00171 Capability match = cai.cap;
00172
00173 ResStatus status = _context->getStatus( provider );
00174 PoolItem_Ref upgrades = Helper::findInstalledItem (_pool, provider);
00175
00176 XXX << "RequireProcessInfo (" << provider << " provides " << match << ", is " << status << ")" << endl;
00177
00178
00179
00180
00181
00182
00183 if (_capability != Capability()
00184 && _capability != match) {
00185 return true;
00186 }
00187
00188 if (!provider->arch().compatibleWith( _context->architecture() )) {
00189 MIL << "provider " << provider << " has incompatible arch '" << provider->arch() << "'" << endl;
00190 return true;
00191 }
00192
00193 if ( upgrades
00194 && upgrades.resolvable()->arch() != provider->arch()
00195 && provider->kind() != ResTraits<Atom>::kind )
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 {
00207
00208 MIL << "provider " << provider << " has OTHER arch '" << provider->arch() << "' than the updated item "
00209 << upgrades << endl;
00210 PoolItemList ignore = _context->getIgnoreArchitectureItem();
00211 PoolItemList::iterator it;
00212 for (it = ignore.begin(); it != ignore.end(); ++it) {
00213 if (provider == *it) break;
00214 }
00215 if (it != ignore.end()) {
00216 MIL << " ---> will be ignored " << endl;
00217 } else {
00218 return true;
00219 }
00220 }
00221
00222
00223 bool vendorFit = true;
00224 if ( provider
00225 && upgrades
00226 && !VendorAttr::instance().equivalent(provider->vendor(), upgrades->vendor())) {
00227
00228 MIL << "provider " << provider << " has ANOTHER vendor '" << provider->vendor() << "' than the updated item "
00229 << upgrades << "(vendor: " << upgrades->vendor() << ")" << endl;
00230 PoolItemList ignore = _context->getIgnoreVendorItem();
00231 PoolItemList::iterator it;
00232 for (it = ignore.begin(); it != ignore.end(); ++it) {
00233 if (provider == *it) break;
00234 }
00235 if (it != ignore.end()) {
00236 MIL << " ---> will be ignored " << endl;
00237 } else {
00238 vendorFit = false;
00239 }
00240 }
00241
00242 Capability failed_cap;
00243
00244 if (! (status.isToBeUninstalled() || status.isImpossible())
00245 && ! _context->isParallelInstall( provider )
00246 && _context->itemIsPossible( provider, failed_cap )
00247 && ! provider.status().isLocked()
00248 && vendorFit
00249 && ! (provider.status().isKept()
00250 &&provider.status().isByUser())
00251 ) {
00252
00253
00254 if (status.isToBeInstalled()
00255 || (status.isUninstalled()
00256 && provider.status().isToBeInstalled()))
00257 {
00258 providers.clear();
00259 providers.push_front( provider );
00260 return false;
00261 }
00262
00263
00264 if (!_context->tryAllPossibilities()) {
00265
00266
00267
00268
00269 UniqMap::iterator upos = uniq.find( provider->name() );
00270
00271 if (upos != uniq.end()) {
00272 if ((upos->second->arch().compare( provider->arch() ) < 0)
00273 || ((upos->second->arch().compare( provider->arch() ) == 0)
00274 && (upos->second->edition().compare( provider->edition() ) < 0) ) )
00275 {
00276
00277
00278
00279 for (PoolItemList::iterator it = providers.begin(); it != providers.end(); ++it) {
00280 if (*it == upos->second) {
00281
00282 _XDEBUG("Kicking " << *it << " for " << provider);
00283 providers.erase( it );
00284 _context->setSkippedPossibilities( true );
00285 break;
00286 }
00287 }
00288 upos = uniq.end();
00289 } else {
00290 if (upos->second != provider) {
00291
00292 _XDEBUG("Ignoring " << provider);
00293 _context->setSkippedPossibilities( true );
00294 }
00295 }
00296 }
00297 if (upos == uniq.end()) {
00298 providers.push_front( provider );
00299 uniq[provider->name()] = provider;
00300 }
00301 } else {
00302
00303 providers.push_front( provider );
00304 }
00305 }
00306
00307 return true;
00308 }
00309 };
00310
00311
00312 struct NoInstallableProviders
00313 {
00314 PoolItem_Ref requirer;
00315 ResolverContext_Ptr context;
00316 ResPool pool;
00317
00318 bool operator()( const CapAndItem cai)
00319 {
00320 PoolItem provider = cai.item;
00321 Capability match = cai.cap;
00322 PoolItem_Ref upgrades = Helper::findInstalledItem (pool, provider);
00323
00324 string msg_str;
00325
00326
00327 ResStatus status = context->getStatus( provider );
00328
00329 ResolverInfoMisc_Ptr misc_info;
00330 Capability failed_cap;
00331
00332 if (status.isToBeUninstalled()) {
00333 misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_UNINSTALL_PROVIDER, requirer, RESOLVER_INFO_PRIORITY_VERBOSE, match);
00334 misc_info->setOtherPoolItem (provider);
00335 } else if (context->isParallelInstall (provider)) {
00336 misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_PARALLEL_PROVIDER, requirer, RESOLVER_INFO_PRIORITY_VERBOSE, match);
00337 misc_info->setOtherPoolItem (provider);
00338 } else if (status.isImpossible()
00339 || ! context->itemIsPossible( provider, failed_cap )) {
00340 misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_NOT_INSTALLABLE_PROVIDER, requirer, RESOLVER_INFO_PRIORITY_VERBOSE, match);
00341 misc_info->setOtherPoolItem (provider);
00342 if (!requirer
00343 && failed_cap != Capability::noCap)
00344 {
00345 ResolverInfoMissingReq_Ptr missing = new ResolverInfoMissingReq( provider, failed_cap );
00346 missing->flagAsImportant();
00347 context->addInfo( missing );
00348 }
00349 } else if (provider.status().isLocked()) {
00350 misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_LOCKED_PROVIDER, requirer, RESOLVER_INFO_PRIORITY_VERBOSE, match);
00351 misc_info->setOtherPoolItem (provider);
00352 } else if (provider.status().isKept() && provider.status().isByUser()) {
00353 misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_KEEP_PROVIDER, requirer, RESOLVER_INFO_PRIORITY_VERBOSE, match);
00354 misc_info->setOtherPoolItem (provider);
00355 } else if (provider
00356 && upgrades
00357 && !VendorAttr::instance().equivalent(provider->vendor(), upgrades->vendor())) {
00358 misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_OTHER_VENDOR_PROVIDER,
00359 upgrades, RESOLVER_INFO_PRIORITY_VERBOSE, match);
00360 misc_info->setOtherPoolItem (provider);
00361 }
00362 else if (provider->arch().compatibleWith( context->architecture() )) {
00363 misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_OTHER_ARCH_PROVIDER,
00364 requirer, RESOLVER_INFO_PRIORITY_VERBOSE, match);
00365 misc_info->setOtherPoolItem (provider);
00366 }
00367
00368 if (misc_info != NULL) {
00369 context->addInfo (misc_info);
00370 }
00371
00372 return true;
00373 }
00374 };
00375
00376 typedef map<string, PoolItem_Ref> UpgradesMap;
00377
00378 struct LookForUpgrades
00379 {
00380 PoolItem_Ref installed;
00381 ResolverContext_Ptr _context;
00382 UpgradesMap upgrades;
00383
00384 LookForUpgrades (PoolItem_Ref i, ResolverContext_Ptr ctx)
00385 : installed (i)
00386 , _context (ctx)
00387 { }
00388
00389 bool operator()( PoolItem_Ref provider )
00390 {
00391 if ( provider.status().maySetToBeInstalled( ResStatus::SOLVER )) {
00392
00393 UpgradesMap::iterator it = upgrades.find( provider->name() );
00394
00395 if (it != upgrades.end()) {
00396 if (!_context->upgradeMode()
00397 && it->second->arch() != installed->arch()
00398 && provider->arch() == installed->arch()) {
00399
00400
00401 it->second = provider;
00402 } else {
00403 int cmp = it->second->arch().compare( provider->arch() );
00404 if ((_context->upgradeMode()
00405 || it->second->arch() != installed->arch())
00406 && cmp < 0) {
00407 it->second = provider;
00408 }
00409 else if (cmp == 0) {
00410 if (it->second->edition().compare( provider->edition() ) < 0) {
00411 it->second = provider;
00412 }
00413 }
00414 }
00415 } else {
00416 upgrades[provider->name()] = provider;
00417 }
00418 }
00419 return true;
00420 }
00421 };
00422
00423
00424
00425
00426
00427 struct HintItem
00428 {
00429 PoolItem_Ref match;
00430
00431 bool operator()( const CapAndItem & cai )
00432 {
00433 if (cai.item.status().staysInstalled()
00434 || cai.item.status().isToBeInstalled())
00435 {
00436 match = cai.item;
00437 return false;
00438 }
00439 return true;
00440 }
00441 };
00442
00443
00444
00445
00446
00447 static bool
00448 codependent_items (const PoolItem_Ref item1, const PoolItem_Ref item2)
00449 {
00450 string name1 = item1->name();
00451 string name2 = item2->name();
00452 string::size_type len1 = name1.size();
00453 string::size_type len2 = name2.size();
00454
00455 if (len2 < len1) {
00456 string swap = name1;
00457 string::size_type swap_len = len1;
00458 name1 = name2;
00459 name2 = swap;
00460 len1 = len2;
00461 len2 = swap_len;
00462 }
00463
00464
00465 if (len1 < len2
00466 && name1.compare (0, len1, name2) == 0
00467 && name2[len1] == '-') {
00468 return true;
00469 }
00470
00471 return false;
00472 }
00473
00474
00475
00476
00477 static bool
00478 hint_match( const CapSet & cset, ResPool pool )
00479 {
00480 HintItem info;
00481
00482 for (CapSet::const_iterator cit = cset.begin(); cit != cset.end(); ++cit) {
00483 Dep dep( Dep::PROVIDES );
00484 invokeOnEach( pool.byCapabilityIndexBegin( cit->index(), dep ),
00485 pool.byCapabilityIndexEnd( cit->index(), dep ),
00486 resfilter::ByCapMatch( *cit ),
00487 functor::functorRef<bool,CapAndItem>(info) );
00488 }
00489 if (info.match) MIL << "hint_match(" << info.match << ")" << endl;
00490 return info.match;
00491 }
00492
00493
00494
00495 bool
00496 QueueItemRequire::process (const QueueItemList & mainQueue,
00497 ResolverContext_Ptr context, QueueItemList & new_items)
00498 {
00499 _XDEBUG("QueueItemRequire::process(" << *this << ")");
00500
00501 bool fulfilled = false;
00502
00503 if (_requiring_item)
00504 {
00505 fulfilled = context->requirementIsInstalledOrUnneeded (_capability, _requiring_item,
00506 _soft?Dep::RECOMMENDS:Dep::REQUIRES);
00507 } else {
00508 fulfilled = context->requirementIsMet (_capability, PoolItem_Ref(), Dep::REQUIRES);
00509 }
00510
00511 if (fulfilled) {
00512 _XDEBUG("requirement is already met in current context");
00513 return true;
00514 }
00515
00516
00517 IgnoreMap ignoreMap = context->getIgnoreRequires();
00518 for (IgnoreMap::iterator it = ignoreMap.begin();
00519 it != ignoreMap.end(); it++) {
00520 if ( (!(it->first)
00521 || it->first == _requiring_item)
00522 && it->second == _capability) {
00523 _XDEBUG("Found ignoring requires " << _capability << " for " << _requiring_item);
00524 return true;
00525 } else {
00526 _XDEBUG("Ignoring requires " << it->second << " for " << it->first << " does not fit");
00527 }
00528 }
00529
00530 RequireProcess info (_requiring_item, Capability(), context, pool());
00531
00532 int num_providers = 0;
00533
00534 if (! _remove_only) {
00535
00536 Dep dep( Dep::PROVIDES );
00537 XXX << "Look for providers of " << _capability << endl;
00538
00539 invokeOnEach( pool().byCapabilityIndexBegin( _capability.index(), dep ),
00540 pool().byCapabilityIndexEnd( _capability.index(), dep ),
00541 resfilter::ByCapMatch( _capability ),
00542 functor::functorRef<bool,CapAndItem>(info) );
00543
00544 _XDEBUG("Look for providers of " << _capability);
00545
00546 num_providers = info.providers.size();
00547
00548 _XDEBUG( "requirement is met by " << num_providers << " resolvable");
00549
00550
00551
00552
00553
00554
00555
00556
00557 if (num_providers > 1) {
00558 #if 1 // see also line 618
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568 if (num_providers == 2) {
00569 PoolItemList::iterator it = info.providers.begin();
00570 PoolItem first( *it++ );
00571 PoolItem second( *it );
00572
00573 if (NVRA(first.resolvable()) == NVRA(second.resolvable()))
00574 {
00575
00576 int cmp = first->arch().compare( second->arch() );
00577 if (cmp < 0) {
00578 --it;
00579 }
00580
00581 if (cmp != 0) {
00582 info.providers.erase( it );
00583 num_providers = 1;
00584 goto provider_done;
00585 }
00586 }
00587 }
00588 #endif
00589 MIL << "Have " << num_providers << " providers for " << _capability << endl;
00590 int to_be_installed = 0;
00591 int uninstalled = 0;
00592 std::map<std::string,PoolItem> language_freshens;
00593 ZYpp::Ptr z = zypp::getZYpp();
00594 ZYpp::LocaleSet requested_locales = z->getRequestedLocales();
00595 bool requested_locale_match = false;
00596 PoolItem requested_locale_item;
00597 PoolItemSet hints;
00598
00599 for (PoolItemList::iterator it = info.providers.begin(); it != info.providers.end(); ++it) {
00600 PoolItem item = *it;
00601 if (item.status().isToBeInstalled()) {
00602 to_be_installed++;
00603 }
00604 if (item.status().staysUninstalled()) {
00605 uninstalled++;
00606 }
00607 CapSet freshens( item->dep( Dep::FRESHENS ) );
00608
00609
00610
00611 for (CapSet::const_iterator cit = freshens.begin(); cit != freshens.end(); ++cit) {
00612 if (cit->refers() == ResTraits<Language>::kind) {
00613 string loc = cit->index();
00614 MIL << "Look for language fallback " << loc << ":" << item << endl;
00615 if (requested_locales.find( Locale( loc ) ) != requested_locales.end()) {
00616 MIL << "Locale '" << loc << "' is requested" << endl;
00617 requested_locale_match = true;
00618 requested_locale_item = item;
00619 }
00620 language_freshens[loc] = item;
00621 }
00622 }
00623
00624
00625 if (hint_match( item->dep( Dep::SUPPLEMENTS ), pool() )
00626 || hint_match( item->dep( Dep::ENHANCES ), pool() ))
00627 {
00628 hints.insert( item );
00629 }
00630
00631 }
00632
00633 if (hints.empty()
00634 && to_be_installed == 0
00635 && !requested_locale_match)
00636 {
00637
00638
00639 for (ZYpp::LocaleSet::const_iterator rit = requested_locales.begin(); rit != requested_locales.end(); ++rit) {
00640
00641
00642 Locale l = *rit;
00643 for (;;) {
00644 Locale fallback = l.fallback();
00645 if (fallback == Locale::noCode
00646 || fallback == l)
00647 {
00648 break;
00649 }
00650 MIL << "requested " << l << " fallback " << fallback << endl;
00651 std::map<std::string,PoolItem>::const_iterator match = language_freshens.find( fallback.code() );
00652 if (match != language_freshens.end()) {
00653 MIL << match->second << " matches the fallback" << endl;
00654 info.providers.clear();
00655 info.providers.push_back( match->second );
00656 break;
00657 }
00658 l = fallback;
00659 }
00660 }
00661 #if 0 // just debug
00662 std::string mil = "language_freshens ";
00663 for (std::map<std::string,PoolItem>::const_iterator it = language_freshens.begin(); it != language_freshens.end(); ++it) {
00664 if (it != language_freshens.begin()) mil += ", ";
00665 mil += it->first;
00666 }
00667 MIL << mil << endl;
00668 #endif
00669 }
00670 else if (to_be_installed == 0
00671 && !hints.empty())
00672 {
00673 MIL << "Have " << hints.size() << " hints" << endl;
00674 info.providers.clear();
00675 for (PoolItemSet::const_iterator it = hints.begin(); it != hints.end(); ++it) {
00676 if (*it == requested_locale_item) {
00677
00678 info.providers.push_back( *it );
00679 } else {
00680
00681 std::map<std::string,PoolItem>::const_iterator itFr;
00682
00683 for (itFr = language_freshens.begin(); itFr != language_freshens.end(); ++itFr) {
00684 if (*it == itFr->second) break;
00685 }
00686 if (itFr == language_freshens.end()) {
00687
00688 info.providers.push_back( *it );
00689 }
00690 }
00691 }
00692 if (info.providers.empty()) {
00693
00694
00695 info.providers.push_back( *(hints.begin()) );
00696 }
00697 }
00698 else {
00699
00700
00701
00702 MIL << to_be_installed << " to-be-installed, " << uninstalled << " uninstalled" << endl;
00703
00704 if (to_be_installed > 0
00705 && uninstalled > 0)
00706 {
00707 PoolItemList::iterator next;
00708 for (PoolItemList::iterator it = info.providers.begin(); it != info.providers.end();) {
00709 next = it; ++next;
00710 if (it->status().staysUninstalled()) {
00711 MIL << "Not considering " << *it << endl;
00712 info.providers.erase (it);
00713 }
00714 it = next;
00715 }
00716 }
00717 }
00718
00719 if (!context->tryAllPossibilities()) {
00720
00721 Arch bestArch = Arch();
00722 PoolItemList::iterator it;
00723 for (it = info.providers.begin();
00724 it != info.providers.end(); it++) {
00725 if (bestArch.compare( (*it)->arch() ) < 0) {
00726 bestArch = (*it)->arch();
00727 }
00728 }
00729
00730
00731
00732
00733 PoolItemList::iterator next;
00734 for (it = info.providers.begin();
00735 it != info.providers.end();) {
00736
00737 bool nameFit = false;
00738 CapFactory factory;
00739 if (isKind<capability::NamedCap>( _capability ) ) {
00740 Capability capTest = factory.parse ( (*it)->kind(), (*it)->name(), Rel::ANY, Edition::noedition );
00741 if (capTest.matches (_capability) == CapMatch::yes) {
00742 nameFit = true;
00743 _XDEBUG("Required Capability " << _capability << " has the same name as the provider:" << *it);
00744 _XDEBUG(" --> do not trow away althout it could have the wrong architecture");
00745 }
00746 }
00747
00748 next = it; ++next;
00749 if ((*it)->arch() != bestArch
00750 && (*it)->arch() != Arch_noarch
00751 && !nameFit) {
00752 _XDEBUG("Kicking " << *it << " due best architecture " << bestArch);
00753 info.providers.erase( it );
00754 }
00755 it = next;
00756 }
00757 }
00758
00759 num_providers = info.providers.size();
00760
00761 }
00762 #if 1 // see also line 474
00763 provider_done:;
00764 #endif
00765 }
00766
00767
00768
00769
00770
00771 if (num_providers == 0) {
00772
00773 if (_soft) goto finished;
00774
00775 _DEBUG( "Unfulfilled requirement '" << _capability << "'. trying different solution");
00776
00777 QueueItemUninstall_Ptr uninstall_item = NULL;
00778 QueueItemBranch_Ptr branch_item = NULL;
00779 bool explore_uninstall_branch = true;
00780
00781
00782
00783 if (!_upgraded_item
00784 || _lost_item)
00785 {
00786 ResolverInfo_Ptr err_info;
00787 NoInstallableProviders info;
00788 info.requirer = _requiring_item;
00789 info.context = context;
00790 info.pool = pool();
00791
00792
00793
00794
00795
00796 Dep dep( Dep::PROVIDES );
00797
00798 invokeOnEach( pool().byCapabilityIndexBegin( _capability.index(), dep ),
00799 pool().byCapabilityIndexEnd( _capability.index(), dep ),
00800 resfilter::ByCapMatch( _capability ),
00801 functor::functorRef<bool,CapAndItem>(info) );
00802
00803 }
00804
00805
00806
00807
00808 if ((_upgraded_item
00809 || _lost_item
00810 || context->verifying())
00811
00812 && _requiring_item)
00813 {
00814
00815 LookForUpgrades info (_requiring_item, context);
00816
00817
00818
00819 invokeOnEach( pool().byNameBegin( _requiring_item->name() ), pool().byNameEnd( _requiring_item->name() ),
00820 functor::chain (resfilter::ByKind( _requiring_item->kind() ),
00821 resfilter::byEdition<CompareByGT<Edition> >( _requiring_item->edition() ) ),
00822 functor::functorRef<bool,PoolItem>(info) );
00823
00824 if (!info.upgrades.empty()) {
00825 string label;
00826
00827 branch_item = new QueueItemBranch (pool());
00828
00829 ostringstream req_str; req_str << _requiring_item;
00830 ostringstream up_str;
00831 if (_upgraded_item)
00832 up_str << _upgraded_item;
00833 else
00834 up_str << _requiring_item;
00835 ostringstream cap_str; cap_str << _capability;
00836
00837
00838 label = str::form (_("for requiring %s for %s when upgrading %s"),
00839 cap_str.str().c_str(), req_str.str().c_str(), up_str.str().c_str());
00840 branch_item->setLabel (label);
00841 _DEBUG("Branching: " + label)
00842
00843 for (UpgradesMap::const_iterator iter = info.upgrades.begin(); iter != info.upgrades.end(); ++iter) {
00844 PoolItem_Ref upgrade_item = iter->second;
00845 QueueItemInstall_Ptr install_item;
00846 Capability failed_cap;
00847
00848 if (context->itemIsPossible( upgrade_item, failed_cap )) {
00849
00850 install_item = new QueueItemInstall (pool(), upgrade_item, _soft);
00851 install_item->setUpgrades (_requiring_item);
00852 branch_item->addItem (install_item);
00853
00854 ResolverInfoNeededBy_Ptr upgrade_info = new ResolverInfoNeededBy (upgrade_item);
00855 if (_upgraded_item)
00856 upgrade_info->addRelatedPoolItem (_upgraded_item);
00857 upgrade_info->setCapability (_capability, Dep::REQUIRES);
00858 install_item->addInfo (upgrade_info);
00859
00860
00861
00862
00863 if (explore_uninstall_branch) {
00864 CapSet requires = upgrade_item->dep (Dep::REQUIRES);
00865 CapSet::const_iterator iter = requires.begin();
00866 for (; iter != requires.end(); iter++) {
00867 const Capability req = *iter;
00868 if (! context->requirementIsMet (req, upgrade_item, Dep::REQUIRES)) {
00869 break;
00870 }
00871 }
00872 if (iter == requires.end()) {
00873 explore_uninstall_branch = false;
00874 }
00875 }
00876
00877 }
00878 }
00879 }
00880
00881 if (!info.upgrades.empty()
00882 && branch_item->isEmpty ())
00883 {
00884
00885 for (UpgradesMap::const_iterator iter = info.upgrades.begin(); iter != info.upgrades.end(); ++iter) {
00886 ResolverInfoMisc_Ptr misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_NO_UPGRADE, _requiring_item, RESOLVER_INFO_PRIORITY_VERBOSE);
00887 if (iter == info.upgrades.begin()) {
00888 misc_info->setOtherPoolItem( iter->second );
00889 }
00890 misc_info->addRelatedPoolItem( iter->second );
00891 context->addInfo( misc_info );
00892
00893 explore_uninstall_branch = true;
00894 }
00895
00896
00897
00898
00899
00900
00901 } else if (!info.upgrades.empty()
00902 && explore_uninstall_branch
00903 && _requiring_item
00904 && _upgraded_item
00905 && codependent_items (_requiring_item, _upgraded_item)
00906 && !_lost_item)
00907 {
00908 explore_uninstall_branch = false;
00909 }
00910
00911 }
00912
00913 ResStatus status = context->getStatus(_requiring_item);
00914
00915 if (context->verifying()) {
00916
00917 explore_uninstall_branch = true;
00918 }
00919 else if (status.isToBeInstalled()
00920 && !status.isToBeUninstalled()
00921 || _requiring_item.status().staysInstalled())
00922 {
00923
00924
00925
00926 ResolverInfo_Ptr misc_info;
00927 if (!_upgraded_item) {
00928 if (_remove_only) {
00929 misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_NO_OTHER_PROVIDER,
00930 _requiring_item, RESOLVER_INFO_PRIORITY_VERBOSE, _capability);
00931 } else {
00932 misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_NO_PROVIDER,
00933 _requiring_item, RESOLVER_INFO_PRIORITY_VERBOSE, _capability);
00934 }
00935 } else {
00936 misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_CANT_SATISFY,
00937 _requiring_item, RESOLVER_INFO_PRIORITY_VERBOSE,
00938 _capability);
00939 }
00940 context->addInfo (misc_info);
00941 }
00942
00943 if (explore_uninstall_branch && _requiring_item) {
00944 ResolverInfo_Ptr log_info;
00945 uninstall_item = new QueueItemUninstall (pool(), _requiring_item, QueueItemUninstall::UNSATISFIED);
00946 uninstall_item->setPriority(0);
00947
00948 uninstall_item->setCapability (_capability);
00949
00950 if (_lost_item) {
00951 log_info = new ResolverInfoDependsOn (_requiring_item, _lost_item);
00952 uninstall_item->addInfo (log_info);
00953 }
00954
00955 if (_remove_only)
00956 uninstall_item->setRemoveOnly ();
00957 }
00958
00959 if (uninstall_item && branch_item) {
00960 branch_item->addItem (uninstall_item);
00961 new_items.push_back (branch_item);
00962 } else if (uninstall_item) {
00963 new_items.push_front (uninstall_item);
00964 } else if (branch_item) {
00965 new_items.push_back (branch_item);
00966 } else {
00967
00968 ResolverInfo_Ptr misc_info;
00969 if (!_upgraded_item) {
00970 if (_remove_only) {
00971 misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_NO_OTHER_PROVIDER,
00972 _requiring_item, RESOLVER_INFO_PRIORITY_VERBOSE, _capability);
00973 } else {
00974 misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_NO_PROVIDER,
00975 _requiring_item, RESOLVER_INFO_PRIORITY_VERBOSE, _capability);
00976 }
00977 } else {
00978 ResolverInfo_Ptr misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_CANT_SATISFY,
00979 _requiring_item, RESOLVER_INFO_PRIORITY_VERBOSE,
00980 _capability);
00981 }
00982 context->addError (misc_info);
00983 }
00984
00985 }
00986
00987
00988
00989
00990
00991 else if (num_providers == 1) {
00992
00993 _XDEBUG( "Found exactly one resolvable, installing it.");
00994
00995 PoolItem item = info.providers.front();
00996
00997
00998
00999 if (_soft
01000 && item.status().isUninstalled()
01001 && !item.status().maySetSoftTransact( true, ResStatus::SOLVER ) )
01002 {
01003 _DEBUG("Can't soft-transact " << item);
01004 goto finished;
01005 }
01006 QueueItemInstall_Ptr install_item = new QueueItemInstall (pool(), item, _soft);
01007 install_item->setDependency (_capability);
01008
01009
01010 if (_requiring_item) {
01011 install_item->setNeededBy (_requiring_item);
01012 }
01013 new_items.push_front (install_item);
01014
01015 }
01016
01017
01018
01019
01020
01021 else if (num_providers > 1) {
01022
01023 _DEBUG( "Branching: Found more than one provider of " << _capability);
01024
01025 QueueItemBranch_Ptr branch_item = new QueueItemBranch( pool() );
01026
01027 for (PoolItemList::const_iterator iter = info.providers.begin(); iter != info.providers.end(); iter++) {
01028
01029 PoolItem item = *iter;
01030
01031
01032
01033 if (_soft
01034 && item.status().isUninstalled()
01035 && !item.status().maySetSoftTransact( true, ResStatus::SOLVER ) )
01036 {
01037 _DEBUG("Can't soft-transact " << item);
01038 continue;
01039 }
01040
01041 QueueItemInstall_Ptr install_item = new QueueItemInstall( pool(), item, _soft );
01042 install_item->setDependency( _capability );
01043 branch_item->addItem( install_item );
01044
01045
01046 if (_requiring_item) {
01047 install_item->setNeededBy( _requiring_item );
01048 }
01049 }
01050
01051 if (!branch_item->isEmpty())
01052 new_items.push_back (branch_item);
01053
01054 } else {
01055 abort ();
01056 }
01057
01058 finished:
01059
01060 return true;
01061 }
01062
01063
01064
01065 QueueItem_Ptr
01066 QueueItemRequire::copy (void) const
01067 {
01068 QueueItemRequire_Ptr new_require = new QueueItemRequire (pool(), _capability);
01069
01070 new_require->QueueItem::copy(this);
01071
01072 new_require->_requiring_item = _requiring_item;
01073 new_require->_upgraded_item = _upgraded_item;
01074 new_require->_remove_only = _remove_only;
01075
01076 return new_require;
01077 }
01078
01079
01080 int
01081 QueueItemRequire::cmp (QueueItem_constPtr item) const
01082 {
01083 int cmp = this->compare (item);
01084 if (cmp != 0)
01085 return cmp;
01086
01087 QueueItemRequire_constPtr require = dynamic_pointer_cast<const QueueItemRequire>(item);
01088
01089 if (_capability != require->capability())
01090 {
01091 cmp = -1;
01092 }
01093 return cmp;
01094 }
01095
01097 };
01100 };
01103 };
01105