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