QueueItemInstall.cc

Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
00002 /* QueueItemInstall.cc
00003  *
00004  * Copyright (C) 2000-2002 Ximian, Inc.
00005  * Copyright (C) 2005 SUSE Linux Products GmbH
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License,
00009  * version 2, as published by the Free Software Foundation.
00010  *
00011  * This program is distributed in the hope that it will be useful, but
00012  * WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019  * 02111-1307, USA.
00020  */
00021 
00022 #include "zypp/CapFactory.h"
00023 #include "zypp/CapSet.h"
00024 #include "zypp/Package.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/CapMatchHelper.h"
00034 
00035 #include "zypp/solver/detail/QueueItemInstall.h"
00036 #include "zypp/solver/detail/QueueItemEstablish.h"
00037 #include "zypp/solver/detail/QueueItemUninstall.h"
00038 #include "zypp/solver/detail/QueueItemRequire.h"
00039 #include "zypp/solver/detail/QueueItemConflict.h"
00040 #include "zypp/solver/detail/QueueItem.h"
00041 #include "zypp/solver/detail/ResolverContext.h"
00042 #include "zypp/solver/detail/ResolverInfoConflictsWith.h"
00043 #include "zypp/solver/detail/ResolverInfoMisc.h"
00044 #include "zypp/solver/detail/ResolverInfoNeededBy.h"
00045 #include "zypp/solver/detail/Helper.h"
00046 
00048 namespace zypp
00049 { 
00050 
00051   namespace solver
00052   { 
00053 
00054     namespace detail
00055     { 
00056 
00057 using namespace std;
00058 
00059 IMPL_PTR_TYPE(QueueItemInstall);
00060 
00061 //---------------------------------------------------------------------------
00062 
00063 std::ostream &
00064 QueueItemInstall::dumpOn( std::ostream & os ) const
00065 {
00066     os << "[" << (_soft?"Soft":"") << "Install: ";
00067     os << _item;
00068     if (_upgrades) {
00069         os << ", Upgrades ";
00070         os << _upgrades;
00071     }
00072     if (!_deps_satisfied_by_this_install.empty()) {
00073         os << ", Satisfies [";
00074         for (CapSet::const_iterator iter = _deps_satisfied_by_this_install.begin();
00075             iter != _deps_satisfied_by_this_install.end(); iter++)
00076         {
00077             if (iter != _deps_satisfied_by_this_install.begin()) os << ", ";
00078             os << (*iter);
00079         }
00080         os << "]";
00081     }
00082     if (!_needed_by.empty()) {
00083         os << ", Needed by ";
00084         for (PoolItemList::const_iterator it = _needed_by.begin(); it != _needed_by.end(); ++it) {
00085             if (it != _needed_by.begin()) os << ", ";
00086             os << *it;
00087         }
00088     }
00089     if (_explicitly_requested) os << ", Explicit !";
00090     os << "]";
00091     return os;
00092 }
00093 
00094 //---------------------------------------------------------------------------
00095 
00096 QueueItemInstall::QueueItemInstall (const ResPool & pool, PoolItem_Ref item, bool soft)
00097     : QueueItem (QUEUE_ITEM_TYPE_INSTALL, pool)
00098     , _item (item)
00099     , _soft (soft)
00100     , _channel_priority (0)
00101     , _other_penalty (0)
00102     , _explicitly_requested (false)
00103 {
00104     Resolvable::constPtr res = item.resolvable();
00105 
00106     // Atoms are by default parallel installable (cf #181103)
00107     bool install_in_parallel = isKind<Atom>( res );
00108 
00109     // if its not an atom, check if its a package with 'install-only' set
00110     if (!install_in_parallel) {
00111         Package::constPtr pkg = asKind<Package>( res );
00112         install_in_parallel = (pkg != NULL) && pkg->installOnly();
00113     }
00114 
00115     // if its not parallel installable
00116     //   check if this install upgrades anything
00117 
00118     if (!install_in_parallel) {
00119         _upgrades = Helper::findInstalledItem (pool, item);
00120     }
00121 
00122     _XDEBUG("QueueItemInstall::QueueItemInstall(" << item << (soft?", soft":"") << ") upgrades " << _upgrades);
00123 }
00124  
00125 
00126 QueueItemInstall::~QueueItemInstall()
00127 {
00128 }
00129 
00130 //---------------------------------------------------------------------------
00131 
00132 bool
00133 QueueItemInstall::isSatisfied (ResolverContext_Ptr context) const
00134 {
00135     return context->isPresent (_item);
00136 }
00137 
00138 
00139 //---------------------------------------------------------------------------
00140 
00141 // Handle items which freshen or supplement us -> re-establish them
00142 
00143 // see also FreshenState in Resolver.cc
00144 // see also UninstallEstablishItem in QueueItemUninstall.cc
00145 
00146 typedef map<string, PoolItem_Ref> EstablishMap;
00147 
00148 struct InstallEstablishItem
00149 {
00150     EstablishMap establishmap;
00151 
00152     InstallEstablishItem ()
00153     { }
00154 
00155 
00156     // provider has a freshens on a just to-be-installed item
00157     //   re-establish provider, maybe its incomplete now
00158 
00159     bool operator()( const CapAndItem & cai )
00160     {
00161         _XDEBUG("QueueItemInstall::InstallEstablishItem (" << cai.item << ", " << cai.cap << ")");
00162 
00163         // only consider best architecture, best edition
00164 
00165         PoolItem_Ref item( cai.item );
00166 
00167         EstablishMap::iterator it = establishmap.find( item->name() );
00168 
00169         if (it != establishmap.end()) {                                 // item with same name found
00170             int cmp = it->second->arch().compare( item->arch() );
00171             if (cmp < 0) {                                              // new item has better arch
00172                 it->second = item;
00173             }
00174             else if (cmp == 0) {                                        // new item has equal arch
00175                 if (it->second->edition().compare( item->edition() ) < 0) {
00176                     it->second = item;                          // new item has better edition
00177                 }
00178             }
00179         }
00180         else {
00181             establishmap[item->name()] = item;
00182         }
00183         return true;
00184     }
00185 };
00186 
00187 
00188 
00189 //---------------------------------------------------------------------------
00190 
00191 // Handle items which conflict us -> uninstall them
00192 
00193 struct UninstallConflicting
00194 {
00195     ResolverContext_Ptr _context;
00196     const Capability _provided_cap;
00197     PoolItem _install_item;             // the to-be-installed item issuing the conflict
00198     PoolItem _upgrade_item;             // the installed, to-be-upgraded item (might be empty if its a fresh install)
00199     QueueItemList & _qil;
00200     bool ignored;
00201 
00202     UninstallConflicting( ResolverContext_Ptr ctx, const Capability & provided_cap, PoolItem install_item, PoolItem upgrade_item, QueueItemList & qil )
00203         : _context( ctx )
00204         , _provided_cap( provided_cap )
00205         , _install_item( install_item )
00206         , _upgrade_item( upgrade_item )
00207         , _qil( qil )
00208         , ignored( false )
00209     { }
00210 
00211 
00212     // conflicting_item provides a capability (conflicting_cap), _install_item lists as conflicts.
00213 
00214     bool operator()( const CapAndItem & cai)
00215     {
00216         PoolItem_Ref conflicting_item = cai.item;
00217 
00218         _XDEBUG("UninstallConflicting(" << conflicting_item << ", cap " << cai.cap << ")");
00219 
00220         if (conflicting_item == _install_item) {                                // self conflict ?
00221             WAR << "Ignoring self-conflicts" << endl;
00222             return true;
00223         }
00224         if (conflicting_item == _upgrade_item) {                                // upgrade conflict ?
00225             _XDEBUG("We're upgrading the conflicting item");
00226             return true;
00227         }
00228 
00229         const Capability conflicting_cap = cai.cap;
00230         ResolverInfo_Ptr log_info;
00231         QueueItemUninstall_Ptr uninstall_item;
00232 
00233         IgnoreMap ignoreMap = _context->getIgnoreConflicts();           // ignored conflict ?
00234         // checking for ignoring dependencies
00235         for (IgnoreMap::iterator it = ignoreMap.begin(); it != ignoreMap.end(); it++) {
00236             if (it->first == conflicting_item
00237                 && it->second == conflicting_cap)
00238             {
00239                 _XDEBUG("Found ignoring conflicts " << conflicting_cap << " for " << conflicting_item);
00240                 ignored = true;
00241                 return false;           // stop iteration
00242             } else {
00243                 _XDEBUG("Ignoring conflict " << it->second << " for " <<  it->first << " does not fit");            
00244             }
00245         }
00246 
00247         /* Check to see if we conflict with ourself and don't create
00248          * an uninstall item for it if we do.  This is Debian's way of
00249          * saying that one and only one item with this provide may
00250          * exist on the system at a time.
00251          */
00252 
00253         if (compareByNVR (conflicting_item.resolvable(), _install_item.resolvable()) == 0) {
00254                 return true;
00255         }
00256 
00257 #warning Make behaviour configurable
00258         // If the package is installed or is set to be installed by the user,
00259         // let the user decide deleting conflicting package. This is only an info.
00260         // Try at first updating packages.
00261         //
00262         ResStatus confl_status = _context->getStatus( conflicting_item );
00263         if (confl_status.isToBeInstalled()                      // scheduled for installation
00264             || confl_status.staysInstalled())                   // not scheduled at all but installed
00265         {
00266             ResolverInfoMisc_Ptr misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_CONFLICT_CANT_INSTALL,
00267                                                                                _install_item, RESOLVER_INFO_PRIORITY_VERBOSE, _provided_cap);
00268             misc_info->setOtherPoolItem (conflicting_item);
00269             misc_info->setOtherCapability (conflicting_cap);
00270             _context->addInfo (misc_info);
00271         }
00272 
00273         _XDEBUG("because: '" << conflicting_item << "'conflicts " << conflicting_cap);
00274 
00275         QueueItemUninstall_Ptr uninstall_qitem = new QueueItemUninstall (_context->pool(), conflicting_item, QueueItemUninstall::CONFLICT);
00276         uninstall_qitem->setDueToConflict ();
00277         log_info = new ResolverInfoConflictsWith (conflicting_item, _install_item,
00278                                                   conflicting_cap);
00279         uninstall_qitem->addInfo (log_info);
00280         _qil.push_front (uninstall_qitem);
00281 
00282         return true;
00283     }
00284 };
00285 
00286 //---------------------------------------------------------------------------------------
00287 
00288 bool
00289 QueueItemInstall::process (ResolverContext_Ptr context, QueueItemList & qil)
00290 {
00291     ResStatus status = context->getStatus(_item);
00292 
00293     _XDEBUG( "QueueItemInstall::process(" << *this << "):" << status);
00294 
00295     /* If we are trying to upgrade item A with item B and they both have the
00296         same version number, do nothing.  This shouldn't happen in general with
00297         zypp, but can come up with the installer & autopull. */
00298 
00299     if (_upgrades
00300         && compareByNVRA(_item.resolvable(), _upgrades.resolvable()) == 0)
00301     {
00302         if (_item->kind() == ResTraits<Package>::kind) {
00303             ResolverInfo_Ptr info;
00304             _DEBUG("install of " << _item << " upgrades itself, skipping");
00305 
00306             info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_SKIPPING, _item, RESOLVER_INFO_PRIORITY_VERBOSE);
00307             context->addInfo (info);
00308             goto finished;
00309         }
00310         else {
00311             _DEBUG("re-install " << _item);
00312         }
00313     }
00314 
00315     // check if this install is still needed
00316     //   (maybe other resolver processing made this install obsolete
00317 
00318     if (!_needed_by.empty()) {
00319         bool still_needed = false;
00320 
00321         _XDEBUG( "still needed ");
00322 
00323         for (PoolItemList::const_iterator iter = _needed_by.begin(); iter != _needed_by.end() && !still_needed; ++iter) {
00324             ResStatus status = iter->status();
00325             _XDEBUG("by: [status: " << status << "] " << *iter);
00326             if (! status.isToBeUninstalled()
00327                 && ! status.isImpossible())
00328             {
00329                 still_needed = true;
00330             }
00331         }
00332 
00333         if (! still_needed)
00334             goto finished;
00335     }
00336 
00337     /* If we are in verify mode and this install is about to fail, don't let it happen...
00338            instead, we try to back out of the install by removing whatever it was that
00339            needed this. */
00340 
00341     if (context->verifying()
00342         && (status.isToBeUninstalled() || status.isImpossible())
00343         && !_needed_by.empty()) {
00344 
00345         QueueItemUninstall_Ptr uninstall_item;
00346 
00347         for (PoolItemList::const_iterator iter = _needed_by.begin(); iter != _needed_by.end(); iter++) {
00348             uninstall_item = new QueueItemUninstall (pool(), *iter, QueueItemUninstall::BACKOUT);
00349             qil.push_front (uninstall_item);
00350         }
00351 
00352         goto finished;
00353     }
00354 
00355     // If this install is due to a needed, convert it to a normal install
00356 
00357     if (status.isNeeded()) {
00358         context->setStatus (_item, _soft ? ResStatus::toBeInstalledSoft :  ResStatus::toBeInstalled);
00359     }
00360 
00361 
00362     // if this install upgrades an installed resolvable, explicitly uninstall this one
00363     //   in order to ensure that all dependencies are still met after the upgrade
00364 
00365     if (!_upgrades) {
00366 
00367         _XDEBUG("trying simple install of " <<  _item);
00368         if (!context->install (_item, context->verifying() || _soft, _other_penalty))
00369             goto finished;
00370 
00371     }
00372     else {
00373 
00374         QueueItemUninstall_Ptr uninstall_item;
00375 
00376         _XDEBUG("trying upgrade install of " << _item);
00377 
00378         if (!context->upgrade (_item, _upgrades, context->verifying() || _soft, _other_penalty)) {
00379             // invalid solution
00380             ResolverInfo_Ptr info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_INVALID_SOLUTION, PoolItem_Ref(), RESOLVER_INFO_PRIORITY_VERBOSE);
00381             context->addError (info);
00382             goto finished;
00383         }
00384 
00385         // the upgrade will uninstall the installed one, take care of this
00386 
00387         uninstall_item = new QueueItemUninstall (pool(), _upgrades, QueueItemUninstall::UPGRADE );
00388         uninstall_item->setUpgradedTo (_item);
00389 
00390         if (_explicitly_requested)
00391             uninstall_item->setExplicitlyRequested ();
00392 
00393         qil.push_front (uninstall_item);
00394 
00395     }
00396 
00397     /* Log which item need this install */
00398 
00399     if (!_needed_by.empty()) {
00400 
00401         ResolverInfoNeededBy_Ptr info;
00402 
00403         info = new ResolverInfoNeededBy (_item);
00404         info->addRelatedPoolItemList (_needed_by);
00405         context->addInfo (info);
00406     }
00407 
00408     // we're done if this isn't currently uninstalled or incomplete
00409 
00410     if (! (status.staysUninstalled()
00411            || status.isToBeUninstalledDueToUnlink()
00412            || status.isIncomplete()
00413            || status.isSatisfied()))
00414     {
00415         _XDEBUG("status " << status << " -> finished");
00416         goto finished;
00417     }
00418 
00419     _XDEBUG("status " << status << " -> NOT finished");
00420     {   // just a block for local initializers, the goto above makes this necessary
00421 
00422         ResolverInfoMisc_Ptr misc_info;
00423 
00424         if (_upgrades) {
00425 
00426             misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_UPDATING, _item, RESOLVER_INFO_PRIORITY_VERBOSE);
00427             misc_info->setOtherPoolItem (_upgrades);
00428 
00429         } else {
00430 
00431             misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_INSTALLING, _item, RESOLVER_INFO_PRIORITY_VERBOSE);
00432 
00433         }
00434 
00435         context->addInfo (misc_info);
00436         logInfo (context);
00437 
00438         /* Construct require items for each of the item's requires that is still unsatisfied. */
00439 
00440         CapSet caps;
00441 
00442         caps = _item->dep (Dep::REQUIRES);
00443 
00444         for (CapSet::const_iterator iter = caps.begin(); iter != caps.end(); iter++) {
00445 
00446             const Capability cap = *iter;
00447             _XDEBUG("this requires " << cap);
00448             bool fulfilled = false;
00449             
00450             if (_item)
00451             {
00452                 fulfilled = context->requirementIsInstalledOrUnneeded (_item->kind(), cap);
00453             } else {
00454                 fulfilled = context->requirementIsMet (cap);
00455             }
00456 
00457             if (!fulfilled) {
00458                 _XDEBUG("this requirement is still unfulfilled");
00459                 QueueItemRequire_Ptr req_item = new QueueItemRequire (pool(), cap );
00460                 req_item->addPoolItem (_item);
00461                 qil.push_front (req_item);
00462             }           
00463         }
00464 
00465         caps = _item->dep (Dep::RECOMMENDS);
00466 
00467         for (CapSet::const_iterator iter = caps.begin(); iter != caps.end(); iter++) {
00468 
00469             const Capability cap = *iter;
00470             _XDEBUG("this recommends " << cap);
00471 
00472             if (!context->requirementIsMet (cap)) {
00473                 _XDEBUG("this recommends is still unfulfilled");
00474                 QueueItemRequire_Ptr req_item = new QueueItemRequire (pool(), cap, true);       // this is a soft requires
00475                 req_item->addPoolItem (_item);
00476                 qil.push_front (req_item);
00477             }
00478 
00479         }
00480 
00481         /* Construct conflict items for each of the item's conflicts. */
00482 
00483         caps = _item->dep (Dep::CONFLICTS);
00484         for (CapSet::const_iterator iter = caps.begin(); iter != caps.end(); iter++) {
00485             const Capability cap = *iter;
00486             _XDEBUG("this conflicts with '" << cap << "'");
00487             QueueItemConflict_Ptr conflict_item = new QueueItemConflict (pool(), cap, _item );
00488             // Push the QueueItem at the END of the list in order to favourite conflicts caused
00489             // by obsolating this item.
00490             qil.push_back (conflict_item);
00491         }
00492 
00493         /* Construct conflict items for each of the item's obsoletes. */
00494 
00495         caps = _item->dep (Dep::OBSOLETES);
00496         IgnoreMap ignoreMap = context->getIgnoreObsoletes();
00497         
00498         for (CapSet::const_iterator iter = caps.begin(); iter != caps.end(); iter++) {
00499             const Capability cap = *iter;
00500             bool found = false;
00501             for (IgnoreMap::iterator it = ignoreMap.begin();
00502                  it != ignoreMap.end(); it++) {
00503                 if (it->first == _item
00504                     && it->second == cap) {
00505                     _XDEBUG("Found ignoring obsoletes " << cap << " for " << _item);
00506                     found = true;
00507                     break;
00508                 }
00509             }
00510             if (!found) {           
00511                 _XDEBUG("this obsoletes " <<  cap);
00512                 QueueItemConflict_Ptr conflict_item = new QueueItemConflict (pool(), cap, _item );
00513                 conflict_item->setActuallyAnObsolete();
00514                 // Push the QueueItem at the BEGIN of the list in order to favourite this confict
00515                 // comparing to "normal" conflicts, cause this item will be deleted. So other
00516                 // conflicts will not be regarded in the future.
00517                 qil.push_front (conflict_item);
00518             }
00519         }
00520 
00521         // Go over each provides of the to-be-uninstalled item and
00522         // - re-establish any freshens
00523         // - re-establish any supplements
00524         // - find items that conflict with us and try to uninstall it if it is useful
00525 
00526         InstallEstablishItem establish;
00527 
00528         caps = _item->dep (Dep::PROVIDES);
00529         bool ignored = false;
00530 
00531         for (CapSet::const_iterator iter = caps.begin(); iter != caps.end(); iter++) {
00532             const Capability cap = *iter;
00533 
00534             /* Construct establish items for each of those which
00535                 freshen or supplement and provides of this resolvable. */
00536 
00537             _XDEBUG("Re-establish all freshens on " << cap);
00538             // pool ()->foreachFresheningResItem (cap, establish_freshens_cb, &info);
00539 
00540             Dep dep( Dep::FRESHENS);
00541             invokeOnEach( pool().byCapabilityIndexBegin( cap.index(), dep ), // begin()
00542                           pool().byCapabilityIndexEnd( cap.index(), dep ),   // end()
00543                           resfilter::ByCapMatch( cap ),
00544                           functor::functorRef<bool,CapAndItem>( establish ) );
00545 
00546             dep = Dep::SUPPLEMENTS;
00547             invokeOnEach( pool().byCapabilityIndexBegin( cap.index(), dep ), // begin()
00548                           pool().byCapabilityIndexEnd( cap.index(), dep ),   // end()
00549                           resfilter::ByCapMatch( cap ),
00550                           functor::functorRef<bool,CapAndItem>( establish ) );
00551 
00552             if (!ignored) {
00553                 // Search items that conflict with us and try to uninstall it if it is useful
00554 
00555                 UninstallConflicting info( context, cap, _item, _upgrades, qil );
00556 
00557                 Dep dep( Dep::CONFLICTS );
00558                 invokeOnEach( pool().byCapabilityIndexBegin( cap.index(), dep ),
00559                               pool().byCapabilityIndexEnd( cap.index(), dep ),
00560                               resfilter::ByCapMatch( cap ),
00561                               functor::functorRef<bool,CapAndItem>( info ) );
00562 
00563                 ignored = info.ignored;         // user choose to ignore these conflitcs
00564             }
00565 
00566         } // iterate over all provides
00567 
00568         // schedule all collected items for establish
00569 
00570         for (EstablishMap::iterator firstIt = establish.establishmap.begin(); firstIt != establish.establishmap.end(); ++firstIt) {
00571             bool conflictFound = false;
00572             CapSet provides = firstIt->second.resolvable()->deps()[Dep::PROVIDES];
00573             // It is useless to establish items which are conflicting with eachother. So they will
00574             // be filtered out. bug 243595
00575             for (EstablishMap::iterator secondIt = firstIt; secondIt != establish.establishmap.end() && !conflictFound; ++secondIt) {
00576                 CapSet conflicts = secondIt->second.resolvable()->deps()[Dep::CONFLICTS];
00577                 if (hasMatches (provides,conflicts)) {
00578                     conflictFound = true;
00579                     _XDEBUG("Do not establish " << firstIt->second << " cause it is conflicting with " << secondIt->second );
00580                 }
00581             }
00582 
00583             if (!conflictFound) {
00584                 QueueItemEstablish_Ptr establish_item = new QueueItemEstablish (pool(), firstIt->second, true);
00585                 qil.push_front( establish_item );
00586             }
00587         }
00588 
00589     } // end of goto-over-definitions-to-finished block
00590 
00591  finished:
00592 
00593     return true;
00594 }
00595 
00596 
00597 QueueItem_Ptr
00598 QueueItemInstall::copy (void) const
00599 {
00600     QueueItemInstall_Ptr new_install = new QueueItemInstall (pool(), _item);
00601     new_install->QueueItem::copy(this);
00602 
00603     new_install->_upgrades = _upgrades;
00604     new_install->_deps_satisfied_by_this_install = CapSet(_deps_satisfied_by_this_install.begin(), _deps_satisfied_by_this_install.end());
00605     new_install->_needed_by = PoolItemList (_needed_by.begin(), _needed_by.end());
00606     new_install->_channel_priority = _channel_priority;
00607     new_install->_other_penalty = _other_penalty;
00608     new_install->_explicitly_requested = _explicitly_requested;
00609 
00610     return new_install;
00611 }
00612 
00613 
00614 int
00615 QueueItemInstall::cmp (QueueItem_constPtr item) const
00616 {
00617     int cmp = this->compare (item);
00618     if (cmp != 0)
00619         return cmp;
00620     QueueItemInstall_constPtr install = dynamic_pointer_cast<const QueueItemInstall>(item);
00621     return compareByNVRA (_item.resolvable(), install->_item.resolvable());
00622 }
00623 
00624 //---------------------------------------------------------------------------
00625 
00626 void
00627 QueueItemInstall::addDependency (const Capability & dep)
00628 {
00629     _deps_satisfied_by_this_install.insert (dep);
00630 }
00631 
00632 
00633 void
00634 QueueItemInstall::addNeededBy (PoolItem_Ref item)
00635 {
00636     _needed_by.push_front (item);
00637 }
00638 
00640     };// namespace detail
00643   };// namespace solver
00646 };// namespace zypp
00648 

Generated on Fri Jul 4 16:57:58 2008 for zypp by  doxygen 1.5.0