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