a128c8bc76db6c449bb2000098ff55f8508481d0
[platform/upstream/libzypp.git] / zypp / sat / SATResolver.cc
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /* SATResolver.cc
3  *
4  * Copyright (C) 2000-2002 Ximian, Inc.
5  * Copyright (C) 2005 SUSE Linux Products GmbH
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License,
9  * version 2, as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19  * 02111-1307, USA.
20  */
21 #include <sstream>
22 #include "zypp/solver/detail/Helper.h"
23 #include "zypp/base/String.h"
24 #include "zypp/Capability.h"
25 #include "zypp/ResStatus.h"
26 #include "zypp/VendorAttr.h"
27 #include "zypp/base/Logger.h"
28 #include "zypp/base/String.h"
29 #include "zypp/base/Gettext.h"
30 #include "zypp/base/Algorithm.h"
31 #include "zypp/ResPool.h"
32 #include "zypp/ResFilters.h"
33 #include "zypp/ZConfig.h"
34 #include "zypp/sat/SATResolver.h"
35 #include "zypp/sat/Pool.h"
36 #include "zypp/sat/WhatProvides.h"
37 #include "zypp/solver/detail/ProblemSolutionCombi.h"
38
39 extern "C" {
40 #include "satsolver/repo_solv.h"
41 #include "satsolver/poolarch.h"
42 #include "satsolver/evr.h"
43 #include "satsolver/poolvendor.h"
44 #include "satsolver/policy.h"
45 }
46
47 /////////////////////////////////////////////////////////////////////////
48 namespace zypp
49 { ///////////////////////////////////////////////////////////////////////
50   ///////////////////////////////////////////////////////////////////////
51   namespace solver
52   { /////////////////////////////////////////////////////////////////////
53     /////////////////////////////////////////////////////////////////////
54     namespace detail
55     { ///////////////////////////////////////////////////////////////////
56
57 using namespace std;
58
59 IMPL_PTR_TYPE(SATResolver);
60
61 static PoolItemSet triggeredSolution;   // only the latest state of an item is interesting
62                                         // for the pool. Documents already inserted items.
63
64 //---------------------------------------------------------------------------
65 // Callbacks for SAT policies
66 //---------------------------------------------------------------------------
67
68 int vendorCheck (Pool *pool, Solvable *solvable1, Solvable *solvable2) {
69 //    DBG << "vendorCheck: " << id2str(pool, solvable1->vendor) << " <--> " << id2str(pool, solvable1->vendor) << endl;
70     return VendorAttr::instance().equivalent(id2str(pool, solvable1->vendor), id2str(pool, solvable2->vendor)) ? 0:1;
71 }
72
73
74 string
75 itemToString (PoolItem item, bool shortVersion)
76 {
77     ostringstream os;
78     if (!item) return "";
79
80     if (item->kind() != ResTraits<zypp::Package>::kind)
81         os << item->kind() << ':';
82     os  << item->name();
83     if (!shortVersion) {
84         os << '-' << item->edition();
85         if (item->arch() != "") {
86             os << '.' << item->arch();
87         }
88         Repository s = item->repository();
89         if (s) {
90             string alias = s.info().alias();
91             if (!alias.empty()
92                 && alias != "@system")
93             {
94                 os << '[' << s.info().alias() << ']';
95             }
96         }
97     }
98     return os.str();
99 }
100         
101
102 //---------------------------------------------------------------------------
103
104 std::ostream &
105 SATResolver::dumpOn( std::ostream & os ) const
106 {
107     return os << "<resolver/>";
108 }
109
110 //---------------------------------------------------------------------------
111
112 SATResolver::SATResolver (const ResPool & pool, Pool *SATPool)
113     : _pool (pool)
114     , _SATPool (SATPool)
115     , _solv(NULL)
116     , _fixsystem(false)
117     , _allowdowngrade(false)
118     , _allowarchchange(false)
119     , _allowvendorchange(false)
120     , _allowuninstall(false)
121     , _updatesystem(false)
122     , _allowvirtualconflicts(false)
123     , _noupdateprovide(false)
124     , _dosplitprovides(false)
125     , _onlyRequires(ZConfig::instance().solver_onlyRequires())
126
127 {
128 }
129
130
131 SATResolver::~SATResolver()
132 {
133 }
134
135 //---------------------------------------------------------------------------
136
137
138 ResPool
139 SATResolver::pool (void) const
140 {
141     return _pool;
142 }
143
144
145 void
146 SATResolver::addPoolItemToInstall (PoolItem item)
147 {
148     bool found = false;
149     for (PoolItemList::const_iterator iter = _items_to_remove.begin();
150          iter != _items_to_remove.end(); iter++) {
151         if (*iter == item) {
152             _items_to_remove.remove(*iter);
153             found = true;
154             break;
155         }
156     }
157     if (!found) {
158         _items_to_install.push_back (item);
159         _items_to_install.unique ();
160     }
161 }
162
163
164 void
165 SATResolver::addPoolItemsToInstallFromList (PoolItemList & rl)
166 {
167     for (PoolItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) {
168         addPoolItemToInstall (*iter);
169     }
170 }
171
172
173 void
174 SATResolver::addPoolItemToRemove (PoolItem item)
175 {
176     bool found = false;
177     for (PoolItemList::const_iterator iter = _items_to_install.begin();
178          iter != _items_to_install.end(); iter++) {
179         if (*iter == item) {
180             _items_to_install.remove(*iter);
181             found = true;
182             break;
183         }
184     }
185     if (!found) {
186         _items_to_remove.push_back (item);
187         _items_to_remove.unique ();
188     }
189 }
190
191
192 void
193 SATResolver::addPoolItemsToRemoveFromList (PoolItemList & rl)
194 {
195     for (PoolItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) {
196         addPoolItemToRemove (*iter);
197     }
198 }
199
200 void
201 SATResolver::addPoolItemToLock (PoolItem item)
202 {
203     _items_to_lock.push_back (item);
204     _items_to_lock.unique ();
205 }
206
207
208 //---------------------------------------------------------------------------
209
210 // copy marked item from solution back to pool
211 // if data != NULL, set as APPL_LOW (from establishPool())
212
213 static void
214 SATSolutionToPool (PoolItem item, const ResStatus & status, const ResStatus::TransactByValue causer)
215 {
216 #if 0
217     if (triggeredSolution.find(item) != triggeredSolution.end()) {
218         _XDEBUG("SATSolutionToPool(" << item << ") is already in the pool --> skip");
219         return;
220     }
221 #endif
222
223     triggeredSolution.insert(item);
224
225     // resetting transaction only
226     item.status().resetTransact (causer);
227
228     bool r;
229
230     if (status.isToBeInstalled()) {
231         r = item.status().setToBeInstalled (causer);
232         _XDEBUG("SATSolutionToPool(" << item << ", " << status << ") install !" << r);
233     }
234     else if (status.isToBeUninstalledDueToUpgrade()) {
235         r = item.status().setToBeUninstalledDueToUpgrade (causer);
236         _XDEBUG("SATSolutionToPool(" << item << ", " << status << ") upgrade !" << r);
237     }
238     else if (status.isToBeUninstalled()) {
239         r = item.status().setToBeUninstalled (causer);
240         _XDEBUG("SATSolutionToPool(" << item << ", " << status << ") remove !" << r);
241     }
242     else if (status.isRecommended()) {
243         item.status().setRecommended(true);
244         _XDEBUG("SATSolutionToPool(" << item << ", " << status << ") recommended !" << r);
245     }
246     else if (status.isSuggested()) {
247         item.status().setSuggested(true);
248         _XDEBUG("SATSolutionToPool(" << item << ", " << status << ") suggested !" << r);        
249     } else {
250         _XDEBUG("SATSolutionToPool(" << item << ", " << status << ") unchanged !");
251     }
252     return;
253 }
254
255
256 //----------------------------------------------------------------------------
257 // helper functions for distupgrade 
258 //----------------------------------------------------------------------------
259
260 bool SATResolver::doesObsoleteItem (PoolItem candidate, PoolItem installed) {
261   Solvable *sCandidate = _SATPool->solvables + candidate.satSolvable().id();
262   ::_Repo *installedRepo = sat::Pool::instance().systemRepo().get();
263   
264   Id p, *pp, obsolete, *obsoleteIt;
265   
266   if ((!installedRepo || sCandidate->repo != installedRepo) && sCandidate->obsoletes) {
267       obsoleteIt = sCandidate->repo->idarraydata + sCandidate->obsoletes;
268       while ((obsolete = *obsoleteIt++) != 0)
269       {
270           for (pp = pool_whatprovides(_SATPool, obsolete) ; (p = *pp++) != 0; ) {
271               if (p > 0 &&  installed.satSolvable().id() == (sat::detail::SolvableIdType)p) {
272                   MIL << candidate << " obsoletes " << installed << endl;
273                   return true;
274               }
275           }
276       }
277   }
278   return false;
279 }
280
281 //----------------------------------------------------------------------------
282 //----------------------------------------------------------------------------
283 // resolvePool
284 //----------------------------------------------------------------------------
285 //----------------------------------------------------------------------------
286
287 //----------------------------------------------------------------------------
288 // Helper functions for the ZYPP-Pool
289 //----------------------------------------------------------------------------
290
291
292 //------------------------------------------------------------------------------------------------------------
293 //  This function loops over the pool and grabs all items
294 //  It clears all previous bySolver() states also
295 //
296 //  Every toBeInstalled is passed to zypp::solver:detail::Resolver.addPoolItemToInstall()
297 //  Every toBeUninstalled is passed to zypp::solver:detail::Resolver.addPoolItemToRemove()
298 //
299 //  Solver results must be written back to the pool.
300 //------------------------------------------------------------------------------------------------------------
301
302
303 struct SATCollectTransact : public resfilter::PoolItemFilterFunctor
304 {
305     SATResolver & resolver;
306
307     SATCollectTransact (SATResolver & r)
308         : resolver (r)
309     { }
310
311     bool operator()( PoolItem item )            // only transacts() items go here
312     {
313         ResStatus status = item.status();
314         bool by_solver = (status.isBySolver() || status.isByApplLow());
315
316         if (by_solver) {
317             _XDEBUG("Resetting " << item );
318             item.status().resetTransact( ResStatus::APPL_LOW );// clear any solver/establish transactions
319             return true;                                // back out here, dont re-queue former solver result
320         }
321
322         if (status.isToBeInstalled()) {
323             resolver.addPoolItemToInstall(item);        // -> install!
324         }
325         else if (status.isToBeUninstalled()) {
326             resolver.addPoolItemToRemove(item);         // -> remove !
327         }
328         else if (status.isLocked()
329                  || (status.isKept()
330                      && !by_solver)) {
331             resolver.addPoolItemToLock (item);
332         }
333
334         return true;
335     }
336 };
337
338
339 //----------------------------------------------------------------------------
340 //----------------------------------------------------------------------------
341 // solving.....
342 //----------------------------------------------------------------------------
343 //----------------------------------------------------------------------------
344
345
346 class CheckIfUpdate : public resfilter::PoolItemFilterFunctor
347 {
348   public:
349     bool is_updated;
350
351     CheckIfUpdate()
352         : is_updated( false )
353     {}
354
355     // check this item will be installed
356
357     bool operator()( PoolItem item )
358     {
359         if (item.status().isToBeInstalled())
360         {
361             is_updated = true;
362             return false;
363         }
364         return true;
365     }
366 };
367
368
369 bool
370 SATResolver::resolvePool(const CapabilitySet & requires_caps,
371                          const CapabilitySet & conflict_caps)
372 {
373     SATCollectTransact info (*this);
374     
375     MIL << "SATResolver::resolvePool()" << endl;
376
377     if (_solv) {
378         // remove old stuff
379         solver_free(_solv);
380         _solv = NULL;
381         queue_free( &(_jobQueue) );
382     }
383
384     queue_init( &_jobQueue );
385     _items_to_install.clear();
386     _items_to_remove.clear();
387     _items_to_lock.clear();
388
389     invokeOnEach ( _pool.begin(), _pool.end(),
390                    functor::functorRef<bool,PoolItem>(info) );
391
392     for (PoolItemList::const_iterator iter = _items_to_install.begin(); iter != _items_to_install.end(); iter++) {
393         PoolItem r = *iter;
394
395         Id id = (*iter)->satSolvable().id();
396         if (id == ID_NULL) {
397             ERR << "Install: " << *iter << " not found" << endl;
398         }
399         MIL << "Install " << *iter << " with the SAT-Pool ID: " << id << endl;
400         queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE );
401         queue_push( &(_jobQueue), id );
402     }
403
404     for (PoolItemList::const_iterator iter = _items_to_remove.begin(); iter != _items_to_remove.end(); iter++) {
405         sat::detail::IdType ident( (*iter)->satSolvable().ident().id() );
406         MIL << "Delete " << *iter << " with the string ID: " << ident << endl;
407         queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE_NAME );
408         queue_push( &(_jobQueue), ident);
409     }
410
411     for (CapabilitySet::const_iterator iter = requires_caps.begin(); iter != requires_caps.end(); iter++) {
412         queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE_PROVIDES );
413         queue_push( &(_jobQueue), iter->id() );
414         MIL << "Requires " << *iter << endl;
415     }
416
417     for (CapabilitySet::const_iterator iter = conflict_caps.begin(); iter != conflict_caps.end(); iter++) {
418         queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE_PROVIDES);
419         queue_push( &(_jobQueue), iter->id() );
420         MIL << "Conflicts " << *iter << endl;
421     }
422
423     for (PoolItemList::const_iterator iter = _items_to_lock.begin(); iter != _items_to_lock.end(); iter++) {
424         sat::detail::SolvableIdType ident( (*iter)->satSolvable().id() );
425         if (iter->status().isInstalled()) {
426             MIL << "Lock installed item " << *iter << " with the string ID: " << ident << endl;
427             queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE );
428             queue_push( &(_jobQueue), ident );
429         } else {
430             MIL << "Lock NOT installed item " << *iter << " with the string ID: " << ident << endl;
431             queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE );
432             queue_push( &(_jobQueue), ident );
433         }
434     }
435
436     _solv = solver_create( _SATPool, sat::Pool::instance().systemRepo().get() );
437     _solv->vendorCheckCb = &vendorCheck;
438     _solv->fixsystem = _fixsystem;
439     _solv->updatesystem = _updatesystem;
440     _solv->allowdowngrade = _allowdowngrade;
441     _solv->allowuninstall = _allowuninstall;
442     _solv->allowarchchange = _allowarchchange;
443     _solv->dosplitprovides = _dosplitprovides;
444     _solv->noupdateprovide = _noupdateprovide;
445     _solv->dontinstallrecommended = _onlyRequires;
446     
447     sat::Pool::instance().prepare();
448
449     // Solve !
450     MIL << "Starting solving...." << endl;
451     solver_solve( _solv, &(_jobQueue) );
452     MIL << "....Solver end" << endl;
453
454     // copying solution back to zypp pool
455     //-----------------------------------------
456
457     if (_solv->problems.count > 0 )
458     {
459         ERR << "Solverrun finished with an ERROR" << endl;
460         return false;
461     }
462
463     /*  solvables to be installed */
464     for (int i = 0; i < _solv->decisionq.count; i++)
465     {
466       Id p;
467       p = _solv->decisionq.elements[i];
468       if (p < 0 || !sat::Solvable(p))
469         continue;
470       if (sat::Solvable(p).repository().get() == _solv->installed)
471         continue;
472
473       PoolItem poolItem = _pool.find (sat::Solvable(p));
474       if (poolItem) {
475           SATSolutionToPool (poolItem, ResStatus::toBeInstalled, ResStatus::SOLVER);
476       } else {
477           ERR << "id " << p << " not found in ZYPP pool." << endl;
478       }
479     }
480
481     /* solvables to be erased */
482     for (int i = _solv->installed->start; i < _solv->installed->start + _solv->installed->nsolvables; i++)
483     {
484       if (_solv->decisionmap[i] > 0)
485         continue;
486
487       PoolItem poolItem = _pool.find (sat::Solvable(i));
488       if (poolItem) {
489           // Check if this is an update
490           CheckIfUpdate info;
491           invokeOnEach( _pool.byIdentBegin( poolItem ),
492                         _pool.byIdentEnd( poolItem ),
493                         resfilter::ByUninstalled(),                     // ByUninstalled
494                         functor::functorRef<bool,PoolItem> (info) );
495
496           if (info.is_updated) {
497               SATSolutionToPool (poolItem, ResStatus::toBeUninstalledDueToUpgrade , ResStatus::SOLVER);
498           } else {
499               SATSolutionToPool (poolItem, ResStatus::toBeUninstalled, ResStatus::SOLVER);
500           }
501       } else {
502           ERR << "id " << i << " not found in ZYPP pool." << endl;
503       }
504     }
505
506     /*  solvables which are recommended */
507     for (int i = 0; i < _solv->recommendations.count; i++)
508     {
509       Id p;
510       p = _solv->recommendations.elements[i];
511       if (p < 0 || !sat::Solvable(p))
512         continue;
513
514       PoolItem poolItem = _pool.find (sat::Solvable(p));
515       if (poolItem) {
516           SATSolutionToPool (poolItem, ResStatus::recommended, ResStatus::SOLVER);
517       } else {
518           ERR << "id " << p << " not found in ZYPP pool." << endl;
519       }
520     }
521
522     /*  solvables which are suggested */
523     for (int i = 0; i < _solv->suggestions.count; i++)
524     {
525       Id p;
526       p = _solv->suggestions.elements[i];
527       if (p < 0 || !sat::Solvable(p))
528         continue;
529
530       PoolItem poolItem = _pool.find (sat::Solvable(p));
531       if (poolItem) {
532           SATSolutionToPool (poolItem, ResStatus::suggested, ResStatus::SOLVER);
533       } else {
534           ERR << "id " << p << " not found in ZYPP pool." << endl;
535       }
536     }
537
538     // cleanup
539     solver_free(_solv);
540     _solv = NULL;
541     queue_free( &(_jobQueue) );    
542
543     MIL << "SATResolver::resolvePool() done" << endl;
544     return true;
545 }
546
547
548 bool SATResolver::doUpdate()
549 {
550     MIL << "SATResolver::doUpdate()" << endl;
551
552     if (_solv) {
553         // remove old stuff
554         solver_free(_solv);
555         _solv = NULL;
556         queue_free( &(_jobQueue) );
557     }
558
559     queue_init( &_jobQueue );
560
561     _solv = solver_create( _SATPool, sat::Pool::instance().systemRepo().get() );
562     _solv->vendorCheckCb = &vendorCheck;
563
564     _solv->updatesystem = true;
565     _solv->dontinstallrecommended = true; // #FIXME dontinstallrecommended maybe set to false if it works correctly
566     
567     sat::Pool::instance().prepare();
568
569     // Solve !
570     MIL << "Starting solving...." << endl;
571     solver_solve( _solv, &(_jobQueue) );
572     MIL << "....Solver end" << endl;
573
574     // copying solution back to zypp pool
575     //-----------------------------------------
576
577     /*  solvables to be installed */
578     for (int i = 0; i < _solv->decisionq.count; i++)
579     {
580       Id p;
581       p = _solv->decisionq.elements[i];
582       if (p < 0 || !sat::Solvable(p))
583         continue;
584       if (sat::Solvable(p).repository().get() == _solv->installed)
585         continue;
586
587       PoolItem poolItem = _pool.find (sat::Solvable(p));
588       if (poolItem) {
589           SATSolutionToPool (poolItem, ResStatus::toBeInstalled, ResStatus::SOLVER);
590       } else {
591           ERR << "id " << p << " not found in ZYPP pool." << endl;
592       }
593     }
594
595     /* solvables to be erased */
596     for (int i = _solv->installed->start; i < _solv->installed->start + _solv->installed->nsolvables; i++)
597     {
598       if (_solv->decisionmap[i] > 0)
599         continue;
600
601       PoolItem poolItem = _pool.find (sat::Solvable(i));
602       if (poolItem) {
603           // Check if this is an update
604           CheckIfUpdate info;
605           invokeOnEach( _pool.byIdentBegin( poolItem ),
606                         _pool.byIdentEnd( poolItem ),
607                         resfilter::ByUninstalled(),                     // ByUninstalled
608                         functor::functorRef<bool,PoolItem> (info) );
609
610           if (info.is_updated) {
611               SATSolutionToPool (poolItem, ResStatus::toBeUninstalledDueToUpgrade , ResStatus::SOLVER);
612           } else {
613               SATSolutionToPool (poolItem, ResStatus::toBeUninstalled, ResStatus::SOLVER);
614           }
615       } else {
616           ERR << "id " << i << " not found in ZYPP pool." << endl;
617       }
618     }
619
620     // cleanup
621     solver_free(_solv);
622     _solv = NULL;
623     queue_free( &(_jobQueue) );    
624
625     MIL << "SATResolver::doUpdate() done" << endl;
626     return true;
627 }
628
629
630
631 //----------------------------------------------------------------------------
632 //----------------------------------------------------------------------------
633 // error handling
634 //----------------------------------------------------------------------------
635 //----------------------------------------------------------------------------
636
637 //----------------------------------------------------------------------------
638 // helper function
639 //----------------------------------------------------------------------------
640
641 struct FindPackage : public resfilter::ResObjectFilterFunctor
642 {
643     ProblemSolutionCombi *problemSolution;
644     TransactionKind action;
645     FindPackage (ProblemSolutionCombi *p, const TransactionKind act)
646        : problemSolution (p)
647          , action (act)
648     {
649     }
650
651     bool operator()( PoolItem p)
652     {
653         problemSolution->addSingleAction (p, action);
654         return true;
655     }
656 };
657
658
659 string SATResolver::SATprobleminfoString(Id problem, string &detail)
660 {
661   string ret;
662   Pool *pool = _solv->pool;
663   Id probr;
664   Id dep, source, target;
665   Solvable *s, *s2;
666
667   probr = solver_findproblemrule(_solv, problem);
668   switch (solver_problemruleinfo(_solv, &(_jobQueue), probr, &dep, &source, &target))
669   {
670       case SOLVER_PROBLEM_UPDATE_RULE:
671           s = pool_id2solvable(pool, source);
672           ret = str::form (_("problem with installed package %s"), solvable2str(pool, s));
673           break;
674       case SOLVER_PROBLEM_JOB_RULE:
675           ret = str::form (_("conflicting requests"));
676           break;
677       case SOLVER_PROBLEM_JOB_NOTHING_PROVIDES_DEP:
678           ret = str::form (_("nothing provides requested %s"), dep2str(pool, dep));
679           break;
680       case SOLVER_PROBLEM_NOT_INSTALLABLE:
681           s = pool_id2solvable(pool, source);
682           ret = str::form (_("%s is not installable"), solvable2str(pool, s));
683           break;
684       case SOLVER_PROBLEM_NOTHING_PROVIDES_DEP:
685           s = pool_id2solvable(pool, source);
686           ret = str::form (_("nothing provides %s needed by %s"), dep2str(pool, dep), solvable2str(pool, s));
687           break;
688       case SOLVER_PROBLEM_SAME_NAME:
689           s = pool_id2solvable(pool, source);
690           s2 = pool_id2solvable(pool, target);
691           ret = str::form (_("cannot install both %s and %s"), solvable2str(pool, s), solvable2str(pool, s2));
692           break;
693       case SOLVER_PROBLEM_PACKAGE_CONFLICT:
694           s = pool_id2solvable(pool, source);
695           s2 = pool_id2solvable(pool, target);
696           ret = str::form (_("%s conflicts with %s provided by %s"), solvable2str(pool, s), dep2str(pool, dep), solvable2str(pool, s2));
697           break;
698       case SOLVER_PROBLEM_PACKAGE_OBSOLETES:
699           s = pool_id2solvable(pool, source);
700           s2 = pool_id2solvable(pool, target);
701           ret = str::form (_("%s obsoletes %s provided by %s"), solvable2str(pool, s), dep2str(pool, dep), solvable2str(pool, s2));
702           break;
703       case SOLVER_PROBLEM_DEP_PROVIDERS_NOT_INSTALLABLE:
704           s = pool_id2solvable(pool, source);
705           Capability cap(dep);
706           sat::WhatProvides possibleProviders(cap);
707
708           // check, if a provider will be deleted
709           typedef list<PoolItem> ProviderList;
710           ProviderList providerlistInstalled, providerlistUninstalled;
711           for_( iter1, possibleProviders.begin(), possibleProviders.end() ) {
712               PoolItem provider1 = ResPool::instance().find( *iter1 );
713               // find pair of an installed/uninstalled item with the same NVR
714               bool found = false;
715               for_( iter2, possibleProviders.begin(), possibleProviders.end() ) {
716                   PoolItem provider2 = ResPool::instance().find( *iter2 );                
717                   if (compareByNVR (provider1.resolvable(),provider2.resolvable()) == 0
718                       && (provider1.status().isInstalled() && provider2.status().isUninstalled() 
719                           || provider2.status().isInstalled() && provider1.status().isUninstalled()))  {
720                       found = true;
721                       break;
722                   }
723               }
724               if (!found) {
725                   if (provider1.status().isInstalled())
726                       providerlistInstalled.push_back(provider1);
727                   else
728                       providerlistUninstalled.push_back(provider1);
729               }
730           }
731
732           ret = str::form (_("%s requires %s, but this requirement cannot be provided"), solvable2str(pool, s), dep2str(pool, dep));
733           if (providerlistInstalled.size() > 0) {
734               detail += _("deleted providers: ");
735               for (ProviderList::const_iterator iter = providerlistInstalled.begin(); iter != providerlistInstalled.end(); iter++) {
736                   if (iter == providerlistInstalled.begin())
737                       detail += itemToString (*iter, false);
738                   else
739                       detail += "\n                   " + itemToString (*iter, false);
740               }
741           }
742           if (providerlistUninstalled.size() > 0) {
743               if (detail.size() > 0)
744                   detail += _("\nuninstallable providers: ");
745               else
746                   detail = _("uninstallable providers: ");                
747               for (ProviderList::const_iterator iter = providerlistUninstalled.begin(); iter != providerlistUninstalled.end(); iter++) {
748                   if (iter == providerlistUninstalled.begin())
749                       detail += itemToString (*iter, false);                  
750                   else
751                       detail += "\n                   " + itemToString (*iter, false);                
752               }
753           }       
754           break;
755   }
756
757   return ret;
758 }
759
760 ResolverProblemList
761 SATResolver::problems ()
762 {
763     ResolverProblemList resolverProblems;
764     if (_solv && _solv->problems.count) {
765         Pool *pool = _solv->pool;
766         int pcnt;
767         Id p, rp, what;
768         Id problem, solution, element;
769         Solvable *s, *sd;
770
771         MIL << "Encountered problems! Here are the solutions:\n" << endl;
772         pcnt = 1;
773         problem = 0;
774         while ((problem = solver_next_problem(_solv, problem)) != 0) {
775             MIL << "Problem " <<  pcnt++ << ":" << endl;
776             MIL << "====================================" << endl;
777             string detail;
778             string whatString = SATprobleminfoString (problem,detail);
779             MIL << whatString << endl;
780             MIL << "------------------------------------" << endl;
781             ResolverProblem_Ptr resolverProblem = new ResolverProblem (whatString, detail);
782             solution = 0;
783             while ((solution = solver_next_solution(_solv, problem, solution)) != 0) {
784                 element = 0;
785                 ProblemSolutionCombi *problemSolution = new ProblemSolutionCombi(resolverProblem);
786                 while ((element = solver_next_solutionelement(_solv, problem, solution, element, &p, &rp)) != 0) {
787                     if (p == 0) {
788                         /* job, rp is index into job queue */
789                         what = _jobQueue.elements[rp];
790                         switch (_jobQueue.elements[rp-1])
791                         {
792                             case SOLVER_INSTALL_SOLVABLE: {
793                                 s = pool->solvables + what;
794                                 PoolItem poolItem = _pool.find (sat::Solvable(what));
795                                 if (poolItem) {
796                                     if (_solv->installed && s->repo == _solv->installed) {
797                                         problemSolution->addSingleAction (poolItem, REMOVE);
798                                         string description = str::form (_("do not keep %s installed"),  solvable2str(pool, s) );
799                                         MIL << description << endl;
800                                         problemSolution->addDescription (description);
801                                     } else {
802                                         problemSolution->addSingleAction (poolItem, REMOVE);
803                                         string description = str::form (_("do not install %s"), solvable2str(pool, s));
804                                         MIL << description << endl;
805                                         problemSolution->addDescription (description);
806                                     }
807                                 } else {
808                                     ERR << "SOLVER_INSTALL_SOLVABLE: No item found for " << id2str(pool, s->name) << "-"
809                                         <<  id2str(pool, s->evr) << "." <<  id2str(pool, s->arch) << endl;
810                                 }
811                             }
812                                 break;
813                             case SOLVER_ERASE_SOLVABLE: {
814                                 s = pool->solvables + what;
815                                 PoolItem poolItem = _pool.find (sat::Solvable(what));
816                                 if (poolItem) {
817                                     if (_solv->installed && s->repo == _solv->installed) {
818                                         problemSolution->addSingleAction (poolItem, KEEP);
819                                         string description = str::form (_("keep %s"), solvable2str(pool, s));
820                                         MIL << description << endl;
821                                         problemSolution->addDescription (description);
822                                     } else {
823                                         problemSolution->addSingleAction (poolItem, INSTALL);
824                                         string description = str::form (_("do not forbid installation of %s"), solvable2str(pool, s));
825                                         MIL << description << endl;
826                                         problemSolution->addDescription (description);
827                                     }
828                                 } else {
829                                     ERR << "SOLVER_ERASE_SOLVABLE: No item found for " << id2str(pool, s->name) << "-" <<  id2str(pool, s->evr) << "." <<
830                                         id2str(pool, s->arch) << endl;
831                                 }
832                             }
833                                 break;
834                             case SOLVER_INSTALL_SOLVABLE_NAME:
835                                 {
836                                 FindPackage info (problemSolution, KEEP);
837                                 IdString ident( what );
838                                 invokeOnEach( _pool.byIdentBegin( ident ),
839                                               _pool.byIdentEnd( ident ),
840                                               resfilter::ByUninstalled (),
841                                               functor::functorRef<bool,PoolItem> (info) );
842                                 string description = str::form (_("do not install %s"), ident.c_str() );
843                                 MIL << description << endl;
844                                 problemSolution->addDescription (description);
845                                 }
846                                 break;
847                             case SOLVER_ERASE_SOLVABLE_NAME:
848                                 {
849                                 FindPackage info (problemSolution, KEEP);
850                                 IdString ident( what );
851                                 invokeOnEach( _pool.byIdentBegin( ident ),
852                                               _pool.byIdentEnd( ident ),
853                                               functor::chain (resfilter::ByInstalled (),                        // ByInstalled
854                                                               resfilter::ByTransact ()),                        // will be deinstalled
855                                               functor::functorRef<bool,PoolItem> (info) );
856                                 string description = str::form (_("keep %s"), ident.c_str());
857                                 MIL << description << endl;
858                                 problemSolution->addDescription (description);
859                                 }
860                                 break;
861                             case SOLVER_INSTALL_SOLVABLE_PROVIDES:
862                                 {
863                                 Id p, *pp;
864                                 FOR_PROVIDES(p, pp, what);
865                                 {
866                                     PoolItem poolItem = _pool.find (sat::Solvable(p));
867                                     if (poolItem.status().isToBeInstalled()
868                                         || poolItem.status().staysUninstalled())
869                                         problemSolution->addSingleAction (poolItem, KEEP);
870                                 }
871                                 string description = str::form (_("do not ask to install a solvable providing %s"), dep2str(pool, what));
872                                 MIL << description << endl;
873                                 problemSolution->addDescription (description);
874                                 }
875                                 break;
876                             case SOLVER_ERASE_SOLVABLE_PROVIDES:
877                                 {
878                                 Id p, *pp;
879                                 FOR_PROVIDES(p, pp, what);
880                                 {
881                                     PoolItem poolItem = _pool.find (sat::Solvable(p));
882                                     if (poolItem.status().isToBeUninstalled()
883                                         || poolItem.status().staysInstalled())
884                                         problemSolution->addSingleAction (poolItem, KEEP);
885                                 }
886                                 string description = str::form (_("do not ask to delete all solvables providing %s"), dep2str(pool, what));
887                                 MIL << description << endl;
888                                 problemSolution->addDescription (description);
889                                 }
890                                 break;
891                             case SOLVER_INSTALL_SOLVABLE_UPDATE:
892                                 {
893                                 PoolItem poolItem = _pool.find (sat::Solvable(what));
894                                 s = pool->solvables + what;
895                                 if (poolItem) {
896                                     if (_solv->installed && s->repo == _solv->installed) {
897                                         problemSolution->addSingleAction (poolItem, KEEP);
898                                         string description = str::form (_("do not install most recent version of %s"), solvable2str(pool, s));
899                                         MIL << description << endl;
900                                         problemSolution->addDescription (description);
901                                     } else {
902                                         ERR << "SOLVER_INSTALL_SOLVABLE_UPDATE " << poolItem << " is not selected for installation" << endl;
903                                     }
904                                 } else {
905                                     ERR << "SOLVER_INSTALL_SOLVABLE_UPDATE: No item found for " << id2str(pool, s->name) << "-" <<  id2str(pool, s->evr) << "." <<
906                                         id2str(pool, s->arch) << endl;
907                                 }
908                                 }
909                                 break;
910                             default:
911                                 MIL << "- do something different" << endl;
912                                 ERR << "No valid solution available" << endl;
913                                 break;
914                         }
915                     } else {
916                         /* policy, replace p with rp */
917                         s = pool->solvables + p;
918                         sd = rp ? pool->solvables + rp : 0;
919
920                         PoolItem itemFrom = _pool.find (sat::Solvable(p));
921                         if (rp)
922                         {
923                             int gotone = 0;
924
925                             PoolItem itemTo = _pool.find (sat::Solvable(rp));
926                             if (itemFrom && itemTo) {
927                                 problemSolution->addSingleAction (itemTo, INSTALL);
928
929                                 if (evrcmp(pool, s->evr, sd->evr, EVRCMP_COMPARE ) > 0)
930                                 {
931                                     string description = str::form (_("downgrade of %s to %s"), solvable2str(pool, s), solvable2str(pool, sd));
932                                     MIL << description << endl;
933                                     problemSolution->addDescription (description);
934                                     gotone = 1;
935                                 }
936                                 if (!_solv->allowarchchange && s->name == sd->name && s->arch != sd->arch && policy_illegal_archchange(_solv, s, sd))
937                                 {
938                                     string description = str::form (_("architecture change of %s to %s"), solvable2str(pool, s), solvable2str(pool, sd));
939                                     MIL << description << endl;
940                                     problemSolution->addDescription (description);
941                                     gotone = 1;
942                                 }
943                                 if (!_solv->allowvendorchange && s->name == sd->name && s->vendor != sd->vendor && policy_illegal_vendorchange(_solv, s, sd))
944                                 {
945                                     string description = str::form (_("install %s (with vendor change)\n  %s\n-->\n  %s") ,
946                                                                     solvable2str(pool, sd) , id2str(pool, s->vendor),
947                                                                     string(sd->vendor ?  id2str(pool, sd->vendor) : " (no vendor) ").c_str() );
948                                     MIL << description << endl;
949                                     problemSolution->addDescription (description);
950                                     gotone = 1;
951                                 }
952                                 if (!gotone) {
953                                     string description = str::form (_("replacement of %s with %s"), solvable2str(pool, s), solvable2str(pool, sd));
954                                     MIL << description << endl;
955                                     problemSolution->addDescription (description);
956                                 }
957                             } else {
958                                 ERR << id2str(pool, s->name) << "-" <<  id2str(pool, s->evr) << "." <<  id2str(pool, s->arch)
959                                     << " or "  << id2str(pool, sd->name) << "-" <<  id2str(pool, sd->evr) << "." <<  id2str(pool, sd->arch) << " not found" << endl;
960                             }
961                         }
962                         else
963                         {
964                             if (itemFrom) {
965                                 string description = str::form (_("deinstallation of %s"), solvable2str(pool, s));
966                                 MIL << description << endl;
967                                 problemSolution->addDescription (description);
968                                 problemSolution->addSingleAction (itemFrom, REMOVE);
969                             }
970                         }
971                     }
972                 }
973                 resolverProblem->addSolution (problemSolution,
974                                               problemSolution->actionCount() > 1 ? true : false); // Solutions with more than 1 action will be shown first.
975                 MIL << "------------------------------------" << endl;
976             }
977             // save problem
978             resolverProblems.push_back (resolverProblem);
979         }
980     }
981     return resolverProblems;
982 }
983
984 void
985 SATResolver::applySolutions (const ProblemSolutionList & solutions)
986 {
987     for (ProblemSolutionList::const_iterator iter = solutions.begin();
988          iter != solutions.end(); ++iter) {
989         ProblemSolution_Ptr solution = *iter;
990         Resolver dummyResolver(_pool);
991         if (!solution->apply (dummyResolver))
992             break;
993     }
994 }
995
996
997
998 ///////////////////////////////////////////////////////////////////
999 };// namespace detail
1000     /////////////////////////////////////////////////////////////////////
1001     /////////////////////////////////////////////////////////////////////
1002   };// namespace solver
1003   ///////////////////////////////////////////////////////////////////////
1004   ///////////////////////////////////////////////////////////////////////
1005 };// namespace zypp
1006 /////////////////////////////////////////////////////////////////////////
1007