00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "zypp/CapSet.h"
00023 #include "zypp/base/Logger.h"
00024 #include "zypp/base/String.h"
00025 #include "zypp/base/Gettext.h"
00026
00027 #include "zypp/base/Algorithm.h"
00028 #include "zypp/ResPool.h"
00029 #include "zypp/ResFilters.h"
00030 #include "zypp/CapFilters.h"
00031
00032 #include "zypp/solver/detail/QueueItemUninstall.h"
00033 #include "zypp/solver/detail/QueueItemEstablish.h"
00034 #include "zypp/solver/detail/QueueItemRequire.h"
00035 #include "zypp/solver/detail/QueueItem.h"
00036 #include "zypp/solver/detail/ResolverContext.h"
00037 #include "zypp/solver/detail/ResolverInfoMisc.h"
00038 #include "zypp/solver/detail/ResolverInfoMissingReq.h"
00039
00041 namespace zypp
00042 {
00043
00044 namespace solver
00045 {
00046
00047 namespace detail
00048 {
00049
00050 using namespace std;
00051
00052 IMPL_PTR_TYPE(QueueItemUninstall);
00053
00054
00055
00056 std::ostream &
00057 QueueItemUninstall::dumpOn( std::ostream & os ) const
00058 {
00059 os << "[" << (_soft?"Soft":"") << "Uninstall: ";
00060
00061 os << _item;
00062 os << " (";
00063 switch (_reason) {
00064 case QueueItemUninstall::CONFLICT: os << "conflicts"; break;
00065 case QueueItemUninstall::OBSOLETE: os << "obsoletes"; break;
00066 case QueueItemUninstall::UNSATISFIED: os << "unsatisfied dependency"; break;
00067 case QueueItemUninstall::BACKOUT: os << "uninstallable"; break;
00068 case QueueItemUninstall::UPGRADE: os << "upgrade"; break;
00069 case QueueItemUninstall::DUPLICATE: os << "duplicate"; break;
00070 case QueueItemUninstall::EXPLICIT: os << "explicit"; break;
00071 }
00072 os << ")";
00073 if (_cap_leading_to_uninstall != Capability::noCap) {
00074 os << ", Triggered By ";
00075 os << _cap_leading_to_uninstall;
00076 }
00077 if (_upgraded_to) {
00078 os << ", Upgraded To ";
00079 os << _upgraded_to;
00080 }
00081 if (_explicitly_requested) os << ", Explicit";
00082 if (_remove_only) os << ", Remove Only";
00083 if (_due_to_conflict) os << ", Due To Conflict";
00084 if (_due_to_obsolete)
00085 os << ", Due To Obsolete:" << _obsoletes_item;
00086 if (_unlink) os << ", Unlink";
00087 os << "]";
00088 return os;
00089 }
00090
00091
00092
00093 QueueItemUninstall::QueueItemUninstall (const ResPool & pool, PoolItem_Ref item, UninstallReason reason, bool soft)
00094 : QueueItem (QUEUE_ITEM_TYPE_UNINSTALL, pool)
00095 , _item (item)
00096 , _reason (reason)
00097 , _soft (soft)
00098 , _cap_leading_to_uninstall (Capability())
00099 , _upgraded_to (NULL)
00100 , _explicitly_requested (false)
00101 , _remove_only (false)
00102 , _due_to_conflict (false)
00103 , _due_to_obsolete (false)
00104 , _unlink (false)
00105 , _obsoletes_item (NULL)
00106 {
00107 _XDEBUG("QueueItemUninstall::QueueItemUninstall(" << item << ")");
00108 }
00109
00110
00111 QueueItemUninstall::~QueueItemUninstall()
00112 {
00113 }
00114
00115
00116
00117 void
00118 QueueItemUninstall::setUnlink ()
00119 {
00120 _unlink = true;
00121
00122
00123
00124 setPriority (0);
00125
00126 return;
00127 }
00128
00129
00130
00131 struct UnlinkCheck
00132 {
00133 ResolverContext_Ptr context;
00134 bool cancel_unlink;
00135
00136
00137
00138
00139
00140
00141
00142
00143 bool operator()( const CapAndItem & cai )
00144 {
00145 if (cancel_unlink)
00146 return true;
00147
00148 if (! context->isPresent (cai.item))
00149 return true;
00150
00151 if (context->requirementIsMet (cai.cap))
00152 return true;
00153
00154 cancel_unlink = true;
00155
00156 return true;
00157 }
00158 };
00159
00160
00161
00162
00163 struct UninstallProcess
00164 {
00165 ResPool pool;
00166 ResolverContext_Ptr context;
00167 PoolItem_Ref uninstalled_item;
00168 PoolItem_Ref upgraded_item;
00169 QueueItemList & qil;
00170 bool remove_only;
00171 bool soft;
00172
00173 UninstallProcess (const ResPool & p, ResolverContext_Ptr ct, PoolItem_Ref u1, PoolItem_Ref u2, QueueItemList & l, bool ro, bool s)
00174 : pool (p)
00175 , context (ct)
00176 , uninstalled_item (u1)
00177 , upgraded_item (u2)
00178 , qil (l)
00179 , remove_only (ro)
00180 , soft (s)
00181 { }
00182
00183
00184
00185 bool operator()( const CapAndItem & cai )
00186 {
00187 PoolItem requirer( cai.item );
00188 if (! context->isPresent (requirer))
00189 return true;
00190
00191 if (context->requirementIsMet( cai.cap, false ))
00192 return true;
00193
00194 if (context->getStatus(requirer).isSatisfied()) {
00195 #warning If an uninstall incompletes a satisfied, the uninstall should be cancelled
00196 QueueItemEstablish_Ptr establish_item = new QueueItemEstablish (pool, requirer, soft);
00197 qil.push_back (establish_item);
00198 return true;
00199 }
00200 QueueItemRequire_Ptr require_item = new QueueItemRequire( pool, cai.cap );
00201 require_item->addPoolItem (requirer);
00202 if (remove_only) {
00203 require_item->setRemoveOnly ();
00204 }
00205 require_item->setUpgradedPoolItem (upgraded_item);
00206 require_item->setLostPoolItem (uninstalled_item);
00207
00208 qil.push_front (require_item);
00209
00210 return true;
00211 }
00212 };
00213
00214
00215
00216
00217 struct UninstallEstablishItem
00218 {
00219 const ResPool & pool;
00220 QueueItemList & qil;
00221 bool soft;
00222
00223 UninstallEstablishItem (const ResPool & p, QueueItemList &l, bool s)
00224 : pool(p)
00225 , qil(l)
00226 , soft(s)
00227 { }
00228
00229
00230
00231
00232
00233 bool operator()( const CapAndItem & cai )
00234 {
00235 _XDEBUG("QueueItemUninstall::UninstallEstablishItem (" << cai.item << ", " << cai.cap << ")");
00236
00237
00238
00239 if (cai.item.status().staysInstalled()) {
00240 QueueItemEstablish_Ptr establish_item = new QueueItemEstablish (pool, cai.item, soft);
00241 qil.push_back (establish_item);
00242 }
00243 return true;
00244 }
00245 };
00246
00247
00248
00249 struct ProvidesItem
00250 {
00251 const ResPool & pool;
00252 QueueItemList & qil;
00253 bool soft;
00254
00255 ProvidesItem (const ResPool & p, QueueItemList &l, bool s)
00256 : pool(p)
00257 , qil(l)
00258 , soft(s)
00259 { }
00260
00261
00262 bool operator()( const CapAndItem & cai )
00263 {
00264 _XDEBUG("remove soft item (" << cai.item << ", " << cai.cap << ")");
00265 PoolItem_Ref item( cai.item );
00266 if (!item.status().transacts()) {
00267 QueueItemUninstall_Ptr uninstall_item = new QueueItemUninstall (pool, item, QueueItemUninstall::EXPLICIT, soft);
00268 uninstall_item->setUnlink ();
00269 qil.push_back (uninstall_item);
00270 }
00271 return true;
00272 }
00273 };
00274
00275
00276
00277
00278
00279
00280 bool
00281 QueueItemUninstall::process (ResolverContext_Ptr context, QueueItemList & qil)
00282 {
00283 ResStatus status = context->getStatus(_item);
00284
00285 _XDEBUG("QueueItemUninstall::process(<" << status << ">" << _item << ( _unlink ? "[unlink]" : ""));
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297 if (_unlink) {
00298
00299 if (status.isToBeInstalled()) {
00300 ResolverInfo_Ptr misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_UNINSTALL_TO_BE_INSTALLED, _item, RESOLVER_INFO_PRIORITY_VERBOSE);
00301 context->addInfo (misc_info);
00302 goto finished;
00303
00304 }
00305 else if (status.staysInstalled()) {
00306
00307 UnlinkCheck info;
00308
00309
00310
00311
00312 context->setStatus(_item, ResStatus::toBeUninstalled);
00313
00314 info.context = context;
00315 info.cancel_unlink = false;
00316
00317
00318
00319
00320 CapSet provides = _item->dep(Dep::PROVIDES);
00321 for (CapSet::const_iterator iter = provides.begin(); iter != provides.end() && ! info.cancel_unlink; iter++) {
00322
00323
00324
00325 Dep dep( Dep::REQUIRES);
00326
00327 invokeOnEach( pool().byCapabilityIndexBegin( iter->index(), dep ),
00328 pool().byCapabilityIndexEnd( iter->index(), dep ),
00329 resfilter::ByCapMatch( *iter ),
00330 functor::functorRef<bool,CapAndItem>(info) );
00331
00332 }
00333
00334
00335
00336 context->setStatus(_item, status);
00337
00338 if (info.cancel_unlink) {
00339 ResolverInfo_Ptr misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_UNINSTALL_INSTALLED, _item, RESOLVER_INFO_PRIORITY_VERBOSE);
00340 context->addInfo (misc_info);
00341 goto finished;
00342 }
00343 }
00344
00345 }
00346
00347 this->logInfo (context);
00348
00349 context->uninstall (_item, _upgraded_to , _due_to_obsolete, _unlink);
00350 if (status.staysInstalled()) {
00351 if (! _explicitly_requested
00352 && _item.status().isLocked()) {
00353
00354 ResolverInfoMisc_Ptr misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_UNINSTALL_LOCKED,
00355 _item, RESOLVER_INFO_PRIORITY_VERBOSE,
00356 _cap_leading_to_uninstall);
00357 if (_due_to_obsolete)
00358 {
00359 misc_info->setOtherPoolItem (_obsoletes_item);
00360 misc_info->addTrigger (ResolverInfoMisc::OBSOLETE);
00361 } else if (_due_to_conflict)
00362 {
00363 misc_info->addTrigger (ResolverInfoMisc::CONFLICT);
00364 }
00365
00366 context->addError (misc_info);
00367 goto finished;
00368 }
00369
00370 if (_cap_leading_to_uninstall != Capability()
00371 && !_due_to_conflict
00372 && !_due_to_obsolete)
00373 {
00374 ResolverInfo_Ptr info = new ResolverInfoMissingReq (_item, _cap_leading_to_uninstall);
00375 context->addInfo (info);
00376 }
00377
00378
00379
00380
00381 CapSet provides = _item->dep(Dep::PROVIDES);
00382
00383 for (CapSet::const_iterator iter = provides.begin(); iter != provides.end(); iter++) {
00384 UninstallProcess info ( pool(), context, _item, _upgraded_to, qil, _remove_only, _soft);
00385
00386
00387 Dep dep( Dep::REQUIRES );
00388
00389 invokeOnEach( pool().byCapabilityIndexBegin( iter->index(), dep ),
00390 pool().byCapabilityIndexEnd( iter->index(), dep ),
00391 resfilter::ByCapMatch( *iter ),
00392 functor::functorRef<bool,CapAndItem>(info) );
00393
00394
00395
00396 UninstallEstablishItem establish( pool(), qil, _soft );
00397
00398 dep = Dep::SUPPLEMENTS;
00399 invokeOnEach( pool().byCapabilityIndexBegin( iter->index(), dep ),
00400 pool().byCapabilityIndexEnd( iter->index(), dep ),
00401 resfilter::ByCapMatch( *iter ),
00402 functor::functorRef<bool,CapAndItem>( establish ) );
00403
00404 dep = Dep::FRESHENS;
00405 invokeOnEach( pool().byCapabilityIndexBegin( iter->index(), dep ),
00406 pool().byCapabilityIndexEnd( iter->index(), dep ),
00407 resfilter::ByCapMatch( *iter ),
00408 functor::functorRef<bool,CapAndItem>( establish ) );
00409 }
00410
00411
00412
00413
00414 if (_upgraded_to
00415 || _item->kind() == ResTraits<Package>::kind)
00416 {
00417 goto finished;
00418 }
00419
00420 CapSet recomments = _item->dep (Dep::RECOMMENDS);
00421 for (CapSet::const_iterator iter = recomments.begin(); iter != recomments.end(); iter++) {
00422 const Capability cap = *iter;
00423 _XDEBUG("this recommends " << cap);
00424 ProvidesItem provides( pool(), qil, true );
00425
00426 Dep dep(Dep::PROVIDES);
00427 invokeOnEach( pool().byCapabilityIndexBegin( iter->index(), dep ),
00428 pool().byCapabilityIndexEnd( iter->index(), dep ),
00429 functor::chain( resfilter::ByCaIInstalled(), resfilter::ByCapMatch( *iter ) ),
00430 functor::functorRef<bool,CapAndItem>( provides ) );
00431 }
00432
00433 }
00434
00435 finished:
00436 return true;
00437 }
00438
00439
00440
00441 int
00442 QueueItemUninstall::cmp (QueueItem_constPtr item) const
00443 {
00444 int cmp = this->compare (item);
00445 if (cmp != 0)
00446 return cmp;
00447
00448 QueueItemUninstall_constPtr uninstall = dynamic_pointer_cast<const QueueItemUninstall>(item);
00449 return compareByNVRA (_item.resolvable(), uninstall->_item.resolvable());
00450 }
00451
00452
00453 QueueItem_Ptr
00454 QueueItemUninstall::copy (void) const
00455 {
00456 QueueItemUninstall_Ptr new_uninstall = new QueueItemUninstall (pool(), _item, _reason);
00457 new_uninstall->QueueItem::copy(this);
00458
00459
00460 new_uninstall->_item = _item;
00461 new_uninstall->_cap_leading_to_uninstall = _cap_leading_to_uninstall;
00462 new_uninstall->_upgraded_to = _upgraded_to;
00463
00464 new_uninstall->_explicitly_requested = _explicitly_requested;
00465 new_uninstall->_remove_only = _remove_only;
00466 new_uninstall->_due_to_conflict = _due_to_conflict;
00467 new_uninstall->_due_to_obsolete = _due_to_obsolete;
00468 new_uninstall->_obsoletes_item = _obsoletes_item;
00469 new_uninstall->_unlink = _unlink;
00470
00471 return new_uninstall;
00472 }
00473
00475 };
00478 };
00481 };
00483