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