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