SATResolver.cc

Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
00002 /* SATResolver.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 the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019  * 02111-1307, USA.
00020  */
00021 extern "C"
00022 {
00023 #include <satsolver/repo_solv.h>
00024 #include <satsolver/poolarch.h>
00025 #include <satsolver/evr.h>
00026 #include <satsolver/poolvendor.h>
00027 #include <satsolver/policy.h>
00028 #include <satsolver/bitmap.h>
00029 #include <satsolver/queue.h>
00030 }
00031 
00032 #include "zypp/solver/detail/Helper.h"
00033 #include "zypp/base/String.h"
00034 #include "zypp/Product.h"
00035 #include "zypp/Capability.h"
00036 #include "zypp/ResStatus.h"
00037 #include "zypp/VendorAttr.h"
00038 #include "zypp/base/LogTools.h"
00039 #include "zypp/base/String.h"
00040 #include "zypp/base/Gettext.h"
00041 #include "zypp/base/Algorithm.h"
00042 #include "zypp/ResPool.h"
00043 #include "zypp/ResFilters.h"
00044 #include "zypp/ZConfig.h"
00045 #include "zypp/sat/Pool.h"
00046 #include "zypp/sat/WhatProvides.h"
00047 #include "zypp/sat/WhatObsoletes.h"
00048 #include "zypp/solver/detail/SATResolver.h"
00049 #include "zypp/solver/detail/ProblemSolutionCombi.h"
00050 #include "zypp/solver/detail/ProblemSolutionIgnore.h"
00051 #include "zypp/solver/detail/SolverQueueItemInstall.h"
00052 #include "zypp/solver/detail/SolverQueueItemDelete.h"
00053 #include "zypp/solver/detail/SystemCheck.h"
00054 
00056 namespace zypp
00057 { 
00058 
00059   namespace solver
00060   { 
00061 
00062     namespace detail
00063     { 
00064 
00065 using namespace std;
00066 
00067 IMPL_PTR_TYPE(SATResolver);
00068 
00069 #define MAYBE_CLEANDEPS (cleandepsOnRemove()?SOLVER_CLEANDEPS:0)
00070 
00071 //---------------------------------------------------------------------------
00072 // Callbacks for SAT policies
00073 //---------------------------------------------------------------------------
00074 
00075 int vendorCheck( Pool *pool, Solvable *solvable1, Solvable *solvable2 )
00076 {
00077   return VendorAttr::instance().equivalent( IdString(solvable1->vendor),
00078                                             IdString(solvable2->vendor) ) ? 0 : 1;
00079 }
00080 
00081 
00082 inline std::string itemToString( const PoolItem & item )
00083 {
00084   if ( !item )
00085     return std::string();
00086 
00087   sat::Solvable slv( item.satSolvable() );
00088   std::string ret( slv.asString() ); // n-v-r.a
00089   if ( ! slv.isSystem() )
00090   {
00091     ret += "[";
00092     ret += slv.repository().alias();
00093     ret += "]";
00094   }
00095   return ret;
00096 }
00097 
00098 inline PoolItem getPoolItem( Id id_r )
00099 {
00100   PoolItem ret( (sat::Solvable( id_r )) );
00101   if ( !ret && id_r )
00102     INT << "id " << id_r << " not found in ZYPP pool." << endl;
00103   return ret;
00104 }
00105 
00106 //---------------------------------------------------------------------------
00107 
00108 std::ostream &
00109 SATResolver::dumpOn( std::ostream & os ) const
00110 {
00111     os << "<resolver>" << endl;
00112     if (_solv) {
00113         os << "  fixsystem = " << _solv->fixsystem << endl;
00114         os << "  allowdowngrade = " << _solv->allowdowngrade << endl;
00115         os << "  allowarchchange = " << _solv->allowarchchange << endl;
00116         os << "  allowvendorchange = " <<  _solv->allowvendorchange << endl;
00117         os << "  allowuninstall = " << _solv->allowuninstall << endl;
00118         os << "  updatesystem = " << _solv->updatesystem << endl;
00119         os << "  noupdateprovide = " << _solv->noupdateprovide << endl;
00120         os << "  dosplitprovides = " << _solv->dosplitprovides << endl;
00121         os << "  onlyRequires = " << _solv->dontinstallrecommended << endl;
00122         os << "  ignorealreadyrecommended = " << _solv->ignorealreadyrecommended << endl;
00123         os << "  distupgrade = " << _distupgrade << endl;
00124         os << "  distupgrade_removeunsupported = " << _distupgrade_removeunsupported << endl;
00125         os << "  solveSrcPackages = " << _solveSrcPackages << endl;
00126         os << "  cleandepsOnRemove = " << _cleandepsOnRemove << endl;
00127     } else {
00128         os << "<NULL>";
00129     }
00130     return os << "<resolver/>" << endl;
00131 }
00132 
00133 //---------------------------------------------------------------------------
00134 
00135 SATResolver::SATResolver (const ResPool & pool, Pool *SATPool)
00136     : _pool (pool)
00137     , _SATPool (SATPool)
00138     , _solv(NULL)
00139     , _fixsystem(false)
00140     , _allowdowngrade(false)
00141     , _allowarchchange(false)
00142     , _allowvendorchange(ZConfig::instance().solver_allowVendorChange())
00143     , _allowuninstall(false)
00144     , _updatesystem(false)
00145     , _noupdateprovide(false)
00146     , _dosplitprovides(false)
00147     , _onlyRequires(ZConfig::instance().solver_onlyRequires())
00148     , _ignorealreadyrecommended(false)
00149     , _distupgrade(false)
00150     , _distupgrade_removeunsupported(false)
00151     , _solveSrcPackages(false)
00152     , _cleandepsOnRemove(ZConfig::instance().solver_cleandepsOnRemove())
00153 {
00154 }
00155 
00156 
00157 SATResolver::~SATResolver()
00158 {
00159 }
00160 
00161 //---------------------------------------------------------------------------
00162 
00163 
00164 ResPool
00165 SATResolver::pool (void) const
00166 {
00167     return _pool;
00168 }
00169 
00170 
00171 void
00172 SATResolver::resetItemTransaction (PoolItem item)
00173 {
00174     bool found = false;
00175     for (PoolItemList::const_iterator iter = _items_to_remove.begin();
00176          iter != _items_to_remove.end(); ++iter) {
00177         if (*iter == item) {
00178             _items_to_remove.remove(*iter);
00179             found = true;
00180             break;
00181         }
00182     }
00183     if (!found) {
00184         for (PoolItemList::const_iterator iter = _items_to_install.begin();
00185              iter != _items_to_install.end(); ++iter) {
00186             if (*iter == item) {
00187                 _items_to_install.remove(*iter);
00188                 found = true;
00189                 break;
00190             }
00191         }
00192     }
00193     if (!found) {
00194         for (PoolItemList::const_iterator iter = _items_to_keep.begin();
00195              iter != _items_to_keep.end(); ++iter) {
00196             if (*iter == item) {
00197                 _items_to_keep.remove(*iter);
00198                 found = true;
00199                 break;
00200             }
00201         }
00202     }
00203     if (!found) {
00204         for (PoolItemList::const_iterator iter = _items_to_lock.begin();
00205              iter != _items_to_lock.end(); ++iter) {
00206             if (*iter == item) {
00207                 _items_to_lock.remove(*iter);
00208                 found = true;
00209                 break;
00210             }
00211         }
00212     }
00213 }
00214 
00215 
00216 void
00217 SATResolver::addPoolItemToInstall (PoolItem item)
00218 {
00219     resetItemTransaction (item);
00220     _items_to_install.push_back (item);
00221     _items_to_install.unique ();
00222 }
00223 
00224 
00225 void
00226 SATResolver::addPoolItemsToInstallFromList (PoolItemList & rl)
00227 {
00228     for (PoolItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) {
00229         addPoolItemToInstall (*iter);
00230     }
00231 }
00232 
00233 
00234 void
00235 SATResolver::addPoolItemToRemove (PoolItem item)
00236 {
00237     resetItemTransaction (item);
00238     _items_to_remove.push_back (item);
00239     _items_to_remove.unique ();
00240 }
00241 
00242 
00243 void
00244 SATResolver::addPoolItemsToRemoveFromList (PoolItemList & rl)
00245 {
00246     for (PoolItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) {
00247         addPoolItemToRemove (*iter);
00248     }
00249 }
00250 
00251 void
00252 SATResolver::addPoolItemToLock (PoolItem item)
00253 {
00254     resetItemTransaction (item);
00255     _items_to_lock.push_back (item);
00256     _items_to_lock.unique ();
00257 }
00258 
00259 void
00260 SATResolver::addPoolItemToKeep (PoolItem item)
00261 {
00262     resetItemTransaction (item);
00263     _items_to_keep.push_back (item);
00264     _items_to_keep.unique ();
00265 }
00266 
00267 //---------------------------------------------------------------------------
00268 
00269 // copy marked item from solution back to pool
00270 // if data != NULL, set as APPL_LOW (from establishPool())
00271 
00272 static void
00273 SATSolutionToPool (PoolItem item, const ResStatus & status, const ResStatus::TransactByValue causer)
00274 {
00275     // resetting
00276     item.status().resetTransact (causer);
00277     item.status().resetWeak ();
00278 
00279     bool r;
00280 
00281     // installation/deletion
00282     if (status.isToBeInstalled()) {
00283         r = item.status().setToBeInstalled (causer);
00284         _XDEBUG("SATSolutionToPool install returns " << item << ", " << r);
00285     }
00286     else if (status.isToBeUninstalledDueToUpgrade()) {
00287         r = item.status().setToBeUninstalledDueToUpgrade (causer);
00288         _XDEBUG("SATSolutionToPool upgrade returns " << item << ", " <<  r);
00289     }
00290     else if (status.isToBeUninstalled()) {
00291         r = item.status().setToBeUninstalled (causer);
00292         _XDEBUG("SATSolutionToPool remove returns " << item << ", " <<  r);
00293     }
00294 
00295     return;
00296 }
00297 
00298 //----------------------------------------------------------------------------
00299 //----------------------------------------------------------------------------
00300 // resolvePool
00301 //----------------------------------------------------------------------------
00302 //----------------------------------------------------------------------------
00303 
00304 //----------------------------------------------------------------------------
00305 // Helper functions for the ZYPP-Pool
00306 //----------------------------------------------------------------------------
00307 
00308 
00309 //------------------------------------------------------------------------------------------------------------
00310 //  This function loops over the pool and grabs all items
00311 //  It clears all previous bySolver() states also
00312 //
00313 //  Every toBeInstalled is passed to zypp::solver:detail::Resolver.addPoolItemToInstall()
00314 //  Every toBeUninstalled is passed to zypp::solver:detail::Resolver.addPoolItemToRemove()
00315 //
00316 //  Solver results must be written back to the pool.
00317 //------------------------------------------------------------------------------------------------------------
00318 
00319 
00320 struct SATCollectTransact : public resfilter::PoolItemFilterFunctor
00321 {
00322     SATResolver & resolver;
00323 
00324     SATCollectTransact (SATResolver & r)
00325         : resolver (r)
00326     { }
00327 
00328     bool operator()( PoolItem item )            // only transacts() items go here
00329     {
00330         ResStatus status = item.status();
00331         bool by_solver = (status.isBySolver() || status.isByApplLow());
00332 
00333         if (by_solver) {
00334             item.status().resetTransact( ResStatus::APPL_LOW );// clear any solver/establish transactions
00335             return true;                                // back out here, dont re-queue former solver result
00336         }
00337 
00338         if ( item.satSolvable().isKind<SrcPackage>() && ! resolver.solveSrcPackages() )
00339         {
00340           // Later we may continue on a per source package base.
00341           return true; // dont process this source package.
00342         }
00343 
00344         if (status.isToBeInstalled()) {
00345             resolver.addPoolItemToInstall(item);        // -> install!
00346         }
00347         else if (status.isToBeUninstalled()) {
00348             resolver.addPoolItemToRemove(item);         // -> remove !
00349         }
00350         else if (status.isLocked()
00351                  && !by_solver) {
00352             resolver.addPoolItemToLock (item);
00353         }
00354         else if (status.isKept()
00355                  && !by_solver) {
00356             resolver.addPoolItemToKeep (item);
00357         }
00358 
00359         return true;
00360     }
00361 };
00362 
00363 
00364 //----------------------------------------------------------------------------
00365 //----------------------------------------------------------------------------
00366 // solving.....
00367 //----------------------------------------------------------------------------
00368 //----------------------------------------------------------------------------
00369 
00370 
00371 class CheckIfUpdate : public resfilter::PoolItemFilterFunctor
00372 {
00373   public:
00374     bool is_updated;
00375     bool multiversion;
00376     sat::Solvable _installed;
00377 
00378     CheckIfUpdate( sat::Solvable installed_r )
00379         : is_updated( false )
00380         , multiversion( installed_r.multiversionInstall() )
00381         , _installed( installed_r )
00382     {}
00383 
00384     // check this item will be updated
00385 
00386     bool operator()( PoolItem item )
00387     {
00388         if ( item.status().isToBeInstalled() )
00389         {
00390           if ( ! multiversion || sameNVRA( _installed, item ) )
00391           {
00392             is_updated = true;
00393             return false;
00394           }
00395         }
00396         return true;
00397     }
00398 };
00399 
00400 
00401 class CollectPseudoInstalled : public resfilter::PoolItemFilterFunctor
00402 {
00403   public:
00404     Queue *solvableQueue;
00405 
00406     CollectPseudoInstalled( Queue *queue )
00407         :solvableQueue (queue)
00408     {}
00409 
00410     // collecting PseudoInstalled items
00411     bool operator()( PoolItem item )
00412     {
00413       if ( traits::isPseudoInstalled( item.satSolvable().kind() ) )
00414         queue_push( solvableQueue, item.satSolvable().id() );
00415       return true;
00416     }
00417 };
00418 
00419 bool
00420 SATResolver::solving(const CapabilitySet & requires_caps,
00421                      const CapabilitySet & conflict_caps)
00422 {
00423     _solv = solver_create( _SATPool );
00424     _solv->vendorCheckCb = &vendorCheck;
00425     _solv->fixsystem = _fixsystem;
00426     _solv->ignorealreadyrecommended = _ignorealreadyrecommended;
00427     _solv->updatesystem = _updatesystem;
00428     _solv->allowdowngrade = _allowdowngrade;
00429     _solv->allowuninstall = _allowuninstall;
00430     _solv->allowarchchange = _allowarchchange;
00431     _solv->allowvendorchange = _allowvendorchange;
00432     _solv->dosplitprovides = _dosplitprovides;
00433     _solv->noupdateprovide = _noupdateprovide;
00434     _solv->dontinstallrecommended = _onlyRequires;
00435     _solv->distupgrade = _distupgrade;
00436     _solv->distupgrade_removeunsupported = _distupgrade_removeunsupported;
00437 
00438     sat::Pool::instance().prepare();
00439 
00440     // Solve !
00441     MIL << "Starting solving...." << endl;
00442     MIL << *this;
00443     solver_solve( _solv, &(_jobQueue) );
00444     MIL << "....Solver end" << endl;
00445 
00446     // copying solution back to zypp pool
00447     //-----------------------------------------
00448     _result_items_to_install.clear();
00449     _result_items_to_remove.clear();
00450 
00451     /*  solvables to be installed */
00452     for ( int i = 0; i < _solv->decisionq.count; ++i )
00453     {
00454       sat::Solvable slv( _solv->decisionq.elements[i] );
00455       if ( !slv || slv.isSystem() )
00456         continue;
00457 
00458       PoolItem poolItem( slv );
00459       SATSolutionToPool (poolItem, ResStatus::toBeInstalled, ResStatus::SOLVER);
00460       _result_items_to_install.push_back (poolItem);
00461     }
00462 
00463     /* solvables to be erased */
00464     Repository systemRepo( sat::Pool::instance().findSystemRepo() ); // don't create if it does not exist
00465     if ( systemRepo && ! systemRepo.solvablesEmpty() )
00466     {
00467       bool mustCheckObsoletes = false;
00468       for_( it, systemRepo.solvablesBegin(), systemRepo.solvablesEnd() )
00469       {
00470         if (_solv->decisionmap[it->id()] > 0)
00471           continue;
00472 
00473         // Check if this is an update
00474         CheckIfUpdate info( *it );
00475         PoolItem poolItem( *it );
00476         invokeOnEach( _pool.byIdentBegin( poolItem ),
00477                       _pool.byIdentEnd( poolItem ),
00478                       resfilter::ByUninstalled(),                       // ByUninstalled
00479                       functor::functorRef<bool,PoolItem> (info) );
00480 
00481         if (info.is_updated) {
00482           SATSolutionToPool( poolItem, ResStatus::toBeUninstalledDueToUpgrade, ResStatus::SOLVER );
00483         } else {
00484           SATSolutionToPool( poolItem, ResStatus::toBeUninstalled, ResStatus::SOLVER );
00485           if ( ! mustCheckObsoletes )
00486             mustCheckObsoletes = true; // lazy check for UninstalledDueToObsolete
00487         }
00488         _result_items_to_remove.push_back (poolItem);
00489       }
00490       if ( mustCheckObsoletes )
00491       {
00492         sat::WhatObsoletes obsoleted( _result_items_to_install.begin(), _result_items_to_install.end() );
00493         for_( it, obsoleted.poolItemBegin(), obsoleted.poolItemEnd() )
00494         {
00495           ResStatus & status( it->status() );
00496           // WhatObsoletes contains installed items only!
00497           if ( status.transacts() && ! status.isToBeUninstalledDueToUpgrade() )
00498             status.setToBeUninstalledDueToObsolete();
00499         }
00500       }
00501     }
00502 
00503     /*  solvables which are recommended */
00504     for ( int i = 0; i < _solv->recommendations.count; ++i )
00505     {
00506       PoolItem poolItem( getPoolItem( _solv->recommendations.elements[i] ) );
00507       poolItem.status().setRecommended( true );
00508     }
00509 
00510     /*  solvables which are suggested */
00511     for ( int i = 0; i < _solv->suggestions.count; ++i )
00512     {
00513       PoolItem poolItem( getPoolItem( _solv->suggestions.elements[i] ) );
00514       poolItem.status().setSuggested( true );
00515     }
00516 
00517     _problem_items.clear();
00518     /*  solvables which are orphaned */
00519     for ( int i = 0; i < _solv->orphaned.count; ++i )
00520     {
00521       PoolItem poolItem( getPoolItem( _solv->orphaned.elements[i] ) );
00522       poolItem.status().setOrphaned( true );
00523       _problem_items.push_back( poolItem );
00524     }
00525 
00526     /* Write validation state back to pool */
00527     Queue flags, solvableQueue;
00528 
00529     queue_init(&flags);
00530     queue_init(&solvableQueue);
00531 
00532     CollectPseudoInstalled collectPseudoInstalled(&solvableQueue);
00533     invokeOnEach( _pool.begin(),
00534                   _pool.end(),
00535                   functor::functorRef<bool,PoolItem> (collectPseudoInstalled) );
00536     solver_trivial_installable(_solv, &solvableQueue, &flags );
00537     for (int i = 0; i < solvableQueue.count; i++) {
00538         PoolItem item = _pool.find (sat::Solvable(solvableQueue.elements[i]));
00539         item.status().setUndetermined();
00540 
00541         if (flags.elements[i] == -1) {
00542             item.status().setNonRelevant();
00543             _XDEBUG("SATSolutionToPool(" << item << " ) nonRelevant !");
00544         } else if (flags.elements[i] == 1) {
00545             item.status().setSatisfied();
00546             _XDEBUG("SATSolutionToPool(" << item << " ) satisfied !");
00547         } else if (flags.elements[i] == 0) {
00548             item.status().setBroken();
00549             _XDEBUG("SATSolutionToPool(" << item << " ) broken !");
00550         }
00551     }
00552 
00553     // Solvables which were selected due requirements which have been made by the user will
00554     // be selected by APPL_LOW. We can't use any higher level, because this setting must
00555     // not serve as a request for the next solver run. APPL_LOW is reset before solving.
00556     for (CapabilitySet::const_iterator iter = requires_caps.begin(); iter != requires_caps.end(); iter++) {
00557         sat::WhatProvides rpmProviders(*iter);
00558         for_( iter2, rpmProviders.begin(), rpmProviders.end() ) {
00559             PoolItem poolItem(*iter2);
00560             if (poolItem.status().isToBeInstalled()) {
00561                 MIL << "User requirement " << *iter << " sets " << poolItem << endl;
00562                 poolItem.status().setTransactByValue (ResStatus::APPL_LOW);
00563             }
00564         }
00565     }
00566     for (CapabilitySet::const_iterator iter = conflict_caps.begin(); iter != conflict_caps.end(); iter++) {
00567         sat::WhatProvides rpmProviders(*iter);
00568         for_( iter2, rpmProviders.begin(), rpmProviders.end() ) {
00569             PoolItem poolItem(*iter2);
00570             if (poolItem.status().isToBeUninstalled()) {
00571                 MIL << "User conflict " << *iter << " sets " << poolItem << endl;
00572                 poolItem.status().setTransactByValue (ResStatus::APPL_LOW);
00573             }
00574         }
00575     }
00576 
00577     if (_solv->problems.count > 0 )
00578     {
00579         ERR << "Solverrun finished with an ERROR" << endl;
00580         return false;
00581     }
00582 
00583     queue_free(&(solvableQueue));
00584     queue_free(&flags);
00585 
00586     return true;
00587 }
00588 
00589 
00590 void
00591 SATResolver::solverInit(const PoolItemList & weakItems)
00592 {
00593     SATCollectTransact info (*this);
00594 
00595     MIL << "SATResolver::solverInit()" << endl;
00596 
00597     if (_solv) {
00598         // remove old stuff
00599         solver_free(_solv);
00600         _solv = NULL;
00601         queue_free( &(_jobQueue) );
00602     }
00603 
00604     queue_init( &_jobQueue );
00605     _items_to_install.clear();
00606     _items_to_remove.clear();
00607     _items_to_lock.clear();
00608     _items_to_keep.clear();
00609 
00610     invokeOnEach ( _pool.begin(), _pool.end(),
00611                    functor::functorRef<bool,PoolItem>(info) );
00612 
00613     for (PoolItemList::const_iterator iter = weakItems.begin(); iter != weakItems.end(); iter++) {
00614         Id id = (*iter)->satSolvable().id();
00615         if (id == ID_NULL) {
00616             ERR << "Weaken: " << *iter << " not found" << endl;
00617         }
00618         MIL << "Weaken dependencies of " << *iter << endl;
00619         queue_push( &(_jobQueue), SOLVER_WEAKENDEPS | SOLVER_SOLVABLE );
00620         queue_push( &(_jobQueue), id );
00621     }
00622 
00623     // Add rules for parallel installable resolvables with different versions
00624     for_( it, sat::Pool::instance().multiversionBegin(), sat::Pool::instance().multiversionEnd() )
00625     {
00626       queue_push( &(_jobQueue), SOLVER_NOOBSOLETES | SOLVER_SOLVABLE_NAME );
00627       queue_push( &(_jobQueue), it->id() );
00628     }
00629 
00630     if ( cleandepsOnRemove() )
00631     {
00632       // Add all items known to be installed by user request (not solver selected).
00633       for_( it, sat::Pool::instance().onSystemByUserBegin(), sat::Pool::instance().onSystemByUserEnd() )
00634       {
00635         queue_push( &(_jobQueue), SOLVER_USERINSTALLED | SOLVER_SOLVABLE_NAME );
00636         queue_push( &(_jobQueue), it->id() );
00637       }
00638     }
00639 
00640     if ( _distupgrade )
00641     {
00642       if ( ZConfig::instance().solverUpgradeRemoveDroppedPackages() )
00643       {
00644         MIL << "Checking droplists ..." << endl;
00645         // Dropped packages: look for 'weakremover()' provides
00646         // in dup candidates of installed products.
00647         ResPoolProxy proxy( ResPool::instance().proxy() );
00648         for_( it, proxy.byKindBegin<Product>(), proxy.byKindEnd<Product>() )
00649         {
00650           if ( (*it)->onSystem() ) // (to install) or (not to delete)
00651           {
00652             Product::constPtr prodCand( (*it)->candidateAsKind<Product>() );
00653             if ( ! prodCand || (*it)->identicalInstalledCandidate() )
00654               continue; // product no longer available or unchanged
00655 
00656             CapabilitySet droplist( prodCand->droplist() );
00657             dumpRangeLine( MIL << "Droplist for " << (*it)->candidateObj() << ": " << droplist.size() << " ", droplist.begin(), droplist.end() ) << endl;
00658             for_( cap, droplist.begin(), droplist.end() )
00659             {
00660               queue_push( &_jobQueue, SOLVER_DROP_ORPHANED | SOLVER_SOLVABLE_NAME );
00661               queue_push( &_jobQueue, cap->id() );
00662             }
00663           }
00664         }
00665       }
00666       else
00667       {
00668         MIL << "Droplist processing is disabled." << endl;
00669       }
00670     }
00671 }
00672 
00673 void
00674 SATResolver::solverEnd()
00675 {
00676     // cleanup
00677     solver_free(_solv);
00678     _solv = NULL;
00679     queue_free( &(_jobQueue) );
00680 }
00681 
00682 
00683 bool
00684 SATResolver::resolvePool(const CapabilitySet & requires_caps,
00685                          const CapabilitySet & conflict_caps,
00686                          const PoolItemList & weakItems,
00687                          const std::set<Repository> & upgradeRepos)
00688 {
00689     MIL << "SATResolver::resolvePool()" << endl;
00690 
00691     // initialize
00692     solverInit(weakItems);
00693 
00694     for (PoolItemList::const_iterator iter = _items_to_install.begin(); iter != _items_to_install.end(); iter++) {
00695         Id id = (*iter)->satSolvable().id();
00696         if (id == ID_NULL) {
00697             ERR << "Install: " << *iter << " not found" << endl;
00698         } else {
00699             MIL << "Install " << *iter << endl;
00700             queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE );
00701             queue_push( &(_jobQueue), id );
00702         }
00703     }
00704 
00705     for (PoolItemList::const_iterator iter = _items_to_remove.begin(); iter != _items_to_remove.end(); iter++) {
00706         Id id = (*iter)->satSolvable().id();
00707         if (id == ID_NULL) {
00708             ERR << "Delete: " << *iter << " not found" << endl;
00709         } else {
00710             MIL << "Delete " << *iter << endl;
00711             queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE | MAYBE_CLEANDEPS );
00712             queue_push( &(_jobQueue), id);
00713         }
00714     }
00715 
00716     for_( iter, upgradeRepos.begin(), upgradeRepos.end() )
00717     {
00718         queue_push( &(_jobQueue), SOLVER_DISTUPGRADE | SOLVER_SOLVABLE_REPO );
00719         queue_push( &(_jobQueue), iter->get()->repoid );
00720         MIL << "Upgrade repo " << *iter << endl;
00721     }
00722 
00723     for (CapabilitySet::const_iterator iter = requires_caps.begin(); iter != requires_caps.end(); iter++) {
00724         queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES );
00725         queue_push( &(_jobQueue), iter->id() );
00726         MIL << "Requires " << *iter << endl;
00727     }
00728 
00729     for (CapabilitySet::const_iterator iter = conflict_caps.begin(); iter != conflict_caps.end(); iter++) {
00730         queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE_PROVIDES | MAYBE_CLEANDEPS );
00731         queue_push( &(_jobQueue), iter->id() );
00732         MIL << "Conflicts " << *iter << endl;
00733     }
00734 
00735     // set requirements for a running system
00736     setSystemRequirements();
00737 
00738     // set locks for the solver
00739     setLocks();
00740 
00741     // solving
00742     bool ret = solving(requires_caps, conflict_caps);
00743     // cleanup
00744     if (ret)
00745         solverEnd(); // remove solver only if no errors happend. Need it for solving problems
00746 
00747     (ret?MIL:WAR) << "SATResolver::resolvePool() done. Ret:" << ret <<  endl;
00748     return ret;
00749 }
00750 
00751 
00752 bool
00753 SATResolver::resolveQueue(const SolverQueueItemList &requestQueue,
00754                           const PoolItemList & weakItems)
00755 {
00756     MIL << "SATResolver::resolvQueue()" << endl;
00757 
00758     // initialize
00759     solverInit(weakItems);
00760 
00761     // generate solver queue
00762     for (SolverQueueItemList::const_iterator iter = requestQueue.begin(); iter != requestQueue.end(); iter++) {
00763         (*iter)->addRule(_jobQueue);
00764     }
00765 
00766     // Add addition item status to the resolve-queue cause these can be set by problem resolutions
00767     for (PoolItemList::const_iterator iter = _items_to_install.begin(); iter != _items_to_install.end(); iter++) {
00768         Id id = (*iter)->satSolvable().id();
00769         if (id == ID_NULL) {
00770             ERR << "Install: " << *iter << " not found" << endl;
00771         } else {
00772             MIL << "Install " << *iter << endl;
00773             queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE );
00774             queue_push( &(_jobQueue), id );
00775         }
00776     }
00777     for (PoolItemList::const_iterator iter = _items_to_remove.begin(); iter != _items_to_remove.end(); iter++) {
00778         sat::detail::IdType ident( (*iter)->satSolvable().ident().id() );
00779         MIL << "Delete " << *iter << ident << endl;
00780         queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE_NAME | MAYBE_CLEANDEPS );
00781         queue_push( &(_jobQueue), ident);
00782     }
00783 
00784     // set requirements for a running system
00785     setSystemRequirements();
00786 
00787     // set locks for the solver
00788     setLocks();
00789 
00790     // solving
00791     bool ret = solving();
00792 
00793     // cleanup
00794     if (ret)
00795         solverEnd(); // remove solver only if no errors happend. Need it for solving problems
00796 
00797     MIL << "SATResolver::resolveQueue() done. Ret:" << ret <<  endl;
00798     return ret;
00799 }
00800 
00802 void SATResolver::doUpdate()
00803 {
00804     MIL << "SATResolver::doUpdate()" << endl;
00805 
00806     // initialize
00807     solverInit(PoolItemList());
00808 
00809     // set requirements for a running system
00810     setSystemRequirements();
00811 
00812     // set locks for the solver
00813     setLocks();
00814 
00815     _solv = solver_create( _SATPool );
00816     _solv->vendorCheckCb = &vendorCheck;
00817     _solv->fixsystem = _fixsystem;
00818     _solv->ignorealreadyrecommended = _ignorealreadyrecommended;
00819     _solv->updatesystem = true;
00820     _solv->allowdowngrade = _allowdowngrade;
00821     _solv->allowuninstall = _allowuninstall;
00822     _solv->allowarchchange = _allowarchchange;
00823     _solv->allowvendorchange = _allowvendorchange;
00824     _solv->dosplitprovides = true;
00825     _solv->noupdateprovide = _noupdateprovide;
00826     _solv->dontinstallrecommended = _onlyRequires;
00827     _solv->distupgrade = _distupgrade;
00828     _solv->distupgrade_removeunsupported = _distupgrade_removeunsupported;
00829 
00830     sat::Pool::instance().prepare();
00831 
00832     // Solve !
00833     MIL << "Starting solving for update...." << endl;
00834     MIL << *this;
00835     solver_solve( _solv, &(_jobQueue) );
00836     MIL << "....Solver end" << endl;
00837 
00838     // copying solution back to zypp pool
00839     //-----------------------------------------
00840 
00841     /*  solvables to be installed */
00842     for (int i = 0; i < _solv->decisionq.count; i++)
00843     {
00844       Id p;
00845       p = _solv->decisionq.elements[i];
00846       if (p < 0 || !sat::Solvable(p))
00847         continue;
00848       if (sat::Solvable(p).repository().get() == _solv->installed)
00849         continue;
00850 
00851       PoolItem poolItem = _pool.find (sat::Solvable(p));
00852       if (poolItem) {
00853           SATSolutionToPool (poolItem, ResStatus::toBeInstalled, ResStatus::SOLVER);
00854       } else {
00855           ERR << "id " << p << " not found in ZYPP pool." << endl;
00856       }
00857     }
00858 
00859     /* solvables to be erased */
00860     for (int i = _solv->installed->start; i < _solv->installed->start + _solv->installed->nsolvables; i++)
00861     {
00862       if (_solv->decisionmap[i] > 0)
00863         continue;
00864 
00865       PoolItem poolItem( _pool.find( sat::Solvable(i) ) );
00866       if (poolItem) {
00867           // Check if this is an update
00868           CheckIfUpdate info( (sat::Solvable(i)) );
00869           invokeOnEach( _pool.byIdentBegin( poolItem ),
00870                         _pool.byIdentEnd( poolItem ),
00871                         resfilter::ByUninstalled(),                     // ByUninstalled
00872                         functor::functorRef<bool,PoolItem> (info) );
00873 
00874           if (info.is_updated) {
00875               SATSolutionToPool (poolItem, ResStatus::toBeUninstalledDueToUpgrade , ResStatus::SOLVER);
00876           } else {
00877               SATSolutionToPool (poolItem, ResStatus::toBeUninstalled, ResStatus::SOLVER);
00878           }
00879       } else {
00880           ERR << "id " << i << " not found in ZYPP pool." << endl;
00881       }
00882     }
00883 
00884     // cleanup
00885     solverEnd();
00886 
00887     MIL << "SATResolver::doUpdate() done" << endl;
00888 }
00889 
00890 
00891 
00892 //----------------------------------------------------------------------------
00893 //----------------------------------------------------------------------------
00894 // error handling
00895 //----------------------------------------------------------------------------
00896 //----------------------------------------------------------------------------
00897 
00898 //----------------------------------------------------------------------------
00899 // helper function
00900 //----------------------------------------------------------------------------
00901 
00902 struct FindPackage : public resfilter::ResObjectFilterFunctor
00903 {
00904     ProblemSolutionCombi *problemSolution;
00905     TransactionKind action;
00906     FindPackage (ProblemSolutionCombi *p, const TransactionKind act)
00907        : problemSolution (p)
00908        , action (act)
00909         {
00910         }
00911 
00912     bool operator()( PoolItem p)
00913    {
00914        problemSolution->addSingleAction (p, action);
00915        return true;
00916    }
00917 };
00918 
00919 
00920 //----------------------------------------------------------------------------
00921 // Checking if this solvable/item has a buddy which reflect the real
00922 // user visible description of an item
00923 // e.g. The release package has a buddy to the concerning product item.
00924 // This user want's the message "Product foo conflicts with product bar" and
00925 // NOT "package release-foo conflicts with package release-bar"
00926 //----------------------------------------------------------------------------
00927 
00928 
00929 PoolItem SATResolver::mapItem (const PoolItem &item)
00930 {
00931     sat::Solvable buddy = item.buddy();
00932     if (buddy != sat::Solvable())
00933     {
00934         return _pool.find (buddy);
00935     }
00936     else
00937     {
00938         return item;
00939     }
00940 }
00941 
00942 sat::Solvable SATResolver::mapSolvable (const Id &id)
00943 {
00944     PoolItem item = _pool.find (sat::Solvable(id));
00945     return mapItem(item).satSolvable();
00946 }
00947 
00948 string SATResolver::SATprobleminfoString(Id problem, string &detail, Id &ignoreId)
00949 {
00950   string ret;
00951   Pool *pool = _solv->pool;
00952   Id probr;
00953   Id dep, source, target;
00954   sat::Solvable s, s2;
00955 
00956   ignoreId = 0;
00957   probr = solver_findproblemrule(_solv, problem);
00958   switch (solver_ruleinfo(_solv, probr, &source, &target, &dep))
00959   {
00960       case SOLVER_RULE_DISTUPGRADE:
00961           s = mapSolvable (source);
00962           ret = str::form (_("%s does not belong to a distupgrade repository"), s.asString().c_str());
00963           break;
00964       case SOLVER_RULE_INFARCH:
00965           s = mapSolvable (source);
00966           ret = str::form (_("%s has inferior architecture"), s.asString().c_str());
00967           break;
00968       case SOLVER_RULE_UPDATE:
00969           s = mapSolvable (source);
00970           ret = str::form (_("problem with installed package %s"), s.asString().c_str());
00971           break;
00972       case SOLVER_RULE_JOB:
00973           ret = _("conflicting requests");
00974           break;
00975       case SOLVER_RULE_RPM:
00976           ret = _("some dependency problem");
00977           break;
00978       case SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP:
00979           ret = str::form (_("nothing provides requested %s"), dep2str(pool, dep));
00980           detail += _("Have you enabled all requested repositories?");
00981           break;
00982       case SOLVER_RULE_RPM_NOT_INSTALLABLE:
00983           s = mapSolvable (source);
00984           ret = str::form (_("%s is not installable"), s.asString().c_str());
00985           break;
00986       case SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP:
00987           ignoreId = source; // for setting weak dependencies
00988           s = mapSolvable (source);
00989           ret = str::form (_("nothing provides %s needed by %s"), dep2str(pool, dep), s.asString().c_str());
00990           break;
00991       case SOLVER_RULE_RPM_SAME_NAME:
00992           s = mapSolvable (source);
00993           s2 = mapSolvable (target);
00994           ret = str::form (_("cannot install both %s and %s"), s.asString().c_str(), s2.asString().c_str());
00995           break;
00996       case SOLVER_RULE_RPM_PACKAGE_CONFLICT:
00997           s = mapSolvable (source);
00998           s2 = mapSolvable (target);
00999           ret = str::form (_("%s conflicts with %s provided by %s"), s.asString().c_str(), dep2str(pool, dep), s2.asString().c_str());
01000           break;
01001       case SOLVER_RULE_RPM_PACKAGE_OBSOLETES:
01002           s = mapSolvable (source);
01003           s2 = mapSolvable (target);
01004           ret = str::form (_("%s obsoletes %s provided by %s"), s.asString().c_str(), dep2str(pool, dep), s2.asString().c_str());
01005           break;
01006       case SOLVER_RULE_RPM_INSTALLEDPKG_OBSOLETES:
01007           s = mapSolvable (source);
01008           s2 = mapSolvable (target);
01009           ret = str::form (_("installed %s obsoletes %s provided by %s"), s.asString().c_str(), dep2str(pool, dep), s2.asString().c_str());
01010           break;
01011       case SOLVER_RULE_RPM_SELF_CONFLICT:
01012           s = mapSolvable (source);
01013           ret = str::form (_("solvable %s conflicts with %s provided by itself"), s.asString().c_str(), dep2str(pool, dep));
01014           break;
01015       case SOLVER_RULE_RPM_PACKAGE_REQUIRES:
01016           ignoreId = source; // for setting weak dependencies
01017           s = mapSolvable (source);
01018           Capability cap(dep);
01019           sat::WhatProvides possibleProviders(cap);
01020 
01021           // check, if a provider will be deleted
01022           typedef list<PoolItem> ProviderList;
01023           ProviderList providerlistInstalled, providerlistUninstalled;
01024           for_( iter1, possibleProviders.begin(), possibleProviders.end() ) {
01025               PoolItem provider1 = ResPool::instance().find( *iter1 );
01026               // find pair of an installed/uninstalled item with the same NVR
01027               bool found = false;
01028               for_( iter2, possibleProviders.begin(), possibleProviders.end() ) {
01029                   PoolItem provider2 = ResPool::instance().find( *iter2 );
01030                   if (compareByNVR (provider1.resolvable(),provider2.resolvable()) == 0
01031                       && ( (provider1.status().isInstalled() && provider2.status().isUninstalled())
01032                           || (provider2.status().isInstalled() && provider1.status().isUninstalled()) ))  {
01033                       found = true;
01034                       break;
01035                   }
01036               }
01037               if (!found) {
01038                   if (provider1.status().isInstalled())
01039                       providerlistInstalled.push_back(provider1);
01040                   else
01041                       providerlistUninstalled.push_back(provider1);
01042               }
01043           }
01044 
01045           ret = str::form (_("%s requires %s, but this requirement cannot be provided"), s.asString().c_str(), dep2str(pool, dep));
01046           if (providerlistInstalled.size() > 0) {
01047               detail += _("deleted providers: ");
01048               for (ProviderList::const_iterator iter = providerlistInstalled.begin(); iter != providerlistInstalled.end(); iter++) {
01049                   if (iter == providerlistInstalled.begin())
01050                       detail += itemToString( *iter );
01051                   else
01052                       detail += "\n                   " + itemToString( mapItem(*iter) );
01053               }
01054           }
01055           if (providerlistUninstalled.size() > 0) {
01056               if (detail.size() > 0)
01057                   detail += _("\nuninstallable providers: ");
01058               else
01059                   detail = _("uninstallable providers: ");
01060               for (ProviderList::const_iterator iter = providerlistUninstalled.begin(); iter != providerlistUninstalled.end(); iter++) {
01061                   if (iter == providerlistUninstalled.begin())
01062                       detail += itemToString( *iter );
01063                   else
01064                       detail += "\n                   " + itemToString( mapItem(*iter) );
01065               }
01066           }
01067           break;
01068   }
01069 
01070   return ret;
01071 }
01072 
01073 ResolverProblemList
01074 SATResolver::problems ()
01075 {
01076     ResolverProblemList resolverProblems;
01077     if (_solv && _solv->problems.count) {
01078         Pool *pool = _solv->pool;
01079         int pcnt;
01080         Id p, rp, what;
01081         Id problem, solution, element;
01082         sat::Solvable s, sd;
01083 
01084         CapabilitySet system_requires = SystemCheck::instance().requiredSystemCap();
01085         CapabilitySet system_conflicts = SystemCheck::instance().conflictSystemCap();
01086 
01087         MIL << "Encountered problems! Here are the solutions:\n" << endl;
01088         pcnt = 1;
01089         problem = 0;
01090         while ((problem = solver_next_problem(_solv, problem)) != 0) {
01091             MIL << "Problem " <<  pcnt++ << ":" << endl;
01092             MIL << "====================================" << endl;
01093             string detail;
01094             Id ignoreId;
01095             string whatString = SATprobleminfoString (problem,detail,ignoreId);
01096             MIL << whatString << endl;
01097             MIL << "------------------------------------" << endl;
01098             ResolverProblem_Ptr resolverProblem = new ResolverProblem (whatString, detail);
01099 
01100             solution = 0;
01101             while ((solution = solver_next_solution(_solv, problem, solution)) != 0) {
01102                 element = 0;
01103                 ProblemSolutionCombi *problemSolution = new ProblemSolutionCombi(resolverProblem);
01104                 while ((element = solver_next_solutionelement(_solv, problem, solution, element, &p, &rp)) != 0) {
01105                     if (p == SOLVER_SOLUTION_JOB) {
01106                         /* job, rp is index into job queue */
01107                         what = _jobQueue.elements[rp];
01108                         switch (_jobQueue.elements[rp-1]&(SOLVER_SELECTMASK|SOLVER_JOBMASK))
01109                         {
01110                             case SOLVER_INSTALL | SOLVER_SOLVABLE: {
01111                                 s = mapSolvable (what);
01112                                 PoolItem poolItem = _pool.find (s);
01113                                 if (poolItem) {
01114                                     if (_solv->installed && s.get()->repo == _solv->installed) {
01115                                         problemSolution->addSingleAction (poolItem, REMOVE);
01116                                         string description = str::form (_("do not keep %s installed"),  s.asString().c_str() );
01117                                         MIL << description << endl;
01118                                         problemSolution->addDescription (description);
01119                                     } else {
01120                                         problemSolution->addSingleAction (poolItem, KEEP);
01121                                         string description = str::form (_("do not install %s"), s.asString().c_str());
01122                                         MIL << description << endl;
01123                                         problemSolution->addDescription (description);
01124                                     }
01125                                 } else {
01126                                     ERR << "SOLVER_INSTALL_SOLVABLE: No item found for " << s.asString() << endl;
01127                                 }
01128                             }
01129                                 break;
01130                             case SOLVER_ERASE | SOLVER_SOLVABLE: {
01131                                 s = mapSolvable (what);
01132                                 PoolItem poolItem = _pool.find (s);
01133                                 if (poolItem) {
01134                                     if (_solv->installed && s.get()->repo == _solv->installed) {
01135                                         problemSolution->addSingleAction (poolItem, KEEP);
01136                                         string description = str::form (_("keep %s"), s.asString().c_str());
01137                                         MIL << description << endl;
01138                                         problemSolution->addDescription (description);
01139                                     } else {
01140                                         problemSolution->addSingleAction (poolItem, UNLOCK);
01141                                         string description = str::form (_("do not forbid installation of %s"), itemToString( poolItem ).c_str());
01142                                         MIL << description << endl;
01143                                         problemSolution->addDescription (description);
01144                                     }
01145                                 } else {
01146                                     ERR << "SOLVER_ERASE_SOLVABLE: No item found for " << s.asString() << endl;
01147                                 }
01148                             }
01149                                 break;
01150                             case SOLVER_INSTALL | SOLVER_SOLVABLE_NAME:
01151                                 {
01152                                 IdString ident( what );
01153                                 SolverQueueItemInstall_Ptr install =
01154                                     new SolverQueueItemInstall(_pool, ident.asString(), false );
01155                                 problemSolution->addSingleAction (install, REMOVE_SOLVE_QUEUE_ITEM);
01156 
01157                                 string description = str::form (_("do not install %s"), ident.c_str() );
01158                                 MIL << description << endl;
01159                                 problemSolution->addDescription (description);
01160                                 }
01161                                 break;
01162                             case SOLVER_ERASE | SOLVER_SOLVABLE_NAME:
01163                                 {
01164                                 // As we do not know, if this request has come from resolvePool or
01165                                 // resolveQueue we will have to take care for both cases.
01166                                 IdString ident( what );
01167                                 FindPackage info (problemSolution, KEEP);
01168                                 invokeOnEach( _pool.byIdentBegin( ident ),
01169                                               _pool.byIdentEnd( ident ),
01170                                               functor::chain (resfilter::ByInstalled (),                        // ByInstalled
01171                                                               resfilter::ByTransact ()),                        // will be deinstalled
01172                                               functor::functorRef<bool,PoolItem> (info) );
01173 
01174                                 SolverQueueItemDelete_Ptr del =
01175                                     new SolverQueueItemDelete(_pool, ident.asString(), false );
01176                                 problemSolution->addSingleAction (del, REMOVE_SOLVE_QUEUE_ITEM);
01177 
01178                                 string description = str::form (_("keep %s"), ident.c_str());
01179                                 MIL << description << endl;
01180                                 problemSolution->addDescription (description);
01181                                 }
01182                                 break;
01183                             case SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES:
01184                                 {
01185                                 problemSolution->addSingleAction (Capability(what), REMOVE_EXTRA_REQUIRE);
01186                                 string description = "";
01187 
01188                                 // Checking if this problem solution would break your system
01189                                 if (system_requires.find(Capability(what)) != system_requires.end()) {
01190                                     // Show a better warning
01191                                     resolverProblem->setDetails( resolverProblem->description() + "\n" + resolverProblem->details() );
01192                                     resolverProblem->setDescription(_("This request will break your system!"));
01193                                     description = _("ignore the warning of a broken system");
01194                                     description += string(" (requires:")+dep2str(pool, what)+")";
01195                                     MIL << description << endl;
01196                                     problemSolution->addFrontDescription (description);
01197                                 } else {
01198                                     description = str::form (_("do not ask to install a solvable providing %s"), dep2str(pool, what));
01199                                     MIL << description << endl;
01200                                     problemSolution->addDescription (description);
01201                                 }
01202                                 }
01203                                 break;
01204                             case SOLVER_ERASE | SOLVER_SOLVABLE_PROVIDES:
01205                                 {
01206                                 problemSolution->addSingleAction (Capability(what), REMOVE_EXTRA_CONFLICT);
01207                                 string description = "";
01208 
01209                                 // Checking if this problem solution would break your system
01210                                 if (system_conflicts.find(Capability(what)) != system_conflicts.end()) {
01211                                     // Show a better warning
01212                                     resolverProblem->setDetails( resolverProblem->description() + "\n" + resolverProblem->details() );
01213                                     resolverProblem->setDescription(_("This request will break your system!"));
01214                                     description = _("ignore the warning of a broken system");
01215                                     description += string(" (conflicts:")+dep2str(pool, what)+")";
01216                                     MIL << description << endl;
01217                                     problemSolution->addFrontDescription (description);
01218 
01219                                 } else {
01220                                     description = str::form (_("do not ask to delete all solvables providing %s"), dep2str(pool, what));
01221                                     MIL << description << endl;
01222                                     problemSolution->addDescription (description);
01223                                 }
01224                                 }
01225                                 break;
01226                             case SOLVER_UPDATE | SOLVER_SOLVABLE:
01227                                 {
01228                                 s = mapSolvable (what);
01229                                 PoolItem poolItem = _pool.find (s);
01230                                 if (poolItem) {
01231                                     if (_solv->installed && s.get()->repo == _solv->installed) {
01232                                         problemSolution->addSingleAction (poolItem, KEEP);
01233                                         string description = str::form (_("do not install most recent version of %s"), s.asString().c_str());
01234                                         MIL << description << endl;
01235                                         problemSolution->addDescription (description);
01236                                     } else {
01237                                         ERR << "SOLVER_INSTALL_SOLVABLE_UPDATE " << poolItem << " is not selected for installation" << endl;
01238                                     }
01239                                 } else {
01240                                     ERR << "SOLVER_INSTALL_SOLVABLE_UPDATE: No item found for " << s.asString() << endl;
01241                                 }
01242                                 }
01243                                 break;
01244                             default:
01245                                 MIL << "- do something different" << endl;
01246                                 ERR << "No valid solution available" << endl;
01247                                 break;
01248                         }
01249                     } else if (p == SOLVER_SOLUTION_INFARCH) {
01250                         s = mapSolvable (rp);
01251                         PoolItem poolItem = _pool.find (s);
01252                         if (_solv->installed && s.get()->repo == _solv->installed) {
01253                             problemSolution->addSingleAction (poolItem, LOCK);
01254                             string description = str::form (_("keep %s despite the inferior architecture"), s.asString().c_str());
01255                             MIL << description << endl;
01256                             problemSolution->addDescription (description);
01257                         } else {
01258                             problemSolution->addSingleAction (poolItem, INSTALL);
01259                             string description = str::form (_("install %s despite the inferior architecture"), s.asString().c_str());
01260                             MIL << description << endl;
01261                             problemSolution->addDescription (description);
01262                         }
01263                     } else if (p == SOLVER_SOLUTION_DISTUPGRADE) {
01264                         s = mapSolvable (rp);
01265                         PoolItem poolItem = _pool.find (s);
01266                         if (_solv->installed && s.get()->repo == _solv->installed) {
01267                             problemSolution->addSingleAction (poolItem, LOCK);
01268                             string description = str::form (_("keep obsolete %s"), s.asString().c_str());
01269                             MIL << description << endl;
01270                             problemSolution->addDescription (description);
01271                         } else {
01272                             problemSolution->addSingleAction (poolItem, INSTALL);
01273                             string description = str::form (_("install %s from excluded repository"), s.asString().c_str());
01274                             MIL << description << endl;
01275                             problemSolution->addDescription (description);
01276                         }
01277                     } else {
01278                         /* policy, replace p with rp */
01279                         s = mapSolvable (p);
01280                         if (rp)
01281                             sd = mapSolvable (rp);
01282 
01283                         PoolItem itemFrom = _pool.find (s);
01284                         if (s == sd && _solv->distupgrade)
01285                         {
01286                             PoolItem poolItem = _pool.find (s);
01287                             if (poolItem) {
01288                                 problemSolution->addSingleAction (poolItem, LOCK); // for solver reason: NOT weak lock.
01289                                 string description = str::form (_("keep obsolete %s"), s.asString().c_str());
01290                                 MIL << description << endl;
01291                                 problemSolution->addDescription (description);
01292                             } else {
01293                                 ERR << "SOLVER_INSTALL_SOLVABLE: No item found for " << s.asString() << endl;
01294                             }
01295                         }
01296                         else if (rp)
01297                         {
01298                             int gotone = 0;
01299 
01300                             PoolItem itemTo = _pool.find (sd);
01301                             if (itemFrom && itemTo) {
01302                                 problemSolution->addSingleAction (itemTo, INSTALL);
01303 
01304                                 if (evrcmp(pool, s.get()->evr, sd.get()->evr, EVRCMP_COMPARE ) > 0)
01305                                 {
01306                                     string description = str::form (_("downgrade of %s to %s"), s.asString().c_str(), sd.asString().c_str());
01307                                     MIL << description << endl;
01308                                     problemSolution->addDescription (description);
01309                                     gotone = 1;
01310                                 }
01311                                 if (!_solv->allowarchchange && s.get()->name == sd.get()->name && s.get()->arch != sd.get()->arch
01312                                     && policy_illegal_archchange(_solv, s.get(), sd.get()))
01313                                 {
01314                                     string description = str::form (_("architecture change of %s to %s"), s.asString().c_str(), sd.asString().c_str());
01315                                     MIL << description << endl;
01316                                     problemSolution->addDescription (description);
01317                                     gotone = 1;
01318                                 }
01319                                 if (!_solv->allowvendorchange && s.get()->name == sd.get()->name && s.get()->vendor != sd.get()->vendor
01320                                     && policy_illegal_vendorchange(_solv, s.get(), sd.get()))
01321                                 {
01322                                     IdString s_vendor( s.vendor() );
01323                                     IdString sd_vendor( sd.vendor() );
01324                                     string description = str::form (_("install %s (with vendor change)\n  %s  -->  %s") ,
01325                                                                     sd.asString().c_str(),
01326                                                                     ( s_vendor ? s_vendor.c_str() : " (no vendor) " ),
01327                                                                     ( sd_vendor ? sd_vendor.c_str() : " (no vendor) " ) );
01328                                     MIL << description << endl;
01329                                     problemSolution->addDescription (description);
01330                                     gotone = 1;
01331                                 }
01332                                 if (!gotone) {
01333                                     string description = str::form (_("replacement of %s with %s"), s.asString().c_str(), sd.asString().c_str());
01334                                     MIL << description << endl;
01335                                     problemSolution->addDescription (description);
01336                                 }
01337                             } else {
01338                                 ERR << s.asString() << " or "  << sd.asString() << " not found" << endl;
01339                             }
01340                         }
01341                         else
01342                         {
01343                             if (itemFrom) {
01344                                 string description = str::form (_("deinstallation of %s"), s.asString().c_str());
01345                                 MIL << description << endl;
01346                                 problemSolution->addDescription (description);
01347                                 problemSolution->addSingleAction (itemFrom, REMOVE);
01348                             }
01349                         }
01350                     }
01351                 }
01352                 resolverProblem->addSolution (problemSolution,
01353                                               problemSolution->actionCount() > 1 ? true : false); // Solutions with more than 1 action will be shown first.
01354                 MIL << "------------------------------------" << endl;
01355             }
01356 
01357             if (ignoreId > 0) {
01358                 // There is a possibility to ignore this error by setting weak dependencies
01359                 PoolItem item = _pool.find (sat::Solvable(ignoreId));
01360                 ProblemSolutionIgnore *problemSolution = new ProblemSolutionIgnore(resolverProblem, item);
01361                 resolverProblem->addSolution (problemSolution,
01362                                               false); // Solutions will be shown at the end
01363                 MIL << "ignore some dependencies of " << item << endl;
01364                 MIL << "------------------------------------" << endl;
01365             }
01366 
01367             // save problem
01368             resolverProblems.push_back (resolverProblem);
01369         }
01370     }
01371     return resolverProblems;
01372 }
01373 
01374 void
01375 SATResolver::applySolutions (const ProblemSolutionList & solutions)
01376 {
01377     for (ProblemSolutionList::const_iterator iter = solutions.begin();
01378          iter != solutions.end(); ++iter) {
01379         ProblemSolution_Ptr solution = *iter;
01380         Resolver dummyResolver(_pool);
01381         if (!solution->apply (dummyResolver))
01382             break;
01383     }
01384 }
01385 
01386 void SATResolver::setLocks()
01387 {
01388     for (PoolItemList::const_iterator iter = _items_to_lock.begin(); iter != _items_to_lock.end(); ++iter) {
01389         sat::detail::SolvableIdType ident( (*iter)->satSolvable().id() );
01390         if (iter->status().isInstalled()) {
01391             MIL << "Lock installed item " << *iter << endl;
01392             queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE );
01393             queue_push( &(_jobQueue), ident );
01394         } else {
01395             MIL << "Lock NOT installed item " << *iter << endl;
01396             queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE | MAYBE_CLEANDEPS );
01397             queue_push( &(_jobQueue), ident );
01398         }
01399     }
01400 
01401     std::set<IdString> unifiedByName;
01402     for (PoolItemList::const_iterator iter = _items_to_keep.begin(); iter != _items_to_keep.end(); ++iter) {
01403         if (iter->status().isInstalled()) {
01404             MIL << "Keep installed item " << *iter << endl;
01405             queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE | SOLVER_WEAK );
01406             queue_push( &(_jobQueue), (*iter)->satSolvable().id() );
01407         } else {
01408             IdString ident( (*iter)->satSolvable().ident() );
01409             MIL << "Keep NOT installed name " << ident << " (" << *iter << ")" << endl;
01410             if ( unifiedByName.insert( ident ).second )
01411             {
01412               queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE_NAME | SOLVER_WEAK | MAYBE_CLEANDEPS );
01413               queue_push( &(_jobQueue), ident.id() );
01414             }
01415         }
01416     }
01417 }
01418 
01419 void SATResolver::setSystemRequirements()
01420 {
01421     CapabilitySet system_requires = SystemCheck::instance().requiredSystemCap();
01422     CapabilitySet system_conflicts = SystemCheck::instance().conflictSystemCap();
01423 
01424     for (CapabilitySet::const_iterator iter = system_requires.begin(); iter != system_requires.end(); ++iter) {
01425         queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES );
01426         queue_push( &(_jobQueue), iter->id() );
01427         MIL << "SYSTEM Requires " << *iter << endl;
01428     }
01429 
01430     for (CapabilitySet::const_iterator iter = system_conflicts.begin(); iter != system_conflicts.end(); ++iter) {
01431         queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE_PROVIDES | MAYBE_CLEANDEPS );
01432         queue_push( &(_jobQueue), iter->id() );
01433         MIL << "SYSTEM Conflicts " << *iter << endl;
01434     }
01435 
01436     // Lock the architecture of the running systems rpm
01437     // package on distupgrade.
01438     if ( _distupgrade && ZConfig::instance().systemRoot() == "/" )
01439     {
01440       ResPool pool( ResPool::instance() );
01441       IdString rpm( "rpm" );
01442       for_( it, pool.byIdentBegin(rpm), pool.byIdentEnd(rpm) )
01443       {
01444         if ( (*it)->isSystem() )
01445         {
01446           Capability archrule( (*it)->arch(), rpm.c_str(), Capability::PARSED );
01447           queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE_NAME | SOLVER_ESSENTIAL );
01448           queue_push( &(_jobQueue), archrule.id() );
01449 
01450         }
01451       }
01452     }
01453 }
01454 
01455 
01457 };// namespace detail
01460   };// namespace solver
01463 };// namespace zypp
01465 
Generated on Fri Mar 2 09:45:54 2012 for libzypp by  doxygen 1.6.3