Fix to compile with -Werror=format-security
[platform/upstream/libzypp.git] / zypp / solver / detail / 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/Pool.h"
35 #include "zypp/sat/WhatProvides.h"
36 #include "zypp/sat/WhatObsoletes.h"
37 #include "zypp/solver/detail/SATResolver.h"
38 #include "zypp/solver/detail/ProblemSolutionCombi.h"
39 #include "zypp/solver/detail/ProblemSolutionIgnore.h"
40 #include "zypp/solver/detail/SolverQueueItemInstall.h"
41 #include "zypp/solver/detail/SolverQueueItemDelete.h"
42 #include "zypp/solver/detail/SystemCheck.h"
43
44 extern "C" {
45 #include "satsolver/repo_solv.h"
46 #include "satsolver/poolarch.h"
47 #include "satsolver/evr.h"
48 #include "satsolver/poolvendor.h"
49 #include "satsolver/policy.h"
50 #include "satsolver/bitmap.h"
51 #include "satsolver/queue.h"
52 }
53
54 /////////////////////////////////////////////////////////////////////////
55 namespace zypp
56 { ///////////////////////////////////////////////////////////////////////
57   ///////////////////////////////////////////////////////////////////////
58   namespace solver
59   { /////////////////////////////////////////////////////////////////////
60     /////////////////////////////////////////////////////////////////////
61     namespace detail
62     { ///////////////////////////////////////////////////////////////////
63
64 using namespace std;
65
66 IMPL_PTR_TYPE(SATResolver);
67
68 //---------------------------------------------------------------------------
69 // Callbacks for SAT policies
70 //---------------------------------------------------------------------------
71
72 int vendorCheck (Pool *pool, Solvable *solvable1, Solvable *solvable2) {
73 //    DBG << "vendorCheck: " << id2str(pool, solvable1->vendor) << " <--> " << id2str(pool, solvable1->vendor) << endl;
74     return VendorAttr::instance().equivalent(id2str(pool, solvable1->vendor), id2str(pool, solvable2->vendor)) ? 0:1;
75 }
76
77
78 string
79 itemToString (PoolItem item, bool shortVersion)
80 {
81     ostringstream os;
82     if (!item) return "";
83
84     if (item->kind() != ResKind::package)
85         os << item->kind() << ':';
86     os  << item->name();
87     if (!shortVersion) {
88         os << '-' << item->edition();
89         if (item->arch() != "") {
90             os << '.' << item->arch();
91         }
92         Repository s = item->repository();
93         if (s) {
94             string alias = s.info().alias();
95             if (!alias.empty()
96                 && alias != "@system")
97             {
98                 os << '[' << s.info().alias() << ']';
99             }
100         }
101     }
102     return os.str();
103 }
104
105
106 //---------------------------------------------------------------------------
107
108 std::ostream &
109 SATResolver::dumpOn( std::ostream & os ) const
110 {
111     os << "<resolver>" << endl;
112     if (_solv) {
113         os << "  fixsystem = " << _solv->fixsystem << endl;
114         os << "  allowdowngrade = " << _solv->allowdowngrade << endl;
115         os << "  allowarchchange = " << _solv->allowarchchange << endl;
116         os << "  allowvendorchange = " <<  _solv->allowvendorchange << endl;
117         os << "  allowuninstall = " << _solv->allowuninstall << endl;
118         os << "  updatesystem = " << _solv->updatesystem << endl;
119         os << "  allowvirtualconflicts = " <<  _solv->allowvirtualconflicts << endl;
120         os << "  noupdateprovide = " << _solv->noupdateprovide << endl;
121         os << "  dosplitprovides = " << _solv->dosplitprovides << endl;
122         os << "  onlyRequires = " << _solv->dontinstallrecommended << endl;
123         os << "  ignorealreadyrecommended = " << _solv->ignorealreadyrecommended << endl;
124         os << "  distupgrade = " << _distupgrade << endl;
125         os << "  distupgrade_removeunsupported = " << _distupgrade_removeunsupported << endl;
126         os << "  solveSrcPackages = " << _solveSrcPackages << endl;
127     } else {
128         os << "<NULL>";
129     }
130     return os << "<resolver/>" << endl;
131 }
132
133 //---------------------------------------------------------------------------
134
135 SATResolver::SATResolver (const ResPool & pool, Pool *SATPool)
136     : _pool (pool)
137     , _SATPool (SATPool)
138     , _solv(NULL)
139     , _fixsystem(false)
140     , _allowdowngrade(false)
141     , _allowarchchange(false)
142     , _allowvendorchange(false)
143     , _allowuninstall(false)
144     , _updatesystem(false)
145     , _allowvirtualconflicts(false)
146     , _noupdateprovide(false)
147     , _dosplitprovides(false)
148     , _onlyRequires(ZConfig::instance().solver_onlyRequires())
149     , _ignorealreadyrecommended(false)
150     , _distupgrade(false)
151     , _distupgrade_removeunsupported(false)
152
153 {
154 }
155
156
157 SATResolver::~SATResolver()
158 {
159 }
160
161 //---------------------------------------------------------------------------
162
163
164 ResPool
165 SATResolver::pool (void) const
166 {
167     return _pool;
168 }
169
170
171 void
172 SATResolver::resetItemTransaction (PoolItem item)
173 {
174     bool found = false;
175     for (PoolItemList::const_iterator iter = _items_to_remove.begin();
176          iter != _items_to_remove.end(); ++iter) {
177         if (*iter == item) {
178             _items_to_remove.remove(*iter);
179             found = true;
180             break;
181         }
182     }
183     if (!found) {
184         for (PoolItemList::const_iterator iter = _items_to_install.begin();
185              iter != _items_to_install.end(); ++iter) {
186             if (*iter == item) {
187                 _items_to_install.remove(*iter);
188                 found = true;
189                 break;
190             }
191         }
192     }
193     if (!found) {
194         for (PoolItemList::const_iterator iter = _items_to_keep.begin();
195              iter != _items_to_keep.end(); ++iter) {
196             if (*iter == item) {
197                 _items_to_keep.remove(*iter);
198                 found = true;
199                 break;
200             }
201         }
202     }
203     if (!found) {
204         for (PoolItemList::const_iterator iter = _items_to_lock.begin();
205              iter != _items_to_lock.end(); ++iter) {
206             if (*iter == item) {
207                 _items_to_lock.remove(*iter);
208                 found = true;
209                 break;
210             }
211         }
212     }
213 }
214
215
216 void
217 SATResolver::addPoolItemToInstall (PoolItem item)
218 {
219     resetItemTransaction (item);
220     _items_to_install.push_back (item);
221     _items_to_install.unique ();
222 }
223
224
225 void
226 SATResolver::addPoolItemsToInstallFromList (PoolItemList & rl)
227 {
228     for (PoolItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) {
229         addPoolItemToInstall (*iter);
230     }
231 }
232
233
234 void
235 SATResolver::addPoolItemToRemove (PoolItem item)
236 {
237     resetItemTransaction (item);
238     _items_to_remove.push_back (item);
239     _items_to_remove.unique ();
240 }
241
242
243 void
244 SATResolver::addPoolItemsToRemoveFromList (PoolItemList & rl)
245 {
246     for (PoolItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) {
247         addPoolItemToRemove (*iter);
248     }
249 }
250
251 void
252 SATResolver::addPoolItemToLock (PoolItem item)
253 {
254     resetItemTransaction (item);
255     _items_to_lock.push_back (item);
256     _items_to_lock.unique ();
257 }
258
259 void
260 SATResolver::addPoolItemToKeep (PoolItem item)
261 {
262     resetItemTransaction (item);
263     _items_to_keep.push_back (item);
264     _items_to_keep.unique ();
265 }
266
267 //---------------------------------------------------------------------------
268
269 // copy marked item from solution back to pool
270 // if data != NULL, set as APPL_LOW (from establishPool())
271
272 static void
273 SATSolutionToPool (PoolItem item, const ResStatus & status, const ResStatus::TransactByValue causer)
274 {
275     // resetting
276     item.status().resetTransact (causer);
277     item.status().resetWeak ();
278
279     bool r;
280
281     // installation/deletion
282     if (status.isToBeInstalled()) {
283         r = item.status().setToBeInstalled (causer);
284         _XDEBUG("SATSolutionToPool install returns " << item << ", " << r);
285     }
286     else if (status.isToBeUninstalledDueToUpgrade()) {
287         r = item.status().setToBeUninstalledDueToUpgrade (causer);
288         _XDEBUG("SATSolutionToPool upgrade returns " << item << ", " <<  r);
289     }
290     else if (status.isToBeUninstalled()) {
291         r = item.status().setToBeUninstalled (causer);
292         _XDEBUG("SATSolutionToPool remove returns " << item << ", " <<  r);
293     }
294
295     return;
296 }
297
298 //----------------------------------------------------------------------------
299 //----------------------------------------------------------------------------
300 // resolvePool
301 //----------------------------------------------------------------------------
302 //----------------------------------------------------------------------------
303
304 //----------------------------------------------------------------------------
305 // Helper functions for the ZYPP-Pool
306 //----------------------------------------------------------------------------
307
308
309 //------------------------------------------------------------------------------------------------------------
310 //  This function loops over the pool and grabs all items
311 //  It clears all previous bySolver() states also
312 //
313 //  Every toBeInstalled is passed to zypp::solver:detail::Resolver.addPoolItemToInstall()
314 //  Every toBeUninstalled is passed to zypp::solver:detail::Resolver.addPoolItemToRemove()
315 //
316 //  Solver results must be written back to the pool.
317 //------------------------------------------------------------------------------------------------------------
318
319
320 struct SATCollectTransact : public resfilter::PoolItemFilterFunctor
321 {
322     SATResolver & resolver;
323
324     SATCollectTransact (SATResolver & r)
325         : resolver (r)
326     { }
327
328     bool operator()( PoolItem item )            // only transacts() items go here
329     {
330         ResStatus status = item.status();
331         bool by_solver = (status.isBySolver() || status.isByApplLow());
332
333         if (by_solver) {
334             item.status().resetTransact( ResStatus::APPL_LOW );// clear any solver/establish transactions
335             return true;                                // back out here, dont re-queue former solver result
336         }
337
338         if ( item.satSolvable().isKind<SrcPackage>() && ! resolver.solveSrcPackages() )
339         {
340           // Later we may continue on a per source package base.
341           return true; // dont process this source package.
342         }
343
344         if (status.isToBeInstalled()) {
345             resolver.addPoolItemToInstall(item);        // -> install!
346         }
347         else if (status.isToBeUninstalled()) {
348             resolver.addPoolItemToRemove(item);         // -> remove !
349         }
350         else if (status.isLocked()
351                  && !by_solver) {
352             resolver.addPoolItemToLock (item);
353         }
354         else if (status.isKept()
355                  && !by_solver) {
356             resolver.addPoolItemToKeep (item);
357         }
358
359         return true;
360     }
361 };
362
363
364 //----------------------------------------------------------------------------
365 //----------------------------------------------------------------------------
366 // solving.....
367 //----------------------------------------------------------------------------
368 //----------------------------------------------------------------------------
369
370
371 class CheckIfUpdate : public resfilter::PoolItemFilterFunctor
372 {
373   public:
374     bool is_updated;
375
376     CheckIfUpdate()
377         : is_updated( false )
378     {}
379
380     // check this item will be installed
381
382     bool operator()( PoolItem item )
383     {
384         if (item.status().isToBeInstalled())
385         {
386             is_updated = true;
387             return false;
388         }
389         return true;
390     }
391 };
392
393
394 class CollectNonePackages : public resfilter::PoolItemFilterFunctor
395 {
396   public:
397     Queue *solvableQueue;
398
399     CollectNonePackages( Queue *queue )
400         :solvableQueue (queue)
401     {}
402
403     // collecting none packges
404
405     bool operator()( PoolItem item )
406     {
407         queue_push(solvableQueue, item.satSolvable().id());
408         return true;
409     }
410 };
411
412 bool
413 SATResolver::solving(const CapabilitySet & requires_caps,
414                      const CapabilitySet & conflict_caps)
415 {
416     _solv = solver_create( _SATPool );
417     _solv->vendorCheckCb = &vendorCheck;
418     _solv->fixsystem = _fixsystem;
419     _solv->ignorealreadyrecommended = _ignorealreadyrecommended;
420     _solv->updatesystem = _updatesystem;
421     _solv->allowdowngrade = _allowdowngrade;
422     _solv->allowuninstall = _allowuninstall;
423     _solv->allowarchchange = _allowarchchange;
424     _solv->allowvendorchange = _allowvendorchange;
425     _solv->allowvirtualconflicts = _allowvirtualconflicts;
426     _solv->dosplitprovides = _dosplitprovides;
427     _solv->noupdateprovide = _noupdateprovide;
428     _solv->dontinstallrecommended = _onlyRequires;
429     _solv->distupgrade = _distupgrade;
430     _solv->distupgrade_removeunsupported = _distupgrade_removeunsupported;
431
432     sat::Pool::instance().prepare();
433
434     // Solve !
435     MIL << "Starting solving...." << endl;
436     MIL << *this;
437     solver_solve( _solv, &(_jobQueue) );
438     MIL << "....Solver end" << endl;
439
440     // copying solution back to zypp pool
441     //-----------------------------------------
442     _result_items_to_install.clear();
443     _result_items_to_remove.clear();
444
445     /*  solvables to be installed */
446     for (int i = 0; i < _solv->decisionq.count; i++)
447     {
448       Id p;
449       p = _solv->decisionq.elements[i];
450       if (p < 0 || !sat::Solvable(p) || sat::Solvable(p).isSystem())
451         continue;
452
453       PoolItem poolItem((sat::Solvable(p)));
454       if (poolItem) {
455           SATSolutionToPool (poolItem, ResStatus::toBeInstalled, ResStatus::SOLVER);
456           _result_items_to_install.push_back (poolItem);
457       } else {
458           ERR << "id " << p << " not found in ZYPP pool." << endl;
459       }
460     }
461
462     /* solvables to be erased */
463     Repository systemRepo( sat::Pool::instance().findSystemRepo() ); // don't create if it does not exist
464     if ( systemRepo && ! systemRepo.solvablesEmpty() )
465     {
466       bool mustCheckObsoletes = false;
467       for_( it, systemRepo.solvablesBegin(), systemRepo.solvablesEnd() )
468       {
469         if (_solv->decisionmap[it->id()] > 0)
470           continue;
471
472         PoolItem poolItem( *it );
473         // Check if this is an update
474         CheckIfUpdate info;
475         invokeOnEach( _pool.byIdentBegin( poolItem ),
476                       _pool.byIdentEnd( poolItem ),
477                       resfilter::ByUninstalled(),                       // ByUninstalled
478                       functor::functorRef<bool,PoolItem> (info) );
479
480         if (info.is_updated) {
481           SATSolutionToPool( poolItem, ResStatus::toBeUninstalledDueToUpgrade, ResStatus::SOLVER );
482         } else {
483           SATSolutionToPool( poolItem, ResStatus::toBeUninstalled, ResStatus::SOLVER );
484           if ( ! mustCheckObsoletes )
485             mustCheckObsoletes = true; // lazy check for UninstalledDueToObsolete
486         }
487         _result_items_to_remove.push_back (poolItem);
488       }
489       if ( mustCheckObsoletes )
490       {
491         sat::WhatObsoletes obsoleted( _result_items_to_install.begin(), _result_items_to_install.end() );
492         for_( it, obsoleted.poolItemBegin(), obsoleted.poolItemEnd() )
493         {
494           ResStatus & status( it->status() );
495           // WhatObsoletes contains installed items only!
496           if ( status.transacts() && ! status.isToBeUninstalledDueToUpgrade() )
497             status.setToBeUninstalledDueToObsolete();
498         }
499       }
500     }
501     /*  solvables which are recommended */
502     for (int i = 0; i < _solv->recommendations.count; i++)
503     {
504       Id p;
505       p = _solv->recommendations.elements[i];
506       if (p < 0 || !sat::Solvable(p))
507         continue;
508
509       PoolItem poolItem = _pool.find (sat::Solvable(p));
510       if (poolItem) {
511           poolItem.status().setRecommended(true);
512           _XDEBUG("SATSolutionToPool(" << poolItem << ") recommended !");
513       } else {
514           ERR << "id " << p << " not found in ZYPP pool." << endl;
515       }
516     }
517
518     /*  solvables which are suggested */
519     for (int i = 0; i < _solv->suggestions.count; i++)
520     {
521       Id p;
522       p = _solv->suggestions.elements[i];
523       if (p < 0 || !sat::Solvable(p))
524         continue;
525
526       PoolItem poolItem = _pool.find (sat::Solvable(p));
527       if (poolItem) {
528           poolItem.status().setSuggested(true);
529           _XDEBUG("SATSolutionToPool(" << poolItem << ") suggested !");
530       } else {
531           ERR << "id " << p << " not found in ZYPP pool." << endl;
532       }
533     }
534
535     _problem_items.clear();
536     /*  solvables which are no longer supported */
537     for (int i = 0; i < _solv->orphaned.count; i++)
538     {
539         Id p;
540         p = _solv->orphaned.elements[i];
541         if (p < 0 || !sat::Solvable(p))
542             continue;
543
544         PoolItem poolItem = _pool.find (sat::Solvable(p));
545         if (poolItem) {
546             _problem_items.push_back(poolItem);
547             _XDEBUG( poolItem << " orphaned !");
548         } else {
549             ERR << "id " << p << " not found in ZYPP pool." << endl;
550         }
551     }
552
553     /* Write validation state back to pool */
554     Queue flags, solvableQueue;
555
556     queue_init(&flags);
557     queue_init(&solvableQueue);
558
559     CollectNonePackages collectNonePackages(&solvableQueue);
560     invokeOnEach( _pool.begin(),
561                   _pool.end(),
562                   functor::not_c(resfilter::byKind<Package>()), // every solvable BUT packages
563                   functor::functorRef<bool,PoolItem> (collectNonePackages) );
564     solver_trivial_installable(_solv, &solvableQueue, &flags );
565     for (int i = 0; i < solvableQueue.count; i++) {
566         PoolItem item = _pool.find (sat::Solvable(solvableQueue.elements[i]));
567         item.status().setUndetermined();
568
569         if (flags.elements[i] == -1) {
570             item.status().setNonRelevant();
571             _XDEBUG("SATSolutionToPool(" << item << " ) nonRelevant !");
572         } else if (flags.elements[i] == 1) {
573             item.status().setSatisfied();
574             _XDEBUG("SATSolutionToPool(" << item << " ) satisfied !");
575         } else if (flags.elements[i] == 0) {
576             item.status().setBroken();
577             _XDEBUG("SATSolutionToPool(" << item << " ) broken !");
578         }
579     }
580
581     // Solvables which were selected due requirements which have been made by the user will
582     // be selected by APPL_LOW. We can't use any higher level, because this setting must
583     // not serve as a request for the next solver run. APPL_LOW is reset before solving.
584     for (CapabilitySet::const_iterator iter = requires_caps.begin(); iter != requires_caps.end(); iter++) {
585         sat::WhatProvides rpmProviders(*iter);
586         for_( iter2, rpmProviders.begin(), rpmProviders.end() ) {
587             PoolItem poolItem(*iter2);
588             if (poolItem.status().isToBeInstalled()) {
589                 MIL << "User requirement " << *iter << " sets " << poolItem << endl;
590                 poolItem.status().setTransactByValue (ResStatus::APPL_LOW);
591             }
592         }
593     }
594     for (CapabilitySet::const_iterator iter = conflict_caps.begin(); iter != conflict_caps.end(); iter++) {
595         sat::WhatProvides rpmProviders(*iter);
596         for_( iter2, rpmProviders.begin(), rpmProviders.end() ) {
597             PoolItem poolItem(*iter2);
598             if (poolItem.status().isToBeUninstalled()) {
599                 MIL << "User conflict " << *iter << " sets " << poolItem << endl;
600                 poolItem.status().setTransactByValue (ResStatus::APPL_LOW);
601             }
602         }
603     }
604
605     if (_solv->problems.count > 0 )
606     {
607         ERR << "Solverrun finished with an ERROR" << endl;
608         return false;
609     }
610
611     queue_free(&(solvableQueue));
612     queue_free(&flags);
613
614     return true;
615 }
616
617
618 void
619 SATResolver::solverInit(const PoolItemList & weakItems)
620 {
621     SATCollectTransact info (*this);
622
623     MIL << "SATResolver::solverInit()" << endl;
624
625     if (_solv) {
626         // remove old stuff
627         solver_free(_solv);
628         _solv = NULL;
629         queue_free( &(_jobQueue) );
630     }
631
632     queue_init( &_jobQueue );
633     _items_to_install.clear();
634     _items_to_remove.clear();
635     _items_to_lock.clear();
636     _items_to_keep.clear();
637
638     invokeOnEach ( _pool.begin(), _pool.end(),
639                    functor::functorRef<bool,PoolItem>(info) );
640
641     for (PoolItemList::const_iterator iter = weakItems.begin(); iter != weakItems.end(); iter++) {
642         Id id = (*iter)->satSolvable().id();
643         if (id == ID_NULL) {
644             ERR << "Weaken: " << *iter << " not found" << endl;
645         }
646         MIL << "Weaken dependencies of " << *iter << endl;
647         queue_push( &(_jobQueue), SOLVER_WEAKEN_SOLVABLE_DEPS );
648         queue_push( &(_jobQueue), id );
649     }
650
651     // Add rules for parallel installable resolvables with different versions
652     std::set<IdString> parallel = ZConfig::instance().multiversion();
653     for (std::set<IdString>::const_iterator it = parallel.begin(); it != parallel.end(); ++it) {
654         queue_push( &(_jobQueue), SOLVER_NOOBSOLETES_SOLVABLE_NAME );
655         queue_push( &(_jobQueue), it->id() );
656     }
657 }
658
659 void
660 SATResolver::solverEnd()
661 {
662     // cleanup
663     solver_free(_solv);
664     _solv = NULL;
665     queue_free( &(_jobQueue) );
666 }
667
668
669 bool
670 SATResolver::resolvePool(const CapabilitySet & requires_caps,
671                          const CapabilitySet & conflict_caps,
672                          const PoolItemList & weakItems)
673 {
674     MIL << "SATResolver::resolvePool()" << endl;
675
676     // initialize
677     solverInit(weakItems);
678
679     for (PoolItemList::const_iterator iter = _items_to_install.begin(); iter != _items_to_install.end(); iter++) {
680         Id id = (*iter)->satSolvable().id();
681         if (id == ID_NULL) {
682             ERR << "Install: " << *iter << " not found" << endl;
683         } else {
684             MIL << "Install " << *iter << endl;
685             queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE );
686             queue_push( &(_jobQueue), id );
687         }
688     }
689
690     for (PoolItemList::const_iterator iter = _items_to_remove.begin(); iter != _items_to_remove.end(); iter++) {
691         Id id = (*iter)->satSolvable().id();
692         if (id == ID_NULL) {
693             ERR << "Delete: " << *iter << " not found" << endl;
694         } else {
695             MIL << "Delete " << *iter << endl;
696             queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE );
697             queue_push( &(_jobQueue), id);
698         }
699     }
700
701     for (CapabilitySet::const_iterator iter = requires_caps.begin(); iter != requires_caps.end(); iter++) {
702         queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE_PROVIDES );
703         queue_push( &(_jobQueue), iter->id() );
704         MIL << "Requires " << *iter << endl;
705     }
706
707     for (CapabilitySet::const_iterator iter = conflict_caps.begin(); iter != conflict_caps.end(); iter++) {
708         queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE_PROVIDES);
709         queue_push( &(_jobQueue), iter->id() );
710         MIL << "Conflicts " << *iter << endl;
711     }
712
713     // set requirements for a running system
714     setSystemRequirements();
715
716     // set locks for the solver
717     setLocks();
718
719     // solving
720     bool ret = solving(requires_caps, conflict_caps);
721     // cleanup
722     if (ret)
723         solverEnd(); // remove solver only if no errors happend. Need it for solving problems
724
725     (ret?MIL:WAR) << "SATResolver::resolvePool() done. Ret:" << ret <<  endl;
726     return ret;
727 }
728
729
730 bool
731 SATResolver::resolveQueue(const SolverQueueItemList &requestQueue,
732                           const PoolItemList & weakItems)
733 {
734     MIL << "SATResolver::resolvQueue()" << endl;
735
736     // initialize
737     solverInit(weakItems);
738
739     // generate solver queue
740     for (SolverQueueItemList::const_iterator iter = requestQueue.begin(); iter != requestQueue.end(); iter++) {
741         (*iter)->addRule(_jobQueue);
742     }
743
744     // Add addition item status to the resolve-queue cause these can be set by problem resolutions
745     for (PoolItemList::const_iterator iter = _items_to_install.begin(); iter != _items_to_install.end(); iter++) {
746         Id id = (*iter)->satSolvable().id();
747         if (id == ID_NULL) {
748             ERR << "Install: " << *iter << " not found" << endl;
749         } else {
750             MIL << "Install " << *iter << endl;
751             queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE );
752             queue_push( &(_jobQueue), id );
753         }
754     }
755     for (PoolItemList::const_iterator iter = _items_to_remove.begin(); iter != _items_to_remove.end(); iter++) {
756         sat::detail::IdType ident( (*iter)->satSolvable().ident().id() );
757         MIL << "Delete " << *iter << ident << endl;
758         queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE_NAME );
759         queue_push( &(_jobQueue), ident);
760     }
761
762     // set requirements for a running system
763     setSystemRequirements();
764
765     // set locks for the solver
766     setLocks();
767
768     // solving
769     bool ret = solving();
770
771     // cleanup
772     if (ret)
773         solverEnd(); // remove solver only if no errors happend. Need it for solving problems
774
775     MIL << "SATResolver::resolveQueue() done. Ret:" << ret <<  endl;
776     return ret;
777 }
778
779
780 void SATResolver::doUpdate()
781 {
782     MIL << "SATResolver::doUpdate()" << endl;
783
784     // initialize
785     solverInit(PoolItemList());
786
787     // set requirements for a running system
788     setSystemRequirements();
789
790     // set locks for the solver
791     setLocks();
792
793     _solv = solver_create( _SATPool );
794     _solv->vendorCheckCb = &vendorCheck;
795
796     _solv->updatesystem = true;
797     _solv->dontinstallrecommended = true; // #FIXME dontinstallrecommended maybe set to false if it works correctly
798
799     sat::Pool::instance().prepare();
800
801     // Solve !
802     MIL << "Starting solving for update...." << endl;
803     MIL << *this;
804     solver_solve( _solv, &(_jobQueue) );
805     MIL << "....Solver end" << endl;
806
807     // copying solution back to zypp pool
808     //-----------------------------------------
809
810     /*  solvables to be installed */
811     for (int i = 0; i < _solv->decisionq.count; i++)
812     {
813       Id p;
814       p = _solv->decisionq.elements[i];
815       if (p < 0 || !sat::Solvable(p))
816         continue;
817       if (sat::Solvable(p).repository().get() == _solv->installed)
818         continue;
819
820       PoolItem poolItem = _pool.find (sat::Solvable(p));
821       if (poolItem) {
822           SATSolutionToPool (poolItem, ResStatus::toBeInstalled, ResStatus::SOLVER);
823       } else {
824           ERR << "id " << p << " not found in ZYPP pool." << endl;
825       }
826     }
827
828     /* solvables to be erased */
829     for (int i = _solv->installed->start; i < _solv->installed->start + _solv->installed->nsolvables; i++)
830     {
831       if (_solv->decisionmap[i] > 0)
832         continue;
833
834       PoolItem poolItem = _pool.find (sat::Solvable(i));
835       if (poolItem) {
836           // Check if this is an update
837           CheckIfUpdate info;
838           invokeOnEach( _pool.byIdentBegin( poolItem ),
839                         _pool.byIdentEnd( poolItem ),
840                         resfilter::ByUninstalled(),                     // ByUninstalled
841                         functor::functorRef<bool,PoolItem> (info) );
842
843           if (info.is_updated) {
844               SATSolutionToPool (poolItem, ResStatus::toBeUninstalledDueToUpgrade , ResStatus::SOLVER);
845           } else {
846               SATSolutionToPool (poolItem, ResStatus::toBeUninstalled, ResStatus::SOLVER);
847           }
848       } else {
849           ERR << "id " << i << " not found in ZYPP pool." << endl;
850       }
851     }
852
853     // cleanup
854     solverEnd();
855
856     MIL << "SATResolver::doUpdate() done" << endl;
857 }
858
859
860
861 //----------------------------------------------------------------------------
862 //----------------------------------------------------------------------------
863 // error handling
864 //----------------------------------------------------------------------------
865 //----------------------------------------------------------------------------
866
867 //----------------------------------------------------------------------------
868 // helper function
869 //----------------------------------------------------------------------------
870
871 struct FindPackage : public resfilter::ResObjectFilterFunctor
872 {
873     ProblemSolutionCombi *problemSolution;
874     TransactionKind action;
875     FindPackage (ProblemSolutionCombi *p, const TransactionKind act)
876        : problemSolution (p)
877        , action (act)
878         {
879         }
880
881     bool operator()( PoolItem p)
882    {
883        problemSolution->addSingleAction (p, action);
884        return true;
885    }
886 };
887
888
889 //----------------------------------------------------------------------------
890 // Checking if this solvable/item has a buddy which reflect the real
891 // user visible description of an item
892 // e.g. The release package has a buddy to the concerning product item.
893 // This user want's the message "Product foo conflicts with product bar" and
894 // NOT "package release-foo conflicts with package release-bar"
895 //----------------------------------------------------------------------------
896
897
898 PoolItem SATResolver::mapItem (const PoolItem &item)
899 {
900     sat::Solvable buddy = item.buddy();
901     if (buddy != sat::Solvable())
902     {
903         return _pool.find (buddy);
904     }
905     else
906     {
907         return item;
908     }
909 }
910
911 sat::Solvable SATResolver::mapSolvable (const Id &id)
912 {
913     PoolItem item = _pool.find (sat::Solvable(id));
914     return mapItem(item).satSolvable();
915 }
916
917 string SATResolver::SATprobleminfoString(Id problem, string &detail, Id &ignoreId)
918 {
919   string ret;
920   Pool *pool = _solv->pool;
921   Id probr;
922   Id dep, source, target;
923   sat::Solvable s, s2;
924
925   ignoreId = 0;
926   probr = solver_findproblemrule(_solv, problem);
927   switch (solver_problemruleinfo(_solv, &(_jobQueue), probr, &dep, &source, &target))
928   {
929       case SOLVER_PROBLEM_DISTUPGRADE_RULE:
930           s = mapSolvable (source);
931           ret = str::form (_("%s does not belong to a distupgrade repository"), solvable2str(pool, s.get()));
932           break;
933       case SOLVER_PROBLEM_INFARCH_RULE:
934           s = mapSolvable (source);
935           ret = str::form (_("%s has inferior architecture"), solvable2str(pool, s.get()));
936           break;
937       case SOLVER_PROBLEM_UPDATE_RULE:
938           s = mapSolvable (source);
939           ret = str::form (_("problem with installed package %s"), solvable2str(pool, s.get()));
940           break;
941       case SOLVER_PROBLEM_JOB_RULE:
942           ret = _("conflicting requests");
943           break;
944       case SOLVER_PROBLEM_RPM_RULE:
945           ret = _("some dependency problem");
946           break;
947       case SOLVER_PROBLEM_JOB_NOTHING_PROVIDES_DEP:
948           ret = str::form (_("nothing provides requested %s"), dep2str(pool, dep));
949           detail += _("Have you enabled all requested repositories?");
950           break;
951       case SOLVER_PROBLEM_NOT_INSTALLABLE:
952           s = mapSolvable (source);
953           ret = str::form (_("%s is not installable"), solvable2str(pool, s.get()));
954           break;
955       case SOLVER_PROBLEM_NOTHING_PROVIDES_DEP:
956           s = mapSolvable (source);
957           ret = str::form (_("nothing provides %s needed by %s"), dep2str(pool, dep), solvable2str(pool, s.get()));
958           break;
959       case SOLVER_PROBLEM_SAME_NAME:
960           s = mapSolvable (source);
961           s2 = mapSolvable (target);
962           ret = str::form (_("cannot install both %s and %s"), solvable2str(pool, s.get()), solvable2str(pool, s2.get()));
963           break;
964       case SOLVER_PROBLEM_PACKAGE_CONFLICT:
965           s = mapSolvable (source);
966           s2 = mapSolvable (target);
967           ret = str::form (_("%s conflicts with %s provided by %s"), solvable2str(pool, s.get()), dep2str(pool, dep), solvable2str(pool, s2.get()));
968           break;
969       case SOLVER_PROBLEM_PACKAGE_OBSOLETES:
970           s = mapSolvable (source);
971           s2 = mapSolvable (target);
972           ret = str::form (_("%s obsoletes %s provided by %s"), solvable2str(pool, s.get()), dep2str(pool, dep), solvable2str(pool, s2.get()));
973           break;
974       case SOLVER_PROBLEM_SELF_CONFLICT:
975           s = mapSolvable (source);
976           ret = str::form (_("solvable %s conflicts with %s provided by itself"), solvable2str(pool, s.get()), dep2str(pool, dep));
977           break;
978       case SOLVER_PROBLEM_DEP_PROVIDERS_NOT_INSTALLABLE:
979           ignoreId = source; // for setting weak dependencies
980           s = mapSolvable (source);
981           Capability cap(dep);
982           sat::WhatProvides possibleProviders(cap);
983
984           // check, if a provider will be deleted
985           typedef list<PoolItem> ProviderList;
986           ProviderList providerlistInstalled, providerlistUninstalled;
987           for_( iter1, possibleProviders.begin(), possibleProviders.end() ) {
988               PoolItem provider1 = ResPool::instance().find( *iter1 );
989               // find pair of an installed/uninstalled item with the same NVR
990               bool found = false;
991               for_( iter2, possibleProviders.begin(), possibleProviders.end() ) {
992                   PoolItem provider2 = ResPool::instance().find( *iter2 );
993                   if (compareByNVR (provider1.resolvable(),provider2.resolvable()) == 0
994                       && ( (provider1.status().isInstalled() && provider2.status().isUninstalled())
995                           || (provider2.status().isInstalled() && provider1.status().isUninstalled()) ))  {
996                       found = true;
997                       break;
998                   }
999               }
1000               if (!found) {
1001                   if (provider1.status().isInstalled())
1002                       providerlistInstalled.push_back(provider1);
1003                   else
1004                       providerlistUninstalled.push_back(provider1);
1005               }
1006           }
1007
1008           ret = str::form (_("%s requires %s, but this requirement cannot be provided"), solvable2str(pool, s.get()), dep2str(pool, dep));
1009           if (providerlistInstalled.size() > 0) {
1010               detail += _("deleted providers: ");
1011               for (ProviderList::const_iterator iter = providerlistInstalled.begin(); iter != providerlistInstalled.end(); iter++) {
1012                   if (iter == providerlistInstalled.begin())
1013                       detail += itemToString (*iter, false);
1014                   else
1015                       detail += "\n                   " + itemToString (mapItem(*iter), false);
1016               }
1017           }
1018           if (providerlistUninstalled.size() > 0) {
1019               if (detail.size() > 0)
1020                   detail += _("\nuninstallable providers: ");
1021               else
1022                   detail = _("uninstallable providers: ");
1023               for (ProviderList::const_iterator iter = providerlistUninstalled.begin(); iter != providerlistUninstalled.end(); iter++) {
1024                   if (iter == providerlistUninstalled.begin())
1025                       detail += itemToString (*iter, false);
1026                   else
1027                       detail += "\n                   " + itemToString (mapItem(*iter), false);
1028               }
1029           }
1030           break;
1031   }
1032
1033   return ret;
1034 }
1035
1036 ResolverProblemList
1037 SATResolver::problems ()
1038 {
1039     ResolverProblemList resolverProblems;
1040     if (_solv && _solv->problems.count) {
1041         Pool *pool = _solv->pool;
1042         int pcnt;
1043         Id p, rp, what;
1044         Id problem, solution, element;
1045         sat::Solvable s, sd;
1046
1047         CapabilitySet system_requires = SystemCheck::instance().requiredSystemCap();
1048         CapabilitySet system_conflicts = SystemCheck::instance().conflictSystemCap();
1049
1050         MIL << "Encountered problems! Here are the solutions:\n" << endl;
1051         pcnt = 1;
1052         problem = 0;
1053         while ((problem = solver_next_problem(_solv, problem)) != 0) {
1054             MIL << "Problem " <<  pcnt++ << ":" << endl;
1055             MIL << "====================================" << endl;
1056             string detail;
1057             Id ignoreId;
1058             string whatString = SATprobleminfoString (problem,detail,ignoreId);
1059             MIL << whatString << endl;
1060             MIL << "------------------------------------" << endl;
1061             ResolverProblem_Ptr resolverProblem = new ResolverProblem (whatString, detail);
1062
1063             solution = 0;
1064             while ((solution = solver_next_solution(_solv, problem, solution)) != 0) {
1065                 element = 0;
1066                 ProblemSolutionCombi *problemSolution = new ProblemSolutionCombi(resolverProblem);
1067                 while ((element = solver_next_solutionelement(_solv, problem, solution, element, &p, &rp)) != 0) {
1068                     if (p == SOLVER_SOLUTION_JOB) {
1069                         /* job, rp is index into job queue */
1070                         what = _jobQueue.elements[rp];
1071                         switch (_jobQueue.elements[rp-1])
1072                         {
1073                             case SOLVER_INSTALL_SOLVABLE: {
1074                                 s = mapSolvable (what);
1075                                 PoolItem poolItem = _pool.find (s);
1076                                 if (poolItem) {
1077                                     if (_solv->installed && s.get()->repo == _solv->installed) {
1078                                         problemSolution->addSingleAction (poolItem, REMOVE);
1079                                         string description = str::form (_("do not keep %s installed"),  solvable2str(pool, s.get()) );
1080                                         MIL << description << endl;
1081                                         problemSolution->addDescription (description);
1082                                     } else {
1083                                         problemSolution->addSingleAction (poolItem, KEEP);
1084                                         string description = str::form (_("do not install %s"), solvable2str(pool, s.get()));
1085                                         MIL << description << endl;
1086                                         problemSolution->addDescription (description);
1087                                     }
1088                                 } else {
1089                                     ERR << "SOLVER_INSTALL_SOLVABLE: No item found for " << id2str(pool, s.get()->name) << "-"
1090                                         <<  id2str(pool, s.get()->evr) << "." <<  id2str(pool, s.get()->arch) << endl;
1091                                 }
1092                             }
1093                                 break;
1094                             case SOLVER_ERASE_SOLVABLE: {
1095                                 s = mapSolvable (what);
1096                                 PoolItem poolItem = _pool.find (s);
1097                                 if (poolItem) {
1098                                     if (_solv->installed && s.get()->repo == _solv->installed) {
1099                                         problemSolution->addSingleAction (poolItem, KEEP);
1100                                         string description = str::form (_("keep %s"), solvable2str(pool, s.get()));
1101                                         MIL << description << endl;
1102                                         problemSolution->addDescription (description);
1103                                     } else {
1104                                         problemSolution->addSingleAction (poolItem, UNLOCK);
1105                                         string description = str::form (_("do not forbid installation of %s"), itemToString(poolItem, false).c_str());
1106                                         MIL << description << endl;
1107                                         problemSolution->addDescription (description);
1108                                     }
1109                                 } else {
1110                                     ERR << "SOLVER_ERASE_SOLVABLE: No item found for " << id2str(pool, s.get()->name) << "-" <<  id2str(pool, s.get()->evr) << "." <<
1111                                         id2str(pool, s.get()->arch) << endl;
1112                                 }
1113                             }
1114                                 break;
1115                             case SOLVER_INSTALL_SOLVABLE_NAME:
1116                                 {
1117                                 IdString ident( what );
1118                                 SolverQueueItemInstall_Ptr install =
1119                                     new SolverQueueItemInstall(_pool, ident.asString(), false );
1120                                 problemSolution->addSingleAction (install, REMOVE_SOLVE_QUEUE_ITEM);
1121
1122                                 string description = str::form (_("do not install %s"), ident.c_str() );
1123                                 MIL << description << endl;
1124                                 problemSolution->addDescription (description);
1125                                 }
1126                                 break;
1127                             case SOLVER_ERASE_SOLVABLE_NAME:
1128                                 {
1129                                 // As we do not know, if this request has come from resolvePool or
1130                                 // resolveQueue we will have to take care for both cases.
1131                                 IdString ident( what );
1132                                 FindPackage info (problemSolution, KEEP);
1133                                 invokeOnEach( _pool.byIdentBegin( ident ),
1134                                               _pool.byIdentEnd( ident ),
1135                                               functor::chain (resfilter::ByInstalled (),                        // ByInstalled
1136                                                               resfilter::ByTransact ()),                        // will be deinstalled
1137                                               functor::functorRef<bool,PoolItem> (info) );
1138
1139                                 SolverQueueItemDelete_Ptr del =
1140                                     new SolverQueueItemDelete(_pool, ident.asString(), false );
1141                                 problemSolution->addSingleAction (del, REMOVE_SOLVE_QUEUE_ITEM);
1142
1143                                 string description = str::form (_("keep %s"), ident.c_str());
1144                                 MIL << description << endl;
1145                                 problemSolution->addDescription (description);
1146                                 }
1147                                 break;
1148                             case SOLVER_INSTALL_SOLVABLE_PROVIDES:
1149                                 {
1150                                 problemSolution->addSingleAction (Capability(what), REMOVE_EXTRA_REQUIRE);
1151                                 string description = "";
1152
1153                                 // Checking if this problem solution would break your system
1154                                 if (system_requires.find(Capability(what)) != system_requires.end()) {
1155                                     // Show a better warning
1156                                     resolverProblem->setDetails( resolverProblem->description() + "\n" + resolverProblem->details() );
1157                                     resolverProblem->setDescription(_("This request will break your system!"));
1158                                     description = _("ignore the warning of a broken system");
1159                                     description += string(" (requires:")+dep2str(pool, what)+")";
1160                                     MIL << description << endl;
1161                                     problemSolution->addFrontDescription (description);
1162                                 } else {
1163                                     description = str::form (_("do not ask to install a solvable providing %s"), dep2str(pool, what));
1164                                     MIL << description << endl;
1165                                     problemSolution->addDescription (description);
1166                                 }
1167                                 }
1168                                 break;
1169                             case SOLVER_ERASE_SOLVABLE_PROVIDES:
1170                                 {
1171                                 problemSolution->addSingleAction (Capability(what), REMOVE_EXTRA_CONFLICT);
1172                                 string description = "";
1173
1174                                 // Checking if this problem solution would break your system
1175                                 if (system_conflicts.find(Capability(what)) != system_conflicts.end()) {
1176                                     // Show a better warning
1177                                     resolverProblem->setDetails( resolverProblem->description() + "\n" + resolverProblem->details() );
1178                                     resolverProblem->setDescription(_("This request will break your system!"));
1179                                     description = _("ignore the warning of a broken system");
1180                                     description += string(" (conflicts:")+dep2str(pool, what)+")";
1181                                     MIL << description << endl;
1182                                     problemSolution->addFrontDescription (description);
1183
1184                                 } else {
1185                                     description = str::form (_("do not ask to delete all solvables providing %s"), dep2str(pool, what));
1186                                     MIL << description << endl;
1187                                     problemSolution->addDescription (description);
1188                                 }
1189                                 }
1190                                 break;
1191                             case SOLVER_INSTALL_SOLVABLE_UPDATE:
1192                                 {
1193                                 s = mapSolvable (what);
1194                                 PoolItem poolItem = _pool.find (s);
1195                                 if (poolItem) {
1196                                     if (_solv->installed && s.get()->repo == _solv->installed) {
1197                                         problemSolution->addSingleAction (poolItem, KEEP);
1198                                         string description = str::form (_("do not install most recent version of %s"), solvable2str(pool, s.get()));
1199                                         MIL << description << endl;
1200                                         problemSolution->addDescription (description);
1201                                     } else {
1202                                         ERR << "SOLVER_INSTALL_SOLVABLE_UPDATE " << poolItem << " is not selected for installation" << endl;
1203                                     }
1204                                 } else {
1205                                     ERR << "SOLVER_INSTALL_SOLVABLE_UPDATE: No item found for " << id2str(pool, s.get()->name) << "-" <<  id2str(pool, s.get()->evr) << "." <<
1206                                         id2str(pool, s.get()->arch) << endl;
1207                                 }
1208                                 }
1209                                 break;
1210                             default:
1211                                 MIL << "- do something different" << endl;
1212                                 ERR << "No valid solution available" << endl;
1213                                 break;
1214                         }
1215                     } else if (p == SOLVER_SOLUTION_INFARCH) {
1216                         s = mapSolvable (rp);
1217                         PoolItem poolItem = _pool.find (s);
1218                         if (_solv->installed && s.get()->repo == _solv->installed) {
1219                             problemSolution->addSingleAction (poolItem, KEEP);
1220                             string description = str::form (_("keep %s despite the inferior architecture"), solvable2str(pool, s.get()));
1221                             MIL << description << endl;
1222                             problemSolution->addDescription (description);
1223                         } else {
1224                             problemSolution->addSingleAction (poolItem, INSTALL);
1225                             string description = str::form (_("install %s despite the inferior architecture"), solvable2str(pool, s.get()));
1226                             MIL << description << endl;
1227                             problemSolution->addDescription (description);
1228                         }
1229                     } else if (p == SOLVER_SOLUTION_DISTUPGRADE) {
1230                         s = mapSolvable (rp);
1231                         PoolItem poolItem = _pool.find (s);
1232                         if (_solv->installed && s.get()->repo == _solv->installed) {
1233                             problemSolution->addSingleAction (poolItem, KEEP);
1234                             string description = str::form (_("keep obsolete %s"), solvable2str(pool, s.get()));
1235                             MIL << description << endl;
1236                             problemSolution->addDescription (description);
1237                         } else {
1238                             problemSolution->addSingleAction (poolItem, INSTALL);
1239                             string description = str::form (_("install %s from excluded repository"), solvable2str(pool, s.get()));
1240                             MIL << description << endl;
1241                             problemSolution->addDescription (description);
1242                         }
1243                     } else {
1244                         /* policy, replace p with rp */
1245                         s = mapSolvable (p);
1246                         if (rp)
1247                             sd = mapSolvable (rp);
1248
1249                         PoolItem itemFrom = _pool.find (s);
1250                         if (s == sd && _solv->distupgrade)
1251                         {
1252                             PoolItem poolItem = _pool.find (s);
1253                             if (poolItem) {
1254                                 problemSolution->addSingleAction (poolItem, LOCK); // for solver reason: NOT weak lock.
1255                                 string description = str::form (_("keep %s"), solvable2str(pool, s.get()));
1256                                 MIL << description << endl;
1257                                 problemSolution->addDescription (description);
1258                             } else {
1259                                 ERR << "SOLVER_INSTALL_SOLVABLE: No item found for " << id2str(pool, s.get()->name) << "-"
1260                                     <<  id2str(pool, s.get()->evr) << "." <<  id2str(pool, s.get()->arch) << endl;
1261                             }
1262                         }
1263                         else if (rp)
1264                         {
1265                             int gotone = 0;
1266
1267                             PoolItem itemTo = _pool.find (sd);
1268                             if (itemFrom && itemTo) {
1269                                 problemSolution->addSingleAction (itemTo, INSTALL);
1270
1271                                 if (evrcmp(pool, s.get()->evr, sd.get()->evr, EVRCMP_COMPARE ) > 0)
1272                                 {
1273                                     string description = str::form (_("downgrade of %s to %s"), solvable2str(pool, s.get()), solvable2str(pool, sd.get()));
1274                                     MIL << description << endl;
1275                                     problemSolution->addDescription (description);
1276                                     gotone = 1;
1277                                 }
1278                                 if (!_solv->allowarchchange && s.get()->name == sd.get()->name && s.get()->arch != sd.get()->arch
1279                                     && policy_illegal_archchange(_solv, s.get(), sd.get()))
1280                                 {
1281                                     string description = str::form (_("architecture change of %s to %s"), solvable2str(pool, s.get()), solvable2str(pool, sd.get()));
1282                                     MIL << description << endl;
1283                                     problemSolution->addDescription (description);
1284                                     gotone = 1;
1285                                 }
1286                                 if (!_solv->allowvendorchange && s.get()->name == sd.get()->name && s.get()->vendor != sd.get()->vendor
1287                                     && policy_illegal_vendorchange(_solv, s.get(), sd.get()))
1288                                 {
1289                                     string description = str::form (_("install %s (with vendor change)\n  %s\n-->\n  %s") ,
1290                                                                     solvable2str(pool, sd.get()) , id2str(pool, s.get()->vendor),
1291                                                                     string(sd.get()->vendor ?  id2str(pool, sd.get()->vendor) : " (no vendor) ").c_str() );
1292                                     MIL << description << endl;
1293                                     problemSolution->addDescription (description);
1294                                     gotone = 1;
1295                                 }
1296                                 if (!gotone) {
1297                                     string description = str::form (_("replacement of %s with %s"), solvable2str(pool, s.get()), solvable2str(pool, sd.get()));
1298                                     MIL << description << endl;
1299                                     problemSolution->addDescription (description);
1300                                 }
1301                             } else {
1302                                 ERR << id2str(pool, s.get()->name) << "-" <<  id2str(pool, s.get()->evr) << "." <<  id2str(pool, s.get()->arch)
1303                                     << " or "  << id2str(pool, sd.get()->name) << "-" <<  id2str(pool, sd.get()->evr) << "." <<  id2str(pool, sd.get()->arch) << " not found" << endl;
1304                             }
1305                         }
1306                         else
1307                         {
1308                             if (itemFrom) {
1309                                 string description = str::form (_("deinstallation of %s"), solvable2str(pool, s.get()));
1310                                 MIL << description << endl;
1311                                 problemSolution->addDescription (description);
1312                                 problemSolution->addSingleAction (itemFrom, REMOVE);
1313                             }
1314                         }
1315                     }
1316                 }
1317                 resolverProblem->addSolution (problemSolution,
1318                                               problemSolution->actionCount() > 1 ? true : false); // Solutions with more than 1 action will be shown first.
1319                 MIL << "------------------------------------" << endl;
1320             }
1321
1322             if (ignoreId > 0) {
1323                 // There is a possibility to ignore this error by setting weak dependencies
1324                 PoolItem item = _pool.find (sat::Solvable(ignoreId));
1325                 ProblemSolutionIgnore *problemSolution = new ProblemSolutionIgnore(resolverProblem, item);
1326                 resolverProblem->addSolution (problemSolution,
1327                                               false); // Solutions will be shown at the end
1328                 MIL << "ignore some dependencies of " << item << endl;
1329                 MIL << "------------------------------------" << endl;
1330             }
1331
1332             // save problem
1333             resolverProblems.push_back (resolverProblem);
1334         }
1335     }
1336     return resolverProblems;
1337 }
1338
1339 void
1340 SATResolver::applySolutions (const ProblemSolutionList & solutions)
1341 {
1342     for (ProblemSolutionList::const_iterator iter = solutions.begin();
1343          iter != solutions.end(); ++iter) {
1344         ProblemSolution_Ptr solution = *iter;
1345         Resolver dummyResolver(_pool);
1346         if (!solution->apply (dummyResolver))
1347             break;
1348     }
1349 }
1350
1351 void SATResolver::setLocks()
1352 {
1353     for (PoolItemList::const_iterator iter = _items_to_lock.begin(); iter != _items_to_lock.end(); iter++) {
1354         sat::detail::SolvableIdType ident( (*iter)->satSolvable().id() );
1355         if (iter->status().isInstalled()) {
1356             MIL << "Lock installed item " << *iter << endl;
1357             queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE );
1358             queue_push( &(_jobQueue), ident );
1359         } else {
1360             MIL << "Lock NOT installed item " << *iter << endl;
1361             queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE );
1362             queue_push( &(_jobQueue), ident );
1363         }
1364     }
1365
1366     for (PoolItemList::const_iterator iter = _items_to_keep.begin(); iter != _items_to_keep.end(); iter++) {
1367         sat::detail::SolvableIdType ident( (*iter)->satSolvable().id() );
1368         if (iter->status().isInstalled()) {
1369             MIL << "Keep installed item " << *iter << endl;
1370             queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE | SOLVER_WEAK);
1371             queue_push( &(_jobQueue), ident );
1372         } else {
1373             MIL << "Keep NOT installed item " << *iter << ident << endl;
1374             queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE | SOLVER_WEAK);
1375             queue_push( &(_jobQueue), ident );
1376         }
1377     }
1378 }
1379
1380 void SATResolver::setSystemRequirements()
1381 {
1382     CapabilitySet system_requires = SystemCheck::instance().requiredSystemCap();
1383     CapabilitySet system_conflicts = SystemCheck::instance().conflictSystemCap();
1384
1385     for (CapabilitySet::const_iterator iter = system_requires.begin(); iter != system_requires.end(); iter++) {
1386         queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE_PROVIDES);
1387         queue_push( &(_jobQueue), iter->id() );
1388         MIL << "SYSTEM Requires " << *iter << endl;
1389     }
1390
1391     for (CapabilitySet::const_iterator iter = system_conflicts.begin(); iter != system_conflicts.end(); iter++) {
1392         queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE_PROVIDES);
1393         queue_push( &(_jobQueue), iter->id() );
1394         MIL << "SYSTEM Conflicts " << *iter << endl;
1395     }
1396
1397     // try to prefer none architecture change if possible
1398     // So the architecture of the "rpm" package should be prefered
1399
1400     Capability cap("rpm");
1401     sat::WhatProvides rpmProviders(cap);
1402     for_( iter2, rpmProviders.begin(), rpmProviders.end() ) {
1403         if (iter2->isSystem()) {
1404             sat::detail::IdType nid = iter2->ident().id();
1405             nid = rel2id(_SATPool,
1406                          nid,
1407                          iter2->arch().id(), REL_ARCH, true);
1408             if (_distupgrade)
1409             {
1410                 bool addRule = false;
1411                 Capability cap(nid);
1412                 sat::WhatProvides rpmProviders(cap);
1413                 for_( iter3, rpmProviders.begin(), rpmProviders.end() ) {
1414                     if ( !(iter3->isSystem())) {
1415                         addRule = true;
1416                         break;
1417                     }
1418                 }
1419                 if (!addRule)
1420                     break;
1421             }
1422
1423             queue_push(&(_jobQueue), SOLVER_INSTALL|SOLVABLE_NAME|SOLVER_ESSENTIAL);
1424             queue_push(&(_jobQueue), nid);
1425             break;
1426         }
1427     }
1428 }
1429
1430
1431 ///////////////////////////////////////////////////////////////////
1432 };// namespace detail
1433     /////////////////////////////////////////////////////////////////////
1434     /////////////////////////////////////////////////////////////////////
1435   };// namespace solver
1436   ///////////////////////////////////////////////////////////////////////
1437   ///////////////////////////////////////////////////////////////////////
1438 };// namespace zypp
1439 /////////////////////////////////////////////////////////////////////////
1440