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