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