00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "zypp/CapFactory.h"
00023 #include "zypp/CapSet.h"
00024 #include "zypp/CapMatch.h"
00025 #include "zypp/base/Logger.h"
00026 #include "zypp/base/String.h"
00027 #include "zypp/base/Gettext.h"
00028 #include "zypp/base/Exception.h"
00029
00030 #include "zypp/base/Algorithm.h"
00031 #include "zypp/ResPool.h"
00032 #include "zypp/ResFilters.h"
00033 #include "zypp/CapFilters.h"
00034 #include "zypp/CapAndItem.h"
00035
00036 #include "zypp/solver/detail/Types.h"
00037
00038 #include "zypp/solver/detail/QueueItemConflict.h"
00039 #include "zypp/solver/detail/QueueItemBranch.h"
00040 #include "zypp/solver/detail/QueueItemInstall.h"
00041 #include "zypp/solver/detail/QueueItemUninstall.h"
00042 #include "zypp/solver/detail/QueueItem.h"
00043 #include "zypp/solver/detail/ResolverContext.h"
00044 #include "zypp/solver/detail/ResolverInfoConflictsWith.h"
00045 #include "zypp/solver/detail/ResolverInfoMisc.h"
00046 #include "zypp/solver/detail/ResolverInfoObsoletes.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(QueueItemConflict);
00061
00062 #define PHI 1
00063
00064
00065
00066 std::ostream &
00067 QueueItemConflict::dumpOn( std::ostream & os ) const
00068 {
00069 os << "[" << (_soft?"Soft":"") << "Conflict: ";
00070 os << _capability;
00071 os << ", Triggered by ";
00072 os << _conflicting_item;
00073 if (_actually_an_obsolete) os << ", Obsolete !";
00074 if (_explicitly_requested) os << ", Explicit";
00075 os << "]";
00076 return os;
00077 }
00078
00079
00080
00081 QueueItemConflict::QueueItemConflict (const ResPool & pool, const Capability & cap, PoolItem_Ref item, bool soft)
00082 : QueueItem (QUEUE_ITEM_TYPE_CONFLICT, pool)
00083 , _capability (cap)
00084 , _conflicting_item (item)
00085 , _soft (soft)
00086 , _actually_an_obsolete (false)
00087 , _explicitly_requested (false)
00088 {
00089 _XDEBUG("QueueItemConflict::QueueItemConflict(" << cap << ", " << item << (soft?", soft":"") << ")");
00090 }
00091
00092
00093 QueueItemConflict::~QueueItemConflict()
00094 {
00095 }
00096
00097
00098
00099 #if PHI
00100
00101
00102
00103
00104
00105
00106
00107 struct UpgradeCandidate
00108 {
00109 PoolItem_Ref item;
00110 ResolverContext_Ptr context;
00111 PoolItemList upgrades;
00112
00113 UpgradeCandidate (PoolItem_Ref pi, ResolverContext_Ptr ctx)
00114 : item (pi)
00115 , context (ctx)
00116 { }
00117
00118 bool operator() (const CapAndItem & cai)
00119 {
00120
00121 PoolItem candidate = cai.item;
00122
00123
00124
00125 ResStatus status = context->getStatus (candidate);
00126 if ((item->edition().compare(candidate->edition()) < 0)
00127 && item->arch() == candidate->arch()
00128 && (status.isUninstalled()
00129 || status.isToBeUninstalled())
00130
00131
00132
00133 && (!status.isImpossible()) )
00134 {
00135
00136 upgrades.push_back (candidate);
00137 }
00138 return true;
00139 }
00140 };
00141
00142 #endif // PHI
00143
00144
00145
00146
00147 struct ConflictProcess
00148 {
00149 ResPool pool;
00150 PoolItem_Ref conflict_issuer;
00151 const Capability conflict_capability;
00152 ResolverContext_Ptr context;
00153 QueueItemList & new_items;
00154 bool actually_an_obsolete;
00155 bool explicitly_requested;
00156
00157 ConflictProcess (const ResPool & pl, PoolItem_Ref ci, const Capability & cc, ResolverContext_Ptr ct, QueueItemList & ni, bool ao,
00158 bool er)
00159 : pool (pl)
00160 , conflict_issuer (ci)
00161 , conflict_capability (cc)
00162 , context (ct)
00163 , new_items (ni)
00164 , actually_an_obsolete (ao)
00165 , explicitly_requested (er)
00166 { }
00167
00168 bool operator()( const CapAndItem & cai )
00169 {
00170 ResStatus status;
00171 ResolverInfo_Ptr log_info;
00172 CapFactory factory;
00173
00174 PoolItem provider = cai.item;
00175 Capability provides = cai.cap;
00176
00177 _XDEBUG("conflict_process_cb (resolvable[" << provider <<"], provides[" << provides << "], conflicts with [" <<
00178 conflict_issuer << " conflicts: " << conflict_capability);
00179
00180
00181
00182
00183
00184 if (conflict_issuer
00185 && compareByNVRA (provider.resolvable(), conflict_issuer.resolvable()) == 0)
00186 {
00187 _XDEBUG("self-conflict");
00188 return true;
00189 }
00190
00191 #if 0 // Bug 220999; RPM does obsolete virtual provides too
00192
00193
00194
00195
00196
00197
00198
00199
00200 Capability capTest = factory.parse ( provider->kind(), provider->name(), Rel::EQ, provider->edition());
00201
00202 if (actually_an_obsolete
00203 && capTest.matches (provides) != CapMatch::yes )
00204 {
00205 _XDEBUG("obsolete to virtual provide - ignoring");
00206 return true;
00207 }
00208
00209 #endif // Bug 220999; RPM does obsolete virtual provides too
00210
00211 status = context->getStatus(provider);
00212
00213 _XDEBUG("ConflictProcess (provider[" << provider << "]<" << status << ">");
00214
00215 if (status.staysInstalled()
00216 || status.isToBeInstalledSoft())
00217 {
00218 ResolverInfo_Ptr log_info;
00219
00220 #if PHI
00221 _XDEBUG("Provider is installed - try upgrade");
00222
00223
00224
00225
00226
00227
00228 UpgradeCandidate upgrade_info (provider, context);
00229
00230 Capability maybe_upgrade_cap = factory.parse ( provider->kind(), provider->name(), Rel::ANY, Edition::noedition );
00231
00232
00233 Dep dep( Dep::PROVIDES );
00234
00235 if (!actually_an_obsolete) {
00236 invokeOnEach( pool.byCapabilityIndexBegin( maybe_upgrade_cap.index(), dep ),
00237 pool.byCapabilityIndexEnd( maybe_upgrade_cap.index(), dep ),
00238 resfilter::ByCapMatch( maybe_upgrade_cap ),
00239 functor::functorRef<bool,CapAndItem>(upgrade_info) );
00240
00241 _XDEBUG("found " << upgrade_info.upgrades.size() << " upgrade candidates");
00242 }
00243 #endif
00244
00245 QueueItemUninstall_Ptr uninstall = new QueueItemUninstall (pool, provider, actually_an_obsolete ? QueueItemUninstall::OBSOLETE : QueueItemUninstall::CONFLICT);
00246 uninstall->setCapability (conflict_capability);
00247 if (explicitly_requested)
00248 uninstall->setExplicitlyRequested();
00249
00250 if (actually_an_obsolete) {
00251 uninstall->setDueToObsolete (conflict_issuer);
00252 log_info = new ResolverInfoObsoletes (provider,
00253 conflict_issuer);
00254 } else {
00255 uninstall->setDueToConflict ();
00256 log_info = new ResolverInfoConflictsWith (provider,
00257 conflict_issuer,
00258 conflict_capability);
00259 }
00260
00261 uninstall->addInfo (log_info);
00262
00263 #if PHI
00264 if (upgrade_info.upgrades.empty ()) {
00265 #endif
00266
00267 new_items.push_back (uninstall);
00268
00269 #if PHI
00270 }
00271 else {
00272
00273
00274 _DEBUG("Branching: uninstall vs. upgrade");
00275 QueueItemBranch_Ptr branch = new QueueItemBranch (pool);
00276
00277 branch->addItem (uninstall);
00278
00279 for (PoolItemList::const_iterator iter = upgrade_info.upgrades.begin(); iter != upgrade_info.upgrades.end(); iter++) {
00280 QueueItemInstall_Ptr upgrade = new QueueItemInstall (pool, *iter);
00281 upgrade->setUpgrades (provider);
00282 branch->addItem (upgrade);
00283 }
00284 new_items.push_back (branch);
00285 }
00286 #endif
00287
00288 }
00289 else if (status.isToBeInstalled()) {
00290 ResolverInfoMisc_Ptr misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_CONFLICT_CANT_INSTALL, provider, RESOLVER_INFO_PRIORITY_VERBOSE, provides);
00291 if (conflict_issuer) {
00292 misc_info->setOtherPoolItem (conflict_issuer);
00293 misc_info->setOtherCapability (conflict_capability);
00294 }
00295 context->addError (misc_info);
00296
00297 }
00298 else if (status.wasUninstalled()) {
00299
00300 context->setStatus (provider, ResStatus::impossible);
00301
00302 ResolverInfoMisc_Ptr misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_CONFLICT_UNINSTALLABLE, provider, RESOLVER_INFO_PRIORITY_VERBOSE, provides);
00303
00304 misc_info->setOtherPoolItem (conflict_issuer);
00305 misc_info->setOtherCapability (conflict_capability);
00306
00307 context->addInfo (misc_info);
00308
00309 }
00310 else if (status.isToBeUninstalled()
00311 || status.isImpossible()
00312 || status.isToBeUninstalledDueToObsolete()) {
00313
00314
00315 }
00316 else {
00317 ERR << "Unhandled status in ConflictProcess; item: " << provider << " : " << status << endl;
00318 }
00319
00320 return true;
00321
00322 }
00323
00324 };
00325
00326
00327 bool
00328 QueueItemConflict::process (const QueueItemList & mainQueue, ResolverContext_Ptr context, QueueItemList & new_items)
00329 {
00330 _XDEBUG("QueueItemConflict::process(" << *this << ")");
00331
00332
00333 IgnoreMap ignoreMap = context->getIgnoreConflicts();
00334 for (IgnoreMap::iterator it = ignoreMap.begin();
00335 it != ignoreMap.end(); it++) {
00336 if (it->first == _conflicting_item
00337 && it->second == _capability) {
00338 _XDEBUG("Found ignoring requires " << _capability << " for " << _conflicting_item);
00339 return true;
00340 } else {
00341 _XDEBUG("Ignoring requires " << it->second << " for " << it->first << " does not fit");
00342 }
00343 }
00344
00345 ConflictProcess info (pool(), _conflicting_item, _capability, context, new_items, _actually_an_obsolete, _explicitly_requested);
00346
00347
00348
00349 Dep dep( Dep::PROVIDES );
00350 invokeOnEach( pool().byCapabilityIndexBegin( _capability.index(), dep ),
00351 pool().byCapabilityIndexEnd( _capability.index(), dep ),
00352 resfilter::ByCapMatch( _capability ),
00353 functor::functorRef<bool,CapAndItem>(info) );
00354
00355 return true;
00356 }
00357
00358
00359
00360
00361 QueueItem_Ptr
00362 QueueItemConflict::copy (void) const
00363 {
00364 QueueItemConflict_Ptr new_conflict = new QueueItemConflict (pool(), _capability, _conflicting_item);
00365 new_conflict->QueueItem::copy(this);
00366
00367
00368 new_conflict->_explicitly_requested = _explicitly_requested;
00369
00370 return new_conflict;
00371 }
00372
00373
00374 int
00375 QueueItemConflict::cmp (QueueItem_constPtr item) const
00376 {
00377 int cmp = this->compare (item);
00378 if (cmp != 0)
00379 return cmp;
00380
00381 QueueItemConflict_constPtr conflict = dynamic_pointer_cast<const QueueItemConflict>(item);
00382 if ( _capability != conflict->capability())
00383 cmp = -1;
00384
00385 return cmp;
00386 }
00387
00389 };
00392 };
00395 };