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