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 bool fulfilled = false;
00413
00414 if (_requiring_item
00415 && (_requiring_item->kind() != ResTraits<Package>::kind
00416 || _requiring_item->kind() != ResTraits<Script>::kind
00417 || _requiring_item->kind() != ResTraits<Message>::kind)
00418 )
00419 {
00420 bool unneeded, installed;
00421 fulfilled = context->requirementIsMet (_capability, _is_child, &unneeded, &installed);
00422 if (!fulfilled
00423 || (!unneeded
00424 && !installed)) {
00425 fulfilled = false;
00426 _XDEBUG("Requirement is not unneeded and not installed.");
00427
00428
00429 }
00430 } else {
00431 fulfilled = context->requirementIsMet (_capability, _is_child);
00432 }
00433
00434
00435 if (fulfilled) {
00436 _XDEBUG("requirement is already met in current context");
00437 return true;
00438 }
00439
00440
00441 IgnoreMap ignoreMap = context->getIgnoreRequires();
00442 for (IgnoreMap::iterator it = ignoreMap.begin();
00443 it != ignoreMap.end(); it++) {
00444 if (it->first == _requiring_item
00445 && it->second == _capability) {
00446 _XDEBUG("Found ignoring requires " << _capability << " for " << _requiring_item);
00447 return true;
00448 } else {
00449 _XDEBUG("Ignoring requires " << it->second << " for " << it->first << " does not fit");
00450 }
00451 }
00452
00453 RequireProcess info (_requiring_item, _is_child ? _capability : Capability(), context, pool());
00454
00455 int num_providers = 0;
00456
00457 if (! _remove_only) {
00458
00459 Dep dep( Dep::PROVIDES );
00460 XXX << "Look for providers of " << _capability << endl;
00461
00462 invokeOnEach( pool().byCapabilityIndexBegin( _capability.index(), dep ),
00463 pool().byCapabilityIndexEnd( _capability.index(), dep ),
00464 resfilter::ByCapMatch( _capability ),
00465 functor::functorRef<bool,CapAndItem>(info) );
00466
00467 _XDEBUG("Look for providers of " << _capability);
00468
00469 num_providers = info.providers.size();
00470
00471 _XDEBUG( "requirement is met by " << num_providers << " resolvable");
00472
00473
00474
00475
00476
00477
00478
00479
00480 if (num_providers > 1) {
00481 #if 0 // see also line 599
00482
00483
00484
00485
00486
00487
00488 if (num_providers == 2) {
00489 PoolItemList::iterator it = info.providers.begin();
00490 PoolItem first( *it++ );
00491 PoolItem second( *it );
00492
00493 int cmp = first->arch().compare( second->arch() );
00494 if (cmp < 0) {
00495 --it;
00496 }
00497
00498 if (cmp != 0) {
00499 info.providers.erase( it );
00500 num_providers = 1;
00501 goto provider_done;
00502 }
00503 }
00504 #endif
00505 MIL << "Have " << num_providers << " providers for " << _capability << endl;
00506 int to_be_installed = 0;
00507 int uninstalled = 0;
00508 std::map<std::string,PoolItem> language_freshens;
00509 ZYpp::Ptr z = zypp::getZYpp();
00510 ZYpp::LocaleSet requested_locales = z->getRequestedLocales();
00511 bool requested_locale_match = false;
00512 PoolItemSet hints;
00513
00514 for (PoolItemList::iterator it = info.providers.begin(); it != info.providers.end(); ++it) {
00515 PoolItem item = *it;
00516 if (item.status().isToBeInstalled()) {
00517 to_be_installed++;
00518 }
00519 if (item.status().staysUninstalled()) {
00520 uninstalled++;
00521 }
00522 if (!requested_locale_match) {
00523 CapSet freshens( item->dep( Dep::FRESHENS ) );
00524
00525
00526
00527
00528 for (CapSet::const_iterator cit = freshens.begin(); cit != freshens.end(); ++cit) {
00529 if (cit->refers() == ResTraits<Language>::kind) {
00530 string loc = cit->index();
00531 MIL << "Look for language fallback " << loc << ":" << item << endl;
00532 if (requested_locales.find( Locale( loc ) ) != requested_locales.end()) {
00533 MIL << "Locale '" << loc << "' is requested, not looking further" << endl;
00534 requested_locale_match = true;
00535 break;
00536 }
00537 language_freshens[loc] = item;
00538 }
00539 }
00540 }
00541
00542
00543
00544
00545 if (hint_match( item->dep( Dep::SUPPLEMENTS ), pool() )
00546 || hint_match( item->dep( Dep::ENHANCES ), pool() ))
00547 {
00548 hints.insert( item );
00549 }
00550
00551 }
00552
00553 if (hints.empty()
00554 && to_be_installed == 0
00555 && !requested_locale_match)
00556 {
00557
00558
00559 for (ZYpp::LocaleSet::const_iterator rit = requested_locales.begin(); rit != requested_locales.end(); ++rit) {
00560
00561
00562 Locale l = *rit;
00563 for (;;) {
00564 Locale fallback = l.fallback();
00565 if (fallback == Locale::noCode
00566 || fallback == l)
00567 {
00568 break;
00569 }
00570 MIL << "requested " << l << " fallback " << fallback << endl;
00571 std::map<std::string,PoolItem>::const_iterator match = language_freshens.find( fallback.code() );
00572 if (match != language_freshens.end()) {
00573 MIL << match->second << " matches the fallback" << endl;
00574 info.providers.clear();
00575 info.providers.push_back( match->second );
00576 break;
00577 }
00578 l = fallback;
00579 }
00580 }
00581 #if 0 // just debug
00582 std::string mil = "language_freshens ";
00583 for (std::map<std::string,PoolItem>::const_iterator it = language_freshens.begin(); it != language_freshens.end(); ++it) {
00584 if (it != language_freshens.begin()) mil += ", ";
00585 mil += it->first;
00586 }
00587 MIL << mil << endl;
00588 #endif
00589 }
00590 else if (to_be_installed == 0
00591 && !hints.empty())
00592 {
00593 MIL << "Have " << hints.size() << " hints" << endl;
00594 info.providers.clear();
00595 for (PoolItemSet::const_iterator it = hints.begin(); it != hints.end(); ++it)
00596 info.providers.push_back( *it );
00597 }
00598 else {
00599
00600
00601
00602 MIL << to_be_installed << " to-be-installed, " << uninstalled << " uninstalled" << endl;
00603
00604 if (to_be_installed > 0
00605 && uninstalled > 0)
00606 {
00607 PoolItemList::iterator next;
00608 for (PoolItemList::iterator it = info.providers.begin(); it != info.providers.end(); ++it) {
00609 next = it; ++next;
00610 if (it->status().staysUninstalled()) {
00611 MIL << "Not considering " << *it << endl;
00612 info.providers.erase (it);
00613 }
00614 it = next;
00615 }
00616 }
00617 }
00618
00619 num_providers = info.providers.size();
00620
00621 }
00622 #if 0 // see also line 458
00623 provider_done:;
00624 #endif
00625 }
00626
00627
00628
00629
00630
00631 if (num_providers == 0) {
00632
00633 if (_soft) goto finished;
00634
00635 _DEBUG( "Unfulfilled requirement '" << _capability << "'. trying different solution");
00636
00637 QueueItemUninstall_Ptr uninstall_item = NULL;
00638 QueueItemBranch_Ptr branch_item = NULL;
00639 bool explore_uninstall_branch = true;
00640
00641
00642
00643 if (!_upgraded_item
00644 || _lost_item)
00645 {
00646 ResolverInfo_Ptr err_info;
00647 NoInstallableProviders info;
00648 info.requirer = _requiring_item;
00649 info.context = context;
00650
00651
00652
00653
00654
00655 Dep dep( Dep::PROVIDES );
00656
00657 invokeOnEach( pool().byCapabilityIndexBegin( _capability.index(), dep ),
00658 pool().byCapabilityIndexEnd( _capability.index(), dep ),
00659 resfilter::ByCapMatch( _capability ),
00660 functor::functorRef<bool,CapAndItem>(info) );
00661
00662 }
00663
00664
00665
00666
00667 if ((_upgraded_item
00668 || _lost_item
00669 || context->verifying())
00670
00671 && _requiring_item)
00672 {
00673
00674 LookForUpgrades info (_requiring_item);
00675
00676
00677
00678 invokeOnEach( pool().byNameBegin( _requiring_item->name() ), pool().byNameEnd( _requiring_item->name() ),
00679 functor::chain (resfilter::ByKind( _requiring_item->kind() ),
00680 resfilter::byEdition<CompareByGT<Edition> >( _requiring_item->edition() ) ),
00681 functor::functorRef<bool,PoolItem>(info) );
00682
00683 if (!info.upgrades.empty()) {
00684 string label;
00685
00686 branch_item = new QueueItemBranch (pool());
00687
00688 ostringstream req_str; req_str << _requiring_item;
00689 ostringstream up_str;
00690 if (_upgraded_item)
00691 up_str << _upgraded_item;
00692 else
00693 up_str << _requiring_item;
00694 ostringstream cap_str; cap_str << _capability;
00695
00696
00697 label = str::form (_("for requiring %s for %s when upgrading %s"),
00698 cap_str.str().c_str(), req_str.str().c_str(), up_str.str().c_str());
00699 branch_item->setLabel (label);
00700 _DEBUG("Branching: " + label)
00701
00702 for (UpgradesMap::const_iterator iter = info.upgrades.begin(); iter != info.upgrades.end(); ++iter) {
00703 PoolItem_Ref upgrade_item = iter->second;
00704 QueueItemInstall_Ptr install_item;
00705
00706 if (context->itemIsPossible (upgrade_item)) {
00707
00708 install_item = new QueueItemInstall (pool(), upgrade_item, _soft);
00709 install_item->setUpgrades (_requiring_item);
00710 branch_item->addItem (install_item);
00711
00712 ResolverInfoNeededBy_Ptr upgrade_info = new ResolverInfoNeededBy (upgrade_item);
00713 if (_upgraded_item)
00714 upgrade_info->addRelatedPoolItem (_upgraded_item);
00715 install_item->addInfo (upgrade_info);
00716
00717
00718
00719
00720 if (explore_uninstall_branch) {
00721 CapSet requires = upgrade_item->dep (Dep::REQUIRES);
00722 CapSet::const_iterator iter = requires.begin();
00723 for (; iter != requires.end(); iter++) {
00724 const Capability req = *iter;
00725 if (! context->requirementIsMet (req)) {
00726 break;
00727 }
00728 }
00729 if (iter == requires.end()) {
00730 explore_uninstall_branch = false;
00731 }
00732 }
00733
00734 }
00735 }
00736 }
00737
00738 if (!info.upgrades.empty()
00739 && branch_item->isEmpty ())
00740 {
00741
00742 for (UpgradesMap::const_iterator iter = info.upgrades.begin(); iter != info.upgrades.end(); ++iter) {
00743 ResolverInfoMisc_Ptr misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_NO_UPGRADE, _requiring_item, RESOLVER_INFO_PRIORITY_VERBOSE);
00744 if (iter == info.upgrades.begin()) {
00745 misc_info->setOtherPoolItem( iter->second );
00746 }
00747 misc_info->addRelatedPoolItem( iter->second );
00748 context->addInfo( misc_info );
00749
00750 explore_uninstall_branch = true;
00751 }
00752
00753
00754
00755
00756
00757
00758 } else if (!info.upgrades.empty()
00759 && explore_uninstall_branch
00760 && _requiring_item
00761 && _upgraded_item
00762 && codependent_items (_requiring_item, _upgraded_item)
00763 && !_lost_item)
00764 {
00765 explore_uninstall_branch = false;
00766 }
00767
00768 }
00769
00770 ResStatus status = context->getStatus(_requiring_item);
00771
00772 if (context->verifying()) {
00773
00774 explore_uninstall_branch = true;
00775 }
00776 else if (status.isToBeInstalled()
00777 && !status.isToBeUninstalled()
00778 || _requiring_item.status().staysInstalled())
00779 {
00780
00781
00782
00783 ResolverInfo_Ptr misc_info;
00784 if (!_upgraded_item) {
00785 if (_remove_only) {
00786 misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_NO_OTHER_PROVIDER,
00787 _requiring_item, RESOLVER_INFO_PRIORITY_VERBOSE, _capability);
00788 } else {
00789 misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_NO_PROVIDER,
00790 _requiring_item, RESOLVER_INFO_PRIORITY_VERBOSE, _capability);
00791 }
00792 } else {
00793 misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_CANT_SATISFY,
00794 _requiring_item, RESOLVER_INFO_PRIORITY_VERBOSE,
00795 _capability);
00796 }
00797 context->addInfo (misc_info);
00798 }
00799
00800 if (explore_uninstall_branch && _requiring_item) {
00801 ResolverInfo_Ptr log_info;
00802 uninstall_item = new QueueItemUninstall (pool(), _requiring_item, QueueItemUninstall::UNSATISFIED);
00803 uninstall_item->setCapability (_capability);
00804
00805 if (_lost_item) {
00806 log_info = new ResolverInfoDependsOn (_requiring_item, _lost_item);
00807 uninstall_item->addInfo (log_info);
00808 }
00809
00810 if (_remove_only)
00811 uninstall_item->setRemoveOnly ();
00812 }
00813
00814 if (uninstall_item && branch_item) {
00815 branch_item->addItem (uninstall_item);
00816 new_items.push_back (branch_item);
00817 } else if (uninstall_item) {
00818 new_items.push_front (uninstall_item);
00819 } else if (branch_item) {
00820 new_items.push_back (branch_item);
00821 } else {
00822
00823 ResolverInfo_Ptr misc_info;
00824 if (!_upgraded_item) {
00825 if (_remove_only) {
00826 misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_NO_OTHER_PROVIDER,
00827 _requiring_item, RESOLVER_INFO_PRIORITY_VERBOSE, _capability);
00828 } else {
00829 misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_NO_PROVIDER,
00830 _requiring_item, RESOLVER_INFO_PRIORITY_VERBOSE, _capability);
00831 }
00832 } else {
00833 ResolverInfo_Ptr misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_CANT_SATISFY,
00834 _requiring_item, RESOLVER_INFO_PRIORITY_VERBOSE,
00835 _capability);
00836 }
00837 context->addError (misc_info);
00838 }
00839
00840 }
00841
00842
00843
00844
00845
00846 else if (num_providers == 1) {
00847
00848 _XDEBUG( "Found exactly one resolvable, installing it.");
00849
00850 PoolItem item = info.providers.front();
00851
00852
00853
00854 if (_soft
00855 && item.status().isUninstalled()
00856 && !item.status().maySetSoftTransact( true, ResStatus::SOLVER ) )
00857 {
00858 _DEBUG("Can't soft-transact " << item);
00859 goto finished;
00860 }
00861 QueueItemInstall_Ptr install_item = new QueueItemInstall (pool(), item, _soft);
00862 install_item->addDependency (_capability);
00863
00864
00865 if (_requiring_item) {
00866 install_item->addNeededBy (_requiring_item);
00867 }
00868 new_items.push_front (install_item);
00869
00870 }
00871
00872
00873
00874
00875
00876 else if (num_providers > 1) {
00877
00878 _DEBUG( "Branching: Found more than one provider of " << _capability);
00879
00880 QueueItemBranch_Ptr branch_item = new QueueItemBranch( pool() );
00881
00882 for (PoolItemList::const_iterator iter = info.providers.begin(); iter != info.providers.end(); iter++) {
00883
00884 PoolItem item = *iter;
00885
00886
00887
00888 if (_soft
00889 && item.status().isUninstalled()
00890 && !item.status().maySetSoftTransact( true, ResStatus::SOLVER ) )
00891 {
00892 _DEBUG("Can't soft-transact " << item);
00893 continue;
00894 }
00895
00896 QueueItemInstall_Ptr install_item = new QueueItemInstall( pool(), item, _soft );
00897 install_item->addDependency( _capability );
00898 branch_item->addItem( install_item );
00899
00900
00901 if (_requiring_item) {
00902 install_item->addNeededBy( _requiring_item );
00903 }
00904 }
00905
00906 if (!branch_item->isEmpty())
00907 new_items.push_back (branch_item);
00908
00909 } else {
00910 abort ();
00911 }
00912
00913 finished:
00914
00915 return true;
00916 }
00917
00918
00919
00920 QueueItem_Ptr
00921 QueueItemRequire::copy (void) const
00922 {
00923 QueueItemRequire_Ptr new_require = new QueueItemRequire (pool(), _capability);
00924
00925 new_require->QueueItem::copy(this);
00926
00927 new_require->_requiring_item = _requiring_item;
00928 new_require->_upgraded_item = _upgraded_item;
00929 new_require->_remove_only = _remove_only;
00930
00931 return new_require;
00932 }
00933
00934
00935 int
00936 QueueItemRequire::cmp (QueueItem_constPtr item) const
00937 {
00938 int cmp = this->compare (item);
00939 if (cmp != 0)
00940 return cmp;
00941
00942 QueueItemRequire_constPtr require = dynamic_pointer_cast<const QueueItemRequire>(item);
00943
00944 if (_capability != require->capability())
00945 {
00946 cmp = -1;
00947 }
00948 return cmp;
00949 }
00950
00952 };
00955 };
00958 };
00960