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