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