Imported Upstream version 17.8.0
[platform/upstream/libzypp.git] / zypp / solver / detail / Resolver.cc
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /* Resolver.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 to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19  * 02111-1307, USA.
20  */
21 #include <boost/static_assert.hpp>
22
23 #define ZYPP_USE_RESOLVER_INTERNALS
24
25 #include "zypp/solver/detail/Resolver.h"
26 #include "zypp/solver/detail/Testcase.h"
27 #include "zypp/solver/detail/SATResolver.h"
28 #include "zypp/solver/detail/ItemCapKind.h"
29 #include "zypp/solver/detail/SolutionAction.h"
30 #include "zypp/solver/detail/SolverQueueItem.h"
31
32 #include "zypp/Capabilities.h"
33 #include "zypp/ZConfig.h"
34 #include "zypp/base/Logger.h"
35 #include "zypp/base/String.h"
36 #include "zypp/base/Gettext.h"
37 #include "zypp/base/Algorithm.h"
38 #include "zypp/ResPool.h"
39 #include "zypp/ResFilters.h"
40 #include "zypp/sat/Pool.h"
41 #include "zypp/sat/Solvable.h"
42 #include "zypp/sat/Transaction.h"
43 #include "zypp/ResolverProblem.h"
44
45 #define MAXSOLVERRUNS 5
46
47 using std::endl;
48 using std::make_pair;
49
50 #undef ZYPP_BASE_LOGGER_LOGGROUP
51 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::solver"
52
53 /////////////////////////////////////////////////////////////////////////
54 namespace zypp
55 { ///////////////////////////////////////////////////////////////////////
56   ///////////////////////////////////////////////////////////////////////
57   namespace solver
58   { /////////////////////////////////////////////////////////////////////
59     /////////////////////////////////////////////////////////////////////
60     namespace detail
61     { ///////////////////////////////////////////////////////////////////
62
63       //using namespace std;
64
65 //---------------------------------------------------------------------------
66
67
68 std::ostream & Resolver::dumpOn( std::ostream & os ) const
69 {
70   os << "<resolver>" << endl;
71   #define OUTS(t) os << "  " << #t << ":\t" << t << endl;
72   OUTS( _upgradeMode );
73   OUTS( _updateMode );
74   OUTS( _verifying );
75   OUTS( _onlyRequires );
76   OUTS( _solveSrcPackages );
77   OUTS( _cleandepsOnRemove );
78   OUTS( _ignoreAlreadyRecommended );
79   OUTS( _inr );
80   #undef OUT
81   return os << "<resolver/>";
82 }
83
84
85 //---------------------------------------------------------------------------
86
87 Resolver::Resolver (const ResPool & pool)
88     : _pool(pool)
89     , _satResolver(NULL)
90     , _poolchanged(_pool.serial() )
91     , _upgradeMode              (false)
92     , _updateMode               (false)
93     , _verifying                (false)
94     , _onlyRequires             ( ZConfig::instance().solver_onlyRequires() )
95     , _solveSrcPackages         ( false )
96     , _cleandepsOnRemove        ( ZConfig::instance().solver_cleandepsOnRemove() )
97     , _ignoreAlreadyRecommended ( true )
98     // _inr defaults to ResolverNamespaces()
99
100 {
101     sat::Pool satPool( sat::Pool::instance() );
102     _satResolver = new SATResolver(_pool, satPool.get());
103 }
104
105
106 Resolver::~Resolver()
107 {
108   delete _satResolver;
109 }
110
111 //---------------------------------------------------------------------------
112 // forward flags too SATResolver
113 #define ZOLV_FLAG_TRIBOOL( ZSETTER, ZGETTER, ZVARNAME, ZVARDEFAULT )                    \
114     void Resolver::ZSETTER( TriBool state_r )                                           \
115     { _satResolver->ZVARNAME = indeterminate(state_r) ? ZVARDEFAULT : bool(state_r); }  \
116     bool Resolver::ZGETTER() const                                                      \
117     { return _satResolver->ZVARNAME; }                                                  \
118
119 // NOTE: ZVARDEFAULT must be in sync with SATResolver ctor
120 ZOLV_FLAG_TRIBOOL( setForceResolve,             forceResolve,           _allowuninstall,        false )
121
122 ZOLV_FLAG_TRIBOOL( setAllowDowngrade,           allowDowngrade,         _allowdowngrade,        false )
123 ZOLV_FLAG_TRIBOOL( setAllowNameChange,          allowNameChange,        _allownamechange,       true )  // bsc#1071466
124 ZOLV_FLAG_TRIBOOL( setAllowArchChange,          allowArchChange,        _allowarchchange,       false )
125 ZOLV_FLAG_TRIBOOL( setAllowVendorChange,        allowVendorChange,      _allowvendorchange,     ZConfig::instance().solver_allowVendorChange() )
126
127 ZOLV_FLAG_TRIBOOL( dupSetAllowDowngrade,        dupAllowDowngrade,      _dup_allowdowngrade,    ZConfig::instance().solver_dupAllowDowngrade() )
128 ZOLV_FLAG_TRIBOOL( dupSetAllowNameChange,       dupAllowNameChange,     _dup_allownamechange,   ZConfig::instance().solver_dupAllowNameChange() )
129 ZOLV_FLAG_TRIBOOL( dupSetAllowArchChange,       dupAllowArchChange,     _dup_allowarchchange,   ZConfig::instance().solver_dupAllowArchChange() )
130 ZOLV_FLAG_TRIBOOL( dupSetAllowVendorChange,     dupAllowVendorChange,   _dup_allowvendorchange, ZConfig::instance().solver_dupAllowVendorChange() )
131
132 #undef ZOLV_FLAG_TRIBOOL
133 //---------------------------------------------------------------------------
134
135 void Resolver::setOnlyRequires( TriBool state_r )
136 {
137   _onlyRequires = indeterminate(state_r) ? ZConfig::instance().solver_onlyRequires() : bool(state_r);
138 }
139
140 void Resolver::setCleandepsOnRemove( TriBool state_r )
141 {
142   _cleandepsOnRemove = indeterminate(state_r) ? ZConfig::instance().solver_cleandepsOnRemove() : bool(state_r);
143 }
144
145 //---------------------------------------------------------------------------
146
147 ResPool Resolver::pool() const
148 { return _pool; }
149
150 void Resolver::reset( bool keepExtras )
151 {
152     _verifying = false;
153
154     if (!keepExtras) {
155       _extra_requires.clear();
156       _extra_conflicts.clear();
157     }
158
159     _isInstalledBy.clear();
160     _installs.clear();
161     _satifiedByInstalled.clear();
162     _installedSatisfied.clear();
163 }
164
165 bool Resolver::doUpgrade()
166 {
167   // Setting Resolver to upgrade mode. SAT solver will do the update
168   _upgradeMode = true;
169   return resolvePool();
170 }
171
172 void Resolver::doUpdate()
173 {
174     _updateMode = true;
175     return _satResolver->doUpdate();
176 }
177
178 PoolItemList Resolver::problematicUpdateItems() const
179 { return _satResolver->problematicUpdateItems(); }
180
181 void Resolver::addExtraRequire( const Capability & capability )
182 { _extra_requires.insert (capability); }
183
184 void Resolver::removeExtraRequire( const Capability & capability )
185 { _extra_requires.erase (capability); }
186
187 void Resolver::addExtraConflict( const Capability & capability )
188 { _extra_conflicts.insert (capability); }
189
190 void Resolver::removeExtraConflict( const Capability & capability )
191 { _extra_conflicts.erase (capability); }
192
193 void Resolver::removeQueueItem( SolverQueueItem_Ptr item )
194 {
195     bool found = false;
196     for (SolverQueueItemList::const_iterator iter = _added_queue_items.begin();
197          iter != _added_queue_items.end(); iter++) {
198         if (*iter == item) {
199             _added_queue_items.remove(*iter);
200             found = true;
201             break;
202         }
203     }
204     if (!found) {
205         _removed_queue_items.push_back (item);
206         _removed_queue_items.unique ();
207     }
208 }
209
210 void Resolver::addQueueItem( SolverQueueItem_Ptr item )
211 {
212     bool found = false;
213     for (SolverQueueItemList::const_iterator iter = _removed_queue_items.begin();
214          iter != _removed_queue_items.end(); iter++) {
215         if (*iter == item) {
216             _removed_queue_items.remove(*iter);
217             found = true;
218             break;
219         }
220     }
221     if (!found) {
222         _added_queue_items.push_back (item);
223         _added_queue_items.unique ();
224     }
225 }
226
227 void Resolver::addWeak( const PoolItem & item )
228 { _addWeak.push_back( item ); }
229
230 //---------------------------------------------------------------------------
231
232 struct UndoTransact : public resfilter::PoolItemFilterFunctor
233 {
234     ResStatus::TransactByValue resStatus;
235     UndoTransact ( const ResStatus::TransactByValue &status)
236         :resStatus(status)
237     { }
238
239     bool operator()( PoolItem item )            // only transacts() items go here
240     {
241         item.status().resetTransact( resStatus );// clear any solver/establish transactions
242         return true;
243     }
244 };
245
246
247 struct DoTransact : public resfilter::PoolItemFilterFunctor
248 {
249     ResStatus::TransactByValue resStatus;
250     DoTransact ( const ResStatus::TransactByValue &status)
251         :resStatus(status)
252     { }
253
254     bool operator()( PoolItem item )            // only transacts() items go here
255     {
256         item.status().setTransact( true, resStatus );
257         return true;
258     }
259 };
260
261
262 bool Resolver::verifySystem()
263 {
264     UndoTransact resetting (ResStatus::APPL_HIGH);
265
266     DBG << "Resolver::verifySystem()" << endl;
267
268     _verifying = true;
269
270     invokeOnEach ( _pool.begin(), _pool.end(),
271                    resfilter::ByTransact( ),                    // Resetting all transcations
272                    functor::functorRef<bool,PoolItem>(resetting) );
273
274     return resolvePool();
275 }
276
277
278 //----------------------------------------------------------------------------
279 // undo
280 void Resolver::undo()
281 {
282     UndoTransact info(ResStatus::APPL_LOW);
283     MIL << "*** undo ***" << endl;
284     invokeOnEach ( _pool.begin(), _pool.end(),
285                    resfilter::ByTransact( ),                    // collect transacts from Pool to resolver queue
286                    functor::functorRef<bool,PoolItem>(info) );
287     //  Regard dependencies of the item weak onl
288     _addWeak.clear();
289
290     // Additional QueueItems which has to be regarded by the solver
291     _removed_queue_items.clear();
292     _added_queue_items.clear();
293
294     return;
295 }
296
297 void Resolver::solverInit()
298 {
299     // Solving with libsolv
300     static bool poolDumped = false;
301     MIL << "-------------- Calling SAT Solver -------------------" << endl;
302     if ( getenv("ZYPP_FULLLOG") ) {
303         Testcase testcase("/var/log/YaST2/autoTestcase");
304         if (!poolDumped) {
305             testcase.createTestcase (*this, true, false); // dump pool
306             poolDumped = true;
307         } else {
308             testcase.createTestcase (*this, false, false); // write control file only
309         }
310     }
311
312     _satResolver->setFixsystem                  ( isVerifyingMode() );
313     _satResolver->setIgnorealreadyrecommended   ( ignoreAlreadyRecommended() );
314     _satResolver->setInr                        ( inr() );
315     _satResolver->setOnlyRequires               ( onlyRequires() );
316     _satResolver->setUpdatesystem               (_updateMode);
317     _satResolver->setSolveSrcPackages           ( solveSrcPackages() );
318     _satResolver->setCleandepsOnRemove          ( cleandepsOnRemove() );
319
320     _satResolver->setDistupgrade                (_upgradeMode);
321     if (_upgradeMode) {
322       // may overwrite some settings
323       _satResolver->setDistupgrade_removeunsupported    (false);
324     }
325
326     // Resetting additional solver information
327     _isInstalledBy.clear();
328     _installs.clear();
329     _satifiedByInstalled.clear();
330     _installedSatisfied.clear();
331 }
332
333 bool Resolver::resolvePool()
334 {
335     solverInit();
336     return _satResolver->resolvePool(_extra_requires, _extra_conflicts, _addWeak, _upgradeRepos );
337 }
338
339 bool Resolver::resolveQueue( solver::detail::SolverQueueItemList & queue )
340 {
341     solverInit();
342
343     // add/remove additional SolverQueueItems
344     for (SolverQueueItemList::const_iterator iter = _removed_queue_items.begin();
345          iter != _removed_queue_items.end(); iter++) {
346         for (SolverQueueItemList::const_iterator iterQueue = queue.begin(); iterQueue != queue.end(); iterQueue++) {
347             if ( (*iterQueue)->cmp(*iter) == 0) {
348                 MIL << "remove from queue" << *iter;
349                 queue.remove(*iterQueue);
350                 break;
351             }
352         }
353     }
354
355     for (SolverQueueItemList::const_iterator iter = _added_queue_items.begin();
356          iter != _added_queue_items.end(); iter++) {
357         bool found = false;
358         for (SolverQueueItemList::const_iterator iterQueue = queue.begin(); iterQueue != queue.end(); iterQueue++) {
359             if ( (*iterQueue)->cmp(*iter) == 0) {
360                 found = true;
361                 break;
362             }
363         }
364         if (!found) {
365             MIL << "add to queue" << *iter;
366             queue.push_back(*iter);
367         }
368     }
369
370     // The application has to take care to write these solutions back to e.g. selectables in order
371     // give the user a chance for changing these decisions again.
372     _removed_queue_items.clear();
373     _added_queue_items.clear();
374
375     return _satResolver->resolveQueue(queue, _addWeak);
376 }
377
378 sat::Transaction Resolver::getTransaction()
379 {
380   // FIXME: That's an ugly way of pushing autoInstalled into the transaction.
381   sat::Transaction ret( sat::Transaction::loadFromPool );
382   ret.autoInstalled( _satResolver->autoInstalled() );
383   return ret;
384 }
385
386
387 //----------------------------------------------------------------------------
388 // Getting more information about the solve results
389
390 ResolverProblemList Resolver::problems() const
391 {
392   MIL << "Resolver::problems()" << endl;
393   return _satResolver->problems();
394 }
395
396 void Resolver::applySolutions( const ProblemSolutionList & solutions )
397 {
398   for ( ProblemSolution_Ptr solution : solutions )
399   {
400     if ( ! applySolution( *solution ) )
401       break;
402   }
403 }
404
405 bool Resolver::applySolution( const ProblemSolution & solution )
406 {
407   bool ret = true;
408   DBG << "apply solution " << solution << endl;
409   for ( SolutionAction_Ptr action : solution.actions() )
410   {
411     if ( ! action->execute( *this ) )
412     {
413       WAR << "apply solution action failed: " << action << endl;
414       ret = false;
415       break;
416     }
417   }
418   return ret;
419 }
420
421 //----------------------------------------------------------------------------
422
423 void Resolver::collectResolverInfo()
424 {
425     if ( _satResolver
426          && _isInstalledBy.empty()
427          && _installs.empty()) {
428
429         // generating new
430         PoolItemList itemsToInstall = _satResolver->resultItemsToInstall();
431
432         for (PoolItemList::const_iterator instIter = itemsToInstall.begin();
433              instIter != itemsToInstall.end(); instIter++) {
434             // Requires
435             for (Capabilities::const_iterator capIt = (*instIter)->dep (Dep::REQUIRES).begin(); capIt != (*instIter)->dep (Dep::REQUIRES).end(); ++capIt)
436             {
437                 sat::WhatProvides possibleProviders(*capIt);
438                 for_( iter, possibleProviders.begin(), possibleProviders.end() ) {
439                     PoolItem provider = ResPool::instance().find( *iter );
440
441                     // searching if this provider will already be installed
442                     bool found = false;
443                     bool alreadySetForInstallation = false;
444                     ItemCapKindMap::const_iterator pos = _isInstalledBy.find(provider);
445                     while (pos != _isInstalledBy.end()
446                            && pos->first == provider
447                            && !found) {
448                         alreadySetForInstallation = true;
449                         ItemCapKind capKind = pos->second;
450                         if (capKind.item() == *instIter)  found = true;
451                         pos++;
452                     }
453
454                     if (!found
455                         && provider.status().isToBeInstalled()) {
456                         if (provider.status().isBySolver()) {
457                             ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::REQUIRES, !alreadySetForInstallation );
458                             _isInstalledBy.insert (make_pair( provider, capKindisInstalledBy));
459                         } else {
460                             // no initial installation cause it has been set be e.g. user
461                             ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::REQUIRES, false );
462                             _isInstalledBy.insert (make_pair( provider, capKindisInstalledBy));
463                         }
464                         ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::REQUIRES, !alreadySetForInstallation );
465                         _installs.insert (make_pair( *instIter, capKindisInstalledBy));
466                     }
467
468                     if (provider.status().staysInstalled()) { // Is already satisfied by an item which is installed
469                         ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::REQUIRES, false );
470                         _satifiedByInstalled.insert (make_pair( *instIter, capKindisInstalledBy));
471
472                         ItemCapKind installedSatisfied( *instIter, *capIt, Dep::REQUIRES, false );
473                         _installedSatisfied.insert (make_pair( provider, installedSatisfied));
474                     }
475                 }
476             }
477
478             if (!(_satResolver->onlyRequires())) {
479                 //Recommends
480                 for (Capabilities::const_iterator capIt = (*instIter)->dep (Dep::RECOMMENDS).begin(); capIt != (*instIter)->dep (Dep::RECOMMENDS).end(); ++capIt)
481                 {
482                     sat::WhatProvides possibleProviders(*capIt);
483                     for_( iter, possibleProviders.begin(), possibleProviders.end() ) {
484                         PoolItem provider = ResPool::instance().find( *iter );
485
486                         // searching if this provider will already be installed
487                         bool found = false;
488                         bool alreadySetForInstallation = false;
489                         ItemCapKindMap::const_iterator pos = _isInstalledBy.find(provider);
490                         while (pos != _isInstalledBy.end()
491                                && pos->first == provider
492                                && !found) {
493                             alreadySetForInstallation = true;
494                             ItemCapKind capKind = pos->second;
495                             if (capKind.item() == *instIter)  found = true;
496                             pos++;
497                         }
498
499                         if (!found
500                             && provider.status().isToBeInstalled()) {
501                             if (provider.status().isBySolver()) {
502                                 ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::RECOMMENDS, !alreadySetForInstallation );
503                                 _isInstalledBy.insert (make_pair( provider, capKindisInstalledBy));
504                             } else {
505                                 // no initial installation cause it has been set be e.g. user
506                                 ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::RECOMMENDS, false );
507                                 _isInstalledBy.insert (make_pair( provider, capKindisInstalledBy));
508                             }
509                             ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::RECOMMENDS, !alreadySetForInstallation );
510                             _installs.insert (make_pair( *instIter, capKindisInstalledBy));
511                         }
512
513                         if (provider.status().staysInstalled()) { // Is already satisfied by an item which is installed
514                             ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::RECOMMENDS, false );
515                             _satifiedByInstalled.insert (make_pair( *instIter, capKindisInstalledBy));
516
517                             ItemCapKind installedSatisfied( *instIter, *capIt, Dep::RECOMMENDS, false );
518                             _installedSatisfied.insert (make_pair( provider, installedSatisfied));
519                         }
520                     }
521                 }
522
523                 //Supplements
524                 for (Capabilities::const_iterator capIt = (*instIter)->dep (Dep::SUPPLEMENTS).begin(); capIt != (*instIter)->dep (Dep::SUPPLEMENTS).end(); ++capIt)
525                 {
526                     sat::WhatProvides possibleProviders(*capIt);
527                     for_( iter, possibleProviders.begin(), possibleProviders.end() ) {
528                         PoolItem provider = ResPool::instance().find( *iter );
529                         // searching if this item will already be installed
530                         bool found = false;
531                         bool alreadySetForInstallation = false;
532                         ItemCapKindMap::const_iterator pos = _isInstalledBy.find(*instIter);
533                         while (pos != _isInstalledBy.end()
534                                && pos->first == *instIter
535                                && !found) {
536                             alreadySetForInstallation = true;
537                             ItemCapKind capKind = pos->second;
538                             if (capKind.item() == provider)  found = true;
539                             pos++;
540                         }
541
542                         if (!found
543                             && instIter->status().isToBeInstalled()) {
544                             if (instIter->status().isBySolver()) {
545                                 ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::SUPPLEMENTS, !alreadySetForInstallation );
546                                 _isInstalledBy.insert (make_pair( *instIter, capKindisInstalledBy));
547                             } else {
548                                 // no initial installation cause it has been set be e.g. user
549                                 ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::SUPPLEMENTS, false );
550                                 _isInstalledBy.insert (make_pair( *instIter, capKindisInstalledBy));
551                             }
552                             ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::SUPPLEMENTS, !alreadySetForInstallation );
553                             _installs.insert (make_pair( provider, capKindisInstalledBy));
554                         }
555
556                         if (instIter->status().staysInstalled()) { // Is already satisfied by an item which is installed
557                             ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::SUPPLEMENTS, !alreadySetForInstallation );
558                             _satifiedByInstalled.insert (make_pair( provider, capKindisInstalledBy));
559
560                             ItemCapKind installedSatisfied( provider, *capIt, Dep::SUPPLEMENTS, false );
561                             _installedSatisfied.insert (make_pair( *instIter, installedSatisfied));
562                         }
563                     }
564                 }
565             }
566         }
567     }
568 }
569
570
571 ItemCapKindList Resolver::isInstalledBy( const PoolItem & item )
572 {
573     ItemCapKindList ret;
574     collectResolverInfo();
575
576     for (ItemCapKindMap::const_iterator iter = _isInstalledBy.find(item); iter != _isInstalledBy.end();) {
577         ItemCapKind info = iter->second;
578         PoolItem iterItem = iter->first;
579         if (iterItem == item) {
580             ret.push_back(info);
581             iter++;
582         } else {
583             // exit
584             iter = _isInstalledBy.end();
585         }
586     }
587     return ret;
588 }
589
590 ItemCapKindList Resolver::installs( const PoolItem & item )
591 {
592     ItemCapKindList ret;
593     collectResolverInfo();
594
595     for (ItemCapKindMap::const_iterator iter = _installs.find(item); iter != _installs.end();) {
596         ItemCapKind info = iter->second;
597         PoolItem iterItem = iter->first;
598         if (iterItem == item) {
599             ret.push_back(info);
600             iter++;
601         } else {
602             // exit
603             iter = _installs.end();
604         }
605     }
606     return ret;
607 }
608
609 ItemCapKindList Resolver::satifiedByInstalled( const PoolItem & item )
610 {
611     ItemCapKindList ret;
612     collectResolverInfo();
613
614     for (ItemCapKindMap::const_iterator iter = _satifiedByInstalled.find(item); iter != _satifiedByInstalled.end();) {
615         ItemCapKind info = iter->second;
616         PoolItem iterItem = iter->first;
617         if (iterItem == item) {
618             ret.push_back(info);
619             iter++;
620         } else {
621             // exit
622             iter = _satifiedByInstalled.end();
623         }
624     }
625     return ret;
626 }
627
628 ItemCapKindList Resolver::installedSatisfied( const PoolItem & item )
629 {
630     ItemCapKindList ret;
631     collectResolverInfo();
632
633     for (ItemCapKindMap::const_iterator iter = _installedSatisfied.find(item); iter != _installedSatisfied.end();) {
634         ItemCapKind info = iter->second;
635         PoolItem iterItem = iter->first;
636         if (iterItem == item) {
637             ret.push_back(info);
638             iter++;
639         } else {
640             // exit
641             iter = _installedSatisfied.end();
642         }
643     }
644     return ret;
645 }
646
647
648 ///////////////////////////////////////////////////////////////////
649     };// namespace detail
650     /////////////////////////////////////////////////////////////////////
651     /////////////////////////////////////////////////////////////////////
652   };// namespace solver
653   ///////////////////////////////////////////////////////////////////////
654   ///////////////////////////////////////////////////////////////////////
655 };// namespace zypp
656 /////////////////////////////////////////////////////////////////////////
657