added doUpdate( ) which Update to newest packages
[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.isIncomplete()
243              || status.isNeeded()) {
244         r = item.status().setIncomplete();
245         _XDEBUG("SATSolutionToPool(" << item << ", " << status << ") incomplete !" << r);
246     }
247     else if (status.isUnneeded()) {
248         r = item.status().setUnneeded();
249         _XDEBUG("SATSolutionToPool(" << item << ", " << status << ") unneeded !" << r);
250     }
251     else if (status.isSatisfied()) {
252         r = item.status().setSatisfied();
253         _XDEBUG("SATSolutionToPool(" << item << ", " << status << ") satisfied !" << r);
254     }
255     else if (status.isRecommended()) {
256         item.status().setRecommended(true);
257         _XDEBUG("SATSolutionToPool(" << item << ", " << status << ") recommended !" << r);
258     }
259     else if (status.isSuggested()) {
260         item.status().setSuggested(true);
261         _XDEBUG("SATSolutionToPool(" << item << ", " << status << ") suggested !" << r);        
262     } else {
263         _XDEBUG("SATSolutionToPool(" << item << ", " << status << ") unchanged !");
264     }
265     return;
266 }
267
268
269 //----------------------------------------------------------------------------
270 // helper functions for distupgrade 
271 //----------------------------------------------------------------------------
272
273 bool SATResolver::doesObsoleteItem (PoolItem candidate, PoolItem installed) {
274   Solvable *sCandidate = _SATPool->solvables + candidate.satSolvable().id();
275   ::_Repo *installedRepo = sat::Pool::instance().systemRepo().get();
276   
277   Id p, *pp, obsolete, *obsoleteIt;
278   
279   if ((!installedRepo || sCandidate->repo != installedRepo) && sCandidate->obsoletes) {
280       obsoleteIt = sCandidate->repo->idarraydata + sCandidate->obsoletes;
281       while ((obsolete = *obsoleteIt++) != 0)
282       {
283           for (pp = pool_whatprovides(_SATPool, obsolete) ; (p = *pp++) != 0; ) {
284               if (p > 0 &&  installed.satSolvable().id() == (sat::detail::SolvableIdType)p) {
285                   MIL << candidate << " obsoletes " << installed << endl;
286                   return true;
287               }
288           }
289       }
290   }
291   return false;
292 }
293
294 //----------------------------------------------------------------------------
295 //----------------------------------------------------------------------------
296 // resolvePool
297 //----------------------------------------------------------------------------
298 //----------------------------------------------------------------------------
299
300 //----------------------------------------------------------------------------
301 // Helper functions for the ZYPP-Pool
302 //----------------------------------------------------------------------------
303
304
305 //------------------------------------------------------------------------------------------------------------
306 //  This function loops over the pool and grabs all items
307 //  It clears all previous bySolver() states also
308 //
309 //  Every toBeInstalled is passed to zypp::solver:detail::Resolver.addPoolItemToInstall()
310 //  Every toBeUninstalled is passed to zypp::solver:detail::Resolver.addPoolItemToRemove()
311 //
312 //  Solver results must be written back to the pool.
313 //------------------------------------------------------------------------------------------------------------
314
315
316 struct SATCollectTransact : public resfilter::PoolItemFilterFunctor
317 {
318     SATResolver & resolver;
319
320     SATCollectTransact (SATResolver & r)
321         : resolver (r)
322     { }
323
324     bool operator()( PoolItem item )            // only transacts() items go here
325     {
326         ResStatus status = item.status();
327         bool by_solver = (status.isBySolver() || status.isByApplLow());
328
329         if (by_solver) {
330             _XDEBUG("Resetting " << item );
331             item.status().resetTransact( ResStatus::APPL_LOW );// clear any solver/establish transactions
332             return true;                                // back out here, dont re-queue former solver result
333         }
334
335         if (status.isToBeInstalled()) {
336             resolver.addPoolItemToInstall(item);        // -> install!
337         }
338         else if (status.isToBeUninstalled()) {
339             resolver.addPoolItemToRemove(item);         // -> remove !
340         }
341         else if (status.isLocked()
342                  || (status.isKept()
343                      && !by_solver)) {
344             resolver.addPoolItemToLock (item);
345         }
346
347         return true;
348     }
349 };
350
351
352 //----------------------------------------------------------------------------
353 //----------------------------------------------------------------------------
354 // solving.....
355 //----------------------------------------------------------------------------
356 //----------------------------------------------------------------------------
357
358
359 class CheckIfUpdate : public resfilter::PoolItemFilterFunctor
360 {
361   public:
362     bool is_updated;
363
364     CheckIfUpdate()
365         : is_updated( false )
366     {}
367
368     // check this item will be installed
369
370     bool operator()( PoolItem item )
371     {
372         if (item.status().isToBeInstalled())
373         {
374             is_updated = true;
375             return false;
376         }
377         return true;
378     }
379 };
380
381
382 bool
383 SATResolver::resolvePool(const CapabilitySet & requires_caps,
384                          const CapabilitySet & conflict_caps)
385 {
386     SATCollectTransact info (*this);
387     
388     MIL << "SATResolver::resolvePool()" << endl;
389
390     if (_solv) {
391         // remove old stuff
392         solver_free(_solv);
393         _solv = NULL;
394         queue_free( &(_jobQueue) );
395     }
396
397     queue_init( &_jobQueue );
398     _items_to_install.clear();
399     _items_to_remove.clear();
400     _items_to_lock.clear();
401
402     invokeOnEach ( _pool.begin(), _pool.end(),
403                    functor::functorRef<bool,PoolItem>(info) );
404
405     for (PoolItemList::const_iterator iter = _items_to_install.begin(); iter != _items_to_install.end(); iter++) {
406         PoolItem r = *iter;
407
408         Id id = (*iter)->satSolvable().id();
409         if (id == ID_NULL) {
410             ERR << "Install: " << *iter << " not found" << endl;
411         }
412         MIL << "Install " << *iter << " with the SAT-Pool ID: " << id << endl;
413         queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE );
414         queue_push( &(_jobQueue), id );
415     }
416
417     for (PoolItemList::const_iterator iter = _items_to_remove.begin(); iter != _items_to_remove.end(); iter++) {
418         sat::detail::IdType ident( (*iter)->satSolvable().ident().id() );
419         MIL << "Delete " << *iter << " with the string ID: " << ident << endl;
420         queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE_NAME );
421         queue_push( &(_jobQueue), ident);
422     }
423
424     for (CapabilitySet::const_iterator iter = requires_caps.begin(); iter != requires_caps.end(); iter++) {
425         queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE_PROVIDES );
426         queue_push( &(_jobQueue), iter->id() );
427         MIL << "Requires " << *iter << endl;
428     }
429
430     for (CapabilitySet::const_iterator iter = conflict_caps.begin(); iter != conflict_caps.end(); iter++) {
431         queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE_PROVIDES);
432         queue_push( &(_jobQueue), iter->id() );
433         MIL << "Conflicts " << *iter << endl;
434     }
435
436     for (PoolItemList::const_iterator iter = _items_to_lock.begin(); iter != _items_to_lock.end(); iter++) {
437         sat::detail::SolvableIdType ident( (*iter)->satSolvable().id() );
438         if (iter->status().isInstalled()) {
439             MIL << "Lock installed item " << *iter << " with the string ID: " << ident << endl;
440             queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE );
441             queue_push( &(_jobQueue), ident );
442         } else {
443             MIL << "Lock NOT installed item " << *iter << " with the string ID: " << ident << endl;
444             queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE );
445             queue_push( &(_jobQueue), ident );
446         }
447     }
448
449     _solv = solver_create( _SATPool, sat::Pool::instance().systemRepo().get() );
450     _solv->vendorCheckCb = &vendorCheck;
451     _solv->fixsystem = _fixsystem;
452     _solv->updatesystem = _updatesystem;
453     _solv->allowdowngrade = _allowdowngrade;
454     _solv->allowuninstall = _allowuninstall;
455     _solv->allowarchchange = _allowarchchange;
456     _solv->dosplitprovides = _dosplitprovides;
457     _solv->noupdateprovide = _noupdateprovide;
458     _solv->dontinstallrecommended = _onlyRequires;
459     
460     sat::Pool::instance().prepare();
461
462     // Solve !
463     MIL << "Starting solving...." << endl;
464     solver_solve( _solv, &(_jobQueue) );
465     MIL << "....Solver end" << endl;
466
467     // copying solution back to zypp pool
468     //-----------------------------------------
469
470     if (_solv->problems.count > 0 )
471     {
472         ERR << "Solverrun finished with an ERROR" << endl;
473         return false;
474     }
475
476     /*  solvables to be installed */
477     for (int i = 0; i < _solv->decisionq.count; i++)
478     {
479       Id p;
480       p = _solv->decisionq.elements[i];
481       if (p < 0 || !sat::Solvable(p))
482         continue;
483       if (sat::Solvable(p).repository().get() == _solv->installed)
484         continue;
485
486       PoolItem poolItem = _pool.find (sat::Solvable(p));
487       if (poolItem) {
488           SATSolutionToPool (poolItem, ResStatus::toBeInstalled, ResStatus::SOLVER);
489       } else {
490           ERR << "id " << p << " not found in ZYPP pool." << endl;
491       }
492     }
493
494     /* solvables to be erased */
495     for (int i = _solv->installed->start; i < _solv->installed->start + _solv->installed->nsolvables; i++)
496     {
497       if (_solv->decisionmap[i] > 0)
498         continue;
499
500       PoolItem poolItem = _pool.find (sat::Solvable(i));
501       if (poolItem) {
502           // Check if this is an update
503           CheckIfUpdate info;
504           invokeOnEach( _pool.byIdentBegin( poolItem ),
505                         _pool.byIdentEnd( poolItem ),
506                         resfilter::ByUninstalled(),                     // ByUninstalled
507                         functor::functorRef<bool,PoolItem> (info) );
508
509           if (info.is_updated) {
510               SATSolutionToPool (poolItem, ResStatus::toBeUninstalledDueToUpgrade , ResStatus::SOLVER);
511           } else {
512               SATSolutionToPool (poolItem, ResStatus::toBeUninstalled, ResStatus::SOLVER);
513           }
514       } else {
515           ERR << "id " << i << " not found in ZYPP pool." << endl;
516       }
517     }
518
519     /*  solvables which are recommended */
520     for (int i = 0; i < _solv->recommendations.count; i++)
521     {
522       Id p;
523       p = _solv->recommendations.elements[i];
524       if (p < 0 || !sat::Solvable(p))
525         continue;
526
527       PoolItem poolItem = _pool.find (sat::Solvable(p));
528       if (poolItem) {
529           SATSolutionToPool (poolItem, ResStatus::recommended, ResStatus::SOLVER);
530       } else {
531           ERR << "id " << p << " not found in ZYPP pool." << endl;
532       }
533     }
534
535     /*  solvables which are suggested */
536     for (int i = 0; i < _solv->suggestions.count; i++)
537     {
538       Id p;
539       p = _solv->suggestions.elements[i];
540       if (p < 0 || !sat::Solvable(p))
541         continue;
542
543       PoolItem poolItem = _pool.find (sat::Solvable(p));
544       if (poolItem) {
545           SATSolutionToPool (poolItem, ResStatus::suggested, ResStatus::SOLVER);
546       } else {
547           ERR << "id " << p << " not found in ZYPP pool." << endl;
548       }
549     }
550
551     // cleanup
552     solver_free(_solv);
553     _solv = NULL;
554     queue_free( &(_jobQueue) );    
555
556     MIL << "SATResolver::resolvePool() done" << endl;
557     return true;
558 }
559
560
561 bool SATResolver::doUpdate()
562 {
563     MIL << "SATResolver::doUpdate()" << endl;
564
565     if (_solv) {
566         // remove old stuff
567         solver_free(_solv);
568         _solv = NULL;
569         queue_free( &(_jobQueue) );
570     }
571
572     queue_init( &_jobQueue );
573
574     _solv = solver_create( _SATPool, sat::Pool::instance().systemRepo().get() );
575     _solv->vendorCheckCb = &vendorCheck;
576
577     _solv->updatesystem = true;
578     _solv->dontinstallrecommended = true; // #FIXME dontinstallrecommended maybe set to false if it works correctly
579     
580     sat::Pool::instance().prepare();
581
582     // Solve !
583     MIL << "Starting solving...." << endl;
584     solver_solve( _solv, &(_jobQueue) );
585     MIL << "....Solver end" << endl;
586
587     // copying solution back to zypp pool
588     //-----------------------------------------
589
590     /*  solvables to be installed */
591     for (int i = 0; i < _solv->decisionq.count; i++)
592     {
593       Id p;
594       p = _solv->decisionq.elements[i];
595       if (p < 0 || !sat::Solvable(p))
596         continue;
597       if (sat::Solvable(p).repository().get() == _solv->installed)
598         continue;
599
600       PoolItem poolItem = _pool.find (sat::Solvable(p));
601       if (poolItem) {
602           SATSolutionToPool (poolItem, ResStatus::toBeInstalled, ResStatus::SOLVER);
603       } else {
604           ERR << "id " << p << " not found in ZYPP pool." << endl;
605       }
606     }
607
608     /* solvables to be erased */
609     for (int i = _solv->installed->start; i < _solv->installed->start + _solv->installed->nsolvables; i++)
610     {
611       if (_solv->decisionmap[i] > 0)
612         continue;
613
614       PoolItem poolItem = _pool.find (sat::Solvable(i));
615       if (poolItem) {
616           // Check if this is an update
617           CheckIfUpdate info;
618           invokeOnEach( _pool.byIdentBegin( poolItem ),
619                         _pool.byIdentEnd( poolItem ),
620                         resfilter::ByUninstalled(),                     // ByUninstalled
621                         functor::functorRef<bool,PoolItem> (info) );
622
623           if (info.is_updated) {
624               SATSolutionToPool (poolItem, ResStatus::toBeUninstalledDueToUpgrade , ResStatus::SOLVER);
625           } else {
626               SATSolutionToPool (poolItem, ResStatus::toBeUninstalled, ResStatus::SOLVER);
627           }
628       } else {
629           ERR << "id " << i << " not found in ZYPP pool." << endl;
630       }
631     }
632
633     // cleanup
634     solver_free(_solv);
635     _solv = NULL;
636     queue_free( &(_jobQueue) );    
637
638     MIL << "SATResolver::doUpdate() done" << endl;
639     return true;
640 }
641
642
643
644 //----------------------------------------------------------------------------
645 //----------------------------------------------------------------------------
646 // error handling
647 //----------------------------------------------------------------------------
648 //----------------------------------------------------------------------------
649
650 //----------------------------------------------------------------------------
651 // helper function
652 //----------------------------------------------------------------------------
653
654 struct FindPackage : public resfilter::ResObjectFilterFunctor
655 {
656     ProblemSolutionCombi *problemSolution;
657     TransactionKind action;
658     FindPackage (ProblemSolutionCombi *p, const TransactionKind act)
659        : problemSolution (p)
660          , action (act)
661     {
662     }
663
664     bool operator()( PoolItem p)
665     {
666         problemSolution->addSingleAction (p, action);
667         return true;
668     }
669 };
670
671
672 string SATResolver::SATprobleminfoString(Id problem, string &detail)
673 {
674   string ret;
675   Pool *pool = _solv->pool;
676   Id probr;
677   Id dep, source, target;
678   Solvable *s, *s2;
679
680   probr = solver_findproblemrule(_solv, problem);
681   switch (solver_problemruleinfo(_solv, &(_jobQueue), probr, &dep, &source, &target))
682   {
683       case SOLVER_PROBLEM_UPDATE_RULE:
684           s = pool_id2solvable(pool, source);
685           ret = str::form (_("problem with installed package %s"), solvable2str(pool, s));
686           break;
687       case SOLVER_PROBLEM_JOB_RULE:
688           ret = str::form (_("conflicting requests"));
689           break;
690       case SOLVER_PROBLEM_JOB_NOTHING_PROVIDES_DEP:
691           ret = str::form (_("nothing provides requested %s"), dep2str(pool, dep));
692           break;
693       case SOLVER_PROBLEM_NOT_INSTALLABLE:
694           s = pool_id2solvable(pool, source);
695           ret = str::form (_("%s is not installable"), solvable2str(pool, s));
696           break;
697       case SOLVER_PROBLEM_NOTHING_PROVIDES_DEP:
698           s = pool_id2solvable(pool, source);
699           ret = str::form (_("nothing provides %s needed by %s"), dep2str(pool, dep), solvable2str(pool, s));
700           break;
701       case SOLVER_PROBLEM_SAME_NAME:
702           s = pool_id2solvable(pool, source);
703           s2 = pool_id2solvable(pool, target);
704           ret = str::form (_("cannot install both %s and %s"), solvable2str(pool, s), solvable2str(pool, s2));
705           break;
706       case SOLVER_PROBLEM_PACKAGE_CONFLICT:
707           s = pool_id2solvable(pool, source);
708           s2 = pool_id2solvable(pool, target);
709           ret = str::form (_("%s conflicts with %s provided by %s"), solvable2str(pool, s), dep2str(pool, dep), solvable2str(pool, s2));
710           break;
711       case SOLVER_PROBLEM_PACKAGE_OBSOLETES:
712           s = pool_id2solvable(pool, source);
713           s2 = pool_id2solvable(pool, target);
714           ret = str::form (_("%s obsoletes %s provided by %s"), solvable2str(pool, s), dep2str(pool, dep), solvable2str(pool, s2));
715           break;
716       case SOLVER_PROBLEM_DEP_PROVIDERS_NOT_INSTALLABLE:
717           s = pool_id2solvable(pool, source);
718           Capability cap(dep);
719           sat::WhatProvides possibleProviders(cap);
720
721           // check, if a provider will be deleted
722           typedef list<PoolItem> ProviderList;
723           ProviderList providerlistInstalled, providerlistUninstalled;
724           for_( iter1, possibleProviders.begin(), possibleProviders.end() ) {
725               PoolItem provider1 = ResPool::instance().find( *iter1 );
726               // find pair of an installed/uninstalled item with the same NVR
727               bool found = false;
728               for_( iter2, possibleProviders.begin(), possibleProviders.end() ) {
729                   PoolItem provider2 = ResPool::instance().find( *iter2 );                
730                   if (compareByNVR (provider1.resolvable(),provider2.resolvable()) == 0
731                       && (provider1.status().isInstalled() && provider2.status().isUninstalled() 
732                           || provider2.status().isInstalled() && provider1.status().isUninstalled()))  {
733                       found = true;
734                       break;
735                   }
736               }
737               if (!found) {
738                   if (provider1.status().isInstalled())
739                       providerlistInstalled.push_back(provider1);
740                   else
741                       providerlistUninstalled.push_back(provider1);
742               }
743           }
744
745           ret = str::form (_("%s requires %s, but this requirement cannot be provided"), solvable2str(pool, s), dep2str(pool, dep));
746           if (providerlistInstalled.size() > 0) {
747               detail += _("deleted providers: ");
748               for (ProviderList::const_iterator iter = providerlistInstalled.begin(); iter != providerlistInstalled.end(); iter++) {
749                   if (iter == providerlistInstalled.begin())
750                       detail += itemToString (*iter, false);
751                   else
752                       detail += "\n                   " + itemToString (*iter, false);
753               }
754           }
755           if (providerlistUninstalled.size() > 0) {
756               if (detail.size() > 0)
757                   detail += _("\nuninstallable providers: ");
758               else
759                   detail = _("uninstallable providers: ");                
760               for (ProviderList::const_iterator iter = providerlistUninstalled.begin(); iter != providerlistUninstalled.end(); iter++) {
761                   if (iter == providerlistUninstalled.begin())
762                       detail += itemToString (*iter, false);                  
763                   else
764                       detail += "\n                   " + itemToString (*iter, false);                
765               }
766           }       
767           break;
768   }
769
770   return ret;
771 }
772
773 ResolverProblemList
774 SATResolver::problems ()
775 {
776     ResolverProblemList resolverProblems;
777     if (_solv && _solv->problems.count) {
778         Pool *pool = _solv->pool;
779         int pcnt;
780         Id p, rp, what;
781         Id problem, solution, element;
782         Solvable *s, *sd;
783
784         MIL << "Encountered problems! Here are the solutions:\n" << endl;
785         pcnt = 1;
786         problem = 0;
787         while ((problem = solver_next_problem(_solv, problem)) != 0) {
788             MIL << "Problem " <<  pcnt++ << ":" << endl;
789             MIL << "====================================" << endl;
790             string detail;
791             string whatString = SATprobleminfoString (problem,detail);
792             MIL << whatString << endl;
793             MIL << "------------------------------------" << endl;
794             ResolverProblem_Ptr resolverProblem = new ResolverProblem (whatString, detail);
795             solution = 0;
796             while ((solution = solver_next_solution(_solv, problem, solution)) != 0) {
797                 element = 0;
798                 ProblemSolutionCombi *problemSolution = new ProblemSolutionCombi(resolverProblem);
799                 while ((element = solver_next_solutionelement(_solv, problem, solution, element, &p, &rp)) != 0) {
800                     if (p == 0) {
801                         /* job, rp is index into job queue */
802                         what = _jobQueue.elements[rp];
803                         switch (_jobQueue.elements[rp-1])
804                         {
805                             case SOLVER_INSTALL_SOLVABLE: {
806                                 s = pool->solvables + what;
807                                 PoolItem poolItem = _pool.find (sat::Solvable(what));
808                                 if (poolItem) {
809                                     if (_solv->installed && s->repo == _solv->installed) {
810                                         problemSolution->addSingleAction (poolItem, REMOVE);
811                                         string description = str::form (_("do not keep %s installed"),  solvable2str(pool, s) );
812                                         MIL << description << endl;
813                                         problemSolution->addDescription (description);
814                                     } else {
815                                         problemSolution->addSingleAction (poolItem, REMOVE);
816                                         string description = str::form (_("do not install %s"), solvable2str(pool, s));
817                                         MIL << description << endl;
818                                         problemSolution->addDescription (description);
819                                     }
820                                 } else {
821                                     ERR << "SOLVER_INSTALL_SOLVABLE: No item found for " << id2str(pool, s->name) << "-"
822                                         <<  id2str(pool, s->evr) << "." <<  id2str(pool, s->arch) << endl;
823                                 }
824                             }
825                                 break;
826                             case SOLVER_ERASE_SOLVABLE: {
827                                 s = pool->solvables + what;
828                                 PoolItem poolItem = _pool.find (sat::Solvable(what));
829                                 if (poolItem) {
830                                     if (_solv->installed && s->repo == _solv->installed) {
831                                         problemSolution->addSingleAction (poolItem, KEEP);
832                                         string description = str::form (_("keep %s"), solvable2str(pool, s));
833                                         MIL << description << endl;
834                                         problemSolution->addDescription (description);
835                                     } else {
836                                         problemSolution->addSingleAction (poolItem, INSTALL);
837                                         string description = str::form (_("do not forbid installation of %s"), solvable2str(pool, s));
838                                         MIL << description << endl;
839                                         problemSolution->addDescription (description);
840                                     }
841                                 } else {
842                                     ERR << "SOLVER_ERASE_SOLVABLE: No item found for " << id2str(pool, s->name) << "-" <<  id2str(pool, s->evr) << "." <<
843                                         id2str(pool, s->arch) << endl;
844                                 }
845                             }
846                                 break;
847                             case SOLVER_INSTALL_SOLVABLE_NAME:
848                                 {
849                                 FindPackage info (problemSolution, KEEP);
850                                 IdString ident( what );
851                                 invokeOnEach( _pool.byIdentBegin( ident ),
852                                               _pool.byIdentEnd( ident ),
853                                               resfilter::ByUninstalled (),
854                                               functor::functorRef<bool,PoolItem> (info) );
855                                 string description = str::form (_("do not install %s"), ident.c_str() );
856                                 MIL << description << endl;
857                                 problemSolution->addDescription (description);
858                                 }
859                                 break;
860                             case SOLVER_ERASE_SOLVABLE_NAME:
861                                 {
862                                 FindPackage info (problemSolution, KEEP);
863                                 IdString ident( what );
864                                 invokeOnEach( _pool.byIdentBegin( ident ),
865                                               _pool.byIdentEnd( ident ),
866                                               functor::chain (resfilter::ByInstalled (),                        // ByInstalled
867                                                               resfilter::ByTransact ()),                        // will be deinstalled
868                                               functor::functorRef<bool,PoolItem> (info) );
869                                 string description = str::form (_("keep %s"), ident.c_str());
870                                 MIL << description << endl;
871                                 problemSolution->addDescription (description);
872                                 }
873                                 break;
874                             case SOLVER_INSTALL_SOLVABLE_PROVIDES:
875                                 {
876                                 Id p, *pp;
877                                 FOR_PROVIDES(p, pp, what);
878                                 {
879                                     PoolItem poolItem = _pool.find (sat::Solvable(p));
880                                     if (poolItem.status().isToBeInstalled()
881                                         || poolItem.status().staysUninstalled())
882                                         problemSolution->addSingleAction (poolItem, KEEP);
883                                 }
884                                 string description = str::form (_("do not ask to install a solvable providing %s"), dep2str(pool, what));
885                                 MIL << description << endl;
886                                 problemSolution->addDescription (description);
887                                 }
888                                 break;
889                             case SOLVER_ERASE_SOLVABLE_PROVIDES:
890                                 {
891                                 Id p, *pp;
892                                 FOR_PROVIDES(p, pp, what);
893                                 {
894                                     PoolItem poolItem = _pool.find (sat::Solvable(p));
895                                     if (poolItem.status().isToBeUninstalled()
896                                         || poolItem.status().staysInstalled())
897                                         problemSolution->addSingleAction (poolItem, KEEP);
898                                 }
899                                 string description = str::form (_("do not ask to delete all solvables providing %s"), dep2str(pool, what));
900                                 MIL << description << endl;
901                                 problemSolution->addDescription (description);
902                                 }
903                                 break;
904                             case SOLVER_INSTALL_SOLVABLE_UPDATE:
905                                 {
906                                 PoolItem poolItem = _pool.find (sat::Solvable(what));
907                                 s = pool->solvables + what;
908                                 if (poolItem) {
909                                     if (_solv->installed && s->repo == _solv->installed) {
910                                         problemSolution->addSingleAction (poolItem, KEEP);
911                                         string description = str::form (_("do not install most recent version of %s"), solvable2str(pool, s));
912                                         MIL << description << endl;
913                                         problemSolution->addDescription (description);
914                                     } else {
915                                         ERR << "SOLVER_INSTALL_SOLVABLE_UPDATE " << poolItem << " is not selected for installation" << endl;
916                                     }
917                                 } else {
918                                     ERR << "SOLVER_INSTALL_SOLVABLE_UPDATE: No item found for " << id2str(pool, s->name) << "-" <<  id2str(pool, s->evr) << "." <<
919                                         id2str(pool, s->arch) << endl;
920                                 }
921                                 }
922                                 break;
923                             default:
924                                 MIL << "- do something different" << endl;
925                                 ERR << "No valid solution available" << endl;
926                                 break;
927                         }
928                     } else {
929                         /* policy, replace p with rp */
930                         s = pool->solvables + p;
931                         sd = rp ? pool->solvables + rp : 0;
932
933                         PoolItem itemFrom = _pool.find (sat::Solvable(p));
934                         if (rp)
935                         {
936                             int gotone = 0;
937
938                             PoolItem itemTo = _pool.find (sat::Solvable(rp));
939                             if (itemFrom && itemTo) {
940                                 problemSolution->addSingleAction (itemTo, INSTALL);
941
942                                 if (evrcmp(pool, s->evr, sd->evr, EVRCMP_COMPARE ) > 0)
943                                 {
944                                     string description = str::form (_("downgrade of %s to %s"), solvable2str(pool, s), solvable2str(pool, sd));
945                                     MIL << description << endl;
946                                     problemSolution->addDescription (description);
947                                     gotone = 1;
948                                 }
949                                 if (!_solv->allowarchchange && s->name == sd->name && s->arch != sd->arch && policy_illegal_archchange(_solv, s, sd))
950                                 {
951                                     string description = str::form (_("architecture change of %s to %s"), solvable2str(pool, s), solvable2str(pool, sd));
952                                     MIL << description << endl;
953                                     problemSolution->addDescription (description);
954                                     gotone = 1;
955                                 }
956                                 if (!_solv->allowvendorchange && s->name == sd->name && s->vendor != sd->vendor && policy_illegal_vendorchange(_solv, s, sd))
957                                 {
958                                     string description = str::form (_("install %s (with vendor change)\n  %s\n-->\n  %s") ,
959                                                                     solvable2str(pool, sd) , id2str(pool, s->vendor),
960                                                                     string(sd->vendor ?  id2str(pool, sd->vendor) : " (no vendor) ").c_str() );
961                                     MIL << description << endl;
962                                     problemSolution->addDescription (description);
963                                     gotone = 1;
964                                 }
965                                 if (!gotone) {
966                                     string description = str::form (_("replacement of %s with %s"), solvable2str(pool, s), solvable2str(pool, sd));
967                                     MIL << description << endl;
968                                     problemSolution->addDescription (description);
969                                 }
970                             } else {
971                                 ERR << id2str(pool, s->name) << "-" <<  id2str(pool, s->evr) << "." <<  id2str(pool, s->arch)
972                                     << " or "  << id2str(pool, sd->name) << "-" <<  id2str(pool, sd->evr) << "." <<  id2str(pool, sd->arch) << " not found" << endl;
973                             }
974                         }
975                         else
976                         {
977                             if (itemFrom) {
978                                 string description = str::form (_("deinstallation of %s"), solvable2str(pool, s));
979                                 MIL << description << endl;
980                                 problemSolution->addDescription (description);
981                                 problemSolution->addSingleAction (itemFrom, REMOVE);
982                             }
983                         }
984                     }
985                 }
986                 resolverProblem->addSolution (problemSolution,
987                                               problemSolution->actionCount() > 1 ? true : false); // Solutions with more than 1 action will be shown first.
988                 MIL << "------------------------------------" << endl;
989             }
990             // save problem
991             resolverProblems.push_back (resolverProblem);
992         }
993     }
994     return resolverProblems;
995 }
996
997 void
998 SATResolver::applySolutions (const ProblemSolutionList & solutions)
999 {
1000     for (ProblemSolutionList::const_iterator iter = solutions.begin();
1001          iter != solutions.end(); ++iter) {
1002         ProblemSolution_Ptr solution = *iter;
1003         Resolver dummyResolver(_pool);
1004         if (!solution->apply (dummyResolver))
1005             break;
1006     }
1007 }
1008
1009
1010
1011 ///////////////////////////////////////////////////////////////////
1012 };// namespace detail
1013     /////////////////////////////////////////////////////////////////////
1014     /////////////////////////////////////////////////////////////////////
1015   };// namespace solver
1016   ///////////////////////////////////////////////////////////////////////
1017   ///////////////////////////////////////////////////////////////////////
1018 };// namespace zypp
1019 /////////////////////////////////////////////////////////////////////////
1020