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