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