1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/ui/SelectableImpl.h
12 #ifndef ZYPP_UI_SELECTABLEIMPL_H
13 #define ZYPP_UI_SELECTABLEIMPL_H
16 #include "zypp/base/LogTools.h"
18 #include "zypp/base/PtrTypes.h"
20 #include "zypp/ResPool.h"
21 #include "zypp/Resolver.h"
22 #include "zypp/ui/Selectable.h"
23 #include "zypp/ui/SelectableTraits.h"
27 ///////////////////////////////////////////////////////////////////
29 { /////////////////////////////////////////////////////////////////
30 ///////////////////////////////////////////////////////////////////
32 { /////////////////////////////////////////////////////////////////
34 ///////////////////////////////////////////////////////////////////
36 // CLASS NAME : Selectable::Impl
38 /** Selectable implementation.
39 * \note Implementation is based in PoolItem, just the Selectable
40 * inteface restricts them to ResObject::constPtr.
42 struct Selectable::Impl
46 typedef SelectableTraits::AvailableItemSet AvailableItemSet;
47 typedef SelectableTraits::available_iterator available_iterator;
48 typedef SelectableTraits::available_const_iterator available_const_iterator;
49 typedef SelectableTraits::available_size_type available_size_type;
51 typedef SelectableTraits::InstalledItemSet InstalledItemSet;
52 typedef SelectableTraits::installed_iterator installed_iterator;
53 typedef SelectableTraits::installed_const_iterator installed_const_iterator;
54 typedef SelectableTraits::installed_size_type installed_size_type;
56 typedef SelectableTraits::PickList PickList;
59 template <class TIterator>
60 Impl( const ResKind & kind_r,
61 const std::string & name_r,
64 : _ident( sat::Solvable::SplitIdent( kind_r, name_r ).ident() )
68 for_( it, begin_r, end_r )
70 if ( it->status().isInstalled() )
71 _installedItems.insert( *it );
73 _availableItems.insert( *it );
79 IdString ident() const
87 const std::string & name() const
91 Status status() const;
94 bool setStatus( Status state_r, ResStatus::TransactByValue causer_r );
96 /** Installed object (transacting ot highest version). */
97 PoolItem installedObj() const
99 if ( installedEmpty() )
101 PoolItem ret( transactingInstalled() );
102 return ret ? ret : *_installedItems.begin();
105 /** Best among available objects.
106 * The transacting candidate or the one scheduled to receive
109 PoolItem candidateObj() const
111 PoolItem ret( transactingCandidate() );
113 ret = _candidate ? _candidate : defaultCandidate();
117 /** Set a userCandidate (out of available objects).
118 * \return The new userCandidate or NULL if choice was invalid
119 * (not among availableObjs).
121 PoolItem setCandidate( const PoolItem & newCandidate_r, ResStatus::TransactByValue causer_r );
123 /** The best candidate provided by a specific \ref Repository, if there is one.
124 * In contrary to \ref candidateObj, this may return no item even if
125 * there are available objects. This simply means the \ref Repository
126 * does not provide this object.
128 PoolItem candidateObjFrom( Repository repo_r ) const
130 for ( const PoolItem & pi : available() )
132 if ( pi.isRetracted() )
134 if ( pi.repository() == repo_r )
140 /** The best candidate for update, if there is one.
141 * In contrary to \ref candidateObj, this may return no item even if
142 * there are available objects. This simply means the best object is
143 * already installed, and all available objects violate at least one
146 PoolItem updateCandidateObj() const
148 PoolItem defaultCand( defaultCandidate() );
150 // multiversionInstall: This returns the candidate for the last
151 // instance installed. Actually we'd need a list here.
153 if ( ! defaultCand || defaultCand.isRetracted() )
156 if ( installedEmpty() )
158 // Here: installed and defaultCand are non NULL and it's not a
159 // multiversion install.
161 PoolItem installed( installedObj() );
162 // check vendor change
163 if ( ! ( ResPool::instance().resolver().allowVendorChange()
164 || VendorAttr::instance().equivalent( defaultCand->vendor(), installed->vendor() ) ) )
167 // check arch change (arch noarch changes are allowed)
168 if ( defaultCand->arch() != installed->arch()
169 && ! ( defaultCand->arch() == Arch_noarch || installed->arch() == Arch_noarch ) )
172 // check greater edition
173 if ( defaultCand->edition() <= installed->edition() )
179 /** \copydoc Selectable::highestAvailableVersionObj()const */
180 PoolItem highestAvailableVersionObj() const
183 bool retractedOk = false;
184 for ( const PoolItem & pi : available() )
186 if ( !retractedOk && pi.isRetracted() )
189 break; // prefer a not retracted candidate
192 if ( !ret || pi.edition() > ret.edition() )
198 /** \copydoc Selectable::identIsAutoInstalled()const */
199 bool identIsAutoInstalled() const
200 { return sat::Solvable::identIsAutoInstalled( ident() ); }
202 /** \copydoc Selectable::identicalAvailable( const PoolItem & )const */
203 bool identicalAvailable( const PoolItem & rhs ) const
204 { return bool(identicalAvailableObj( rhs )); }
206 /** \copydoc Selectable::identicalInstalled( const PoolItem & )const */
207 bool identicalInstalled( const PoolItem & rhs ) const
208 { return bool(identicalInstalledObj( rhs )); }
210 /** \copydoc Selectable::identicalAvailableObj( const PoolItem & rhs ) const */
211 PoolItem identicalAvailableObj( const PoolItem & rhs ) const
213 if ( !availableEmpty() && rhs )
215 for_( it, _availableItems.begin(), _availableItems.end() )
217 if ( identical( *it, rhs ) )
224 /** \copydoc Selectable::identicalInstalledObj( const PoolItem & rhs ) const */
225 PoolItem identicalInstalledObj( const PoolItem & rhs ) const
227 if ( !installedEmpty() && rhs )
229 for_( it, _installedItems.begin(), _installedItems.end() )
231 if ( identical( *it, rhs ) )
238 /** Best among all objects. */
239 PoolItem theObj() const
241 PoolItem ret( candidateObj() );
244 return installedObj();
247 ////////////////////////////////////////////////////////////////////////
249 bool availableEmpty() const
250 { return _availableItems.empty(); }
252 available_size_type availableSize() const
253 { return _availableItems.size(); }
255 available_iterator availableBegin() const
256 { return _availableItems.begin(); }
258 available_iterator availableEnd() const
259 { return _availableItems.end(); }
261 inline Iterable<available_iterator> available() const
262 { return makeIterable( availableBegin(), availableEnd() ); }
264 ////////////////////////////////////////////////////////////////////////
266 bool installedEmpty() const
267 { return _installedItems.empty(); }
269 installed_size_type installedSize() const
270 { return _installedItems.size(); }
272 installed_iterator installedBegin() const
273 { return _installedItems.begin(); }
275 installed_iterator installedEnd() const
276 { return _installedItems.end(); }
278 inline Iterable<installed_iterator> installed() const
279 { return makeIterable( installedBegin(), installedEnd() ); }
281 ////////////////////////////////////////////////////////////////////////
283 const PickList & picklist() const
285 if ( ! _picklistPtr )
287 _picklistPtr.reset( new PickList );
288 // installed without identical avaialble first:
289 for ( const PoolItem & pi : installed() )
291 if ( ! identicalAvailable( pi ) )
292 _picklistPtr->push_back( pi );
294 _picklistPtr->insert( _picklistPtr->end(), availableBegin(), availableEnd() );
296 return *_picklistPtr;
299 bool picklistEmpty() const
300 { return picklist().empty(); }
302 picklist_size_type picklistSize() const
303 { return picklist().size(); }
305 picklist_iterator picklistBegin() const
306 { return picklist().begin(); }
308 picklist_iterator picklistEnd() const
309 { return picklist().end(); }
311 ////////////////////////////////////////////////////////////////////////
313 bool hasRetracted() const
314 { return !_availableItems.empty() && _availableItems.rbegin()->isRetracted(); }
316 bool hasRetractedInstalled() const
319 if ( hasRetracted() )
321 for ( const PoolItem & ipi : installed() )
323 PoolItem pi { identicalAvailableObj( ipi ) };
324 if ( pi && pi.isRetracted() )
332 // later if pool index is available:
333 // for ( const PoolItem & pi : installed() )
334 // if ( pi.isRetracted() )
339 bool isUnmaintained() const
340 { return availableEmpty(); }
342 bool multiversionInstall() const
344 for ( const PoolItem & pi : picklist() )
346 if ( pi.multiversionInstall() )
352 bool pickInstall( const PoolItem & pi_r, ResStatus::TransactByValue causer_r, bool yesno_r );
354 bool pickDelete( const PoolItem & pi_r, ResStatus::TransactByValue causer_r, bool yesno_r );
356 Status pickStatus( const PoolItem & pi_r ) const;
358 bool setPickStatus( const PoolItem & pi_r, Status state_r, ResStatus::TransactByValue causer_r );
360 ////////////////////////////////////////////////////////////////////////
362 bool isUndetermined() const
364 PoolItem cand( candidateObj() );
365 return ! cand || cand.isUndetermined();
367 bool isRelevant() const
369 PoolItem cand( candidateObj() );
370 return cand && cand.isRelevant();
372 bool isSatisfied() const
374 PoolItem cand( candidateObj() );
375 return cand && cand.isSatisfied();
377 bool isBroken() const
379 PoolItem cand( candidateObj() );
380 return cand && cand.isBroken();
383 /** Return who caused the modification. */
384 ResStatus::TransactByValue modifiedBy() const;
386 /** Return value of LicenceConfirmed bit. */
387 bool hasLicenceConfirmed() const
388 { return candidateObj() && candidateObj().status().isLicenceConfirmed(); }
390 /** Set LicenceConfirmed bit. */
391 void setLicenceConfirmed( bool val_r )
392 { if ( candidateObj() ) candidateObj().status().setLicenceConfirmed( val_r ); }
394 /** \copydoc Selectable::hasLocks()const */
395 bool hasLocks() const
397 for ( const PoolItem & pi : available() )
399 if ( pi.status().isLocked() )
402 for ( const PoolItem & pi : installed() )
404 if ( pi.status().isLocked() )
411 PoolItem transactingInstalled() const
413 for ( const PoolItem & pi : installed() )
415 if ( pi.status().transacts() )
421 PoolItem transactingCandidate() const
423 for ( const PoolItem & pi : available() )
425 if ( pi.status().transacts() )
431 PoolItem defaultCandidate() const
433 if ( ! installedEmpty() )
435 // prefer the installed objects arch and vendor
436 bool solver_allowVendorChange( ResPool::instance().resolver().allowVendorChange() );
437 for ( const PoolItem & ipi : installed() )
439 PoolItem sameArch; // in case there's no same vendor at least stay with same arch.
440 for ( const PoolItem & api : available() )
442 // 'same arch' includes allowed changes to/from noarch.
443 if ( ipi.arch() == api.arch() || ipi.arch() == Arch_noarch || api.arch() == Arch_noarch )
445 if ( ! solver_allowVendorChange )
447 if ( VendorAttr::instance().equivalent( ipi, api ) )
449 else if ( ! sameArch ) // remember best same arch in case no same vendor found
452 else // same arch is sufficient
460 if ( _availableItems.empty() )
463 return *_availableItems.begin();
466 bool allCandidatesLocked() const
468 for ( const PoolItem & pi : available() )
470 if ( ! pi.status().isLocked() )
473 return( ! _availableItems.empty() );
476 bool allInstalledLocked() const
478 for ( const PoolItem & pi : installed() )
480 if ( ! pi.status().isLocked() )
483 return( ! _installedItems.empty() );
488 const IdString _ident;
490 const std::string _name;
491 InstalledItemSet _installedItems;
492 AvailableItemSet _availableItems;
493 //! The object selected by setCandidateObj() method.
495 //! lazy initialized picklist
496 mutable scoped_ptr<PickList> _picklistPtr;
498 ///////////////////////////////////////////////////////////////////
500 /** \relates Selectable::Impl Stream output */
501 inline std::ostream & operator<<( std::ostream & str, const Selectable::Impl & obj )
503 return str << '[' << obj.kind() << ']' << obj.name() << ": " << obj.status()
504 << " (I " << obj.installedSize() << ")"
505 << " (A " << obj.availableSize() << ")"
506 << obj.candidateObj();
509 /** \relates Selectable::Impl Stream output */
510 inline std::ostream & dumpOn( std::ostream & str, const Selectable::Impl & obj )
512 str << '[' << obj.kind() << ']' << obj.name() << ": " << obj.status()
513 << ( obj.multiversionInstall() ? " (multiversion)" : "") << endl;
515 if ( obj.installedEmpty() )
516 str << " (I 0) {}" << endl << " ";
519 PoolItem icand( obj.installedObj() );
520 str << " (I " << obj.installedSize() << ") {" << endl;
521 for ( const PoolItem & pi : obj.installed() )
528 str << " " << t << " " << pi << endl;
533 if ( obj.availableEmpty() )
535 str << "(A 0) {}" << endl << " ";
539 PoolItem cand( obj.candidateObj() );
540 PoolItem up( obj.updateCandidateObj() );
541 str << "(A " << obj.availableSize() << ") {" << endl;
542 for ( const PoolItem & pi : obj.available() )
547 t = pi == up ? 'C' : 'c';
553 str << " " << t << " " << pi << endl;
558 if ( obj.picklistEmpty() )
564 PoolItem cand( obj.candidateObj() );
565 PoolItem up( obj.updateCandidateObj() );
566 str << "(P " << obj.picklistSize() << ") {" << endl;
567 for ( const PoolItem & pi : obj.picklist() )
572 t = pi == up ? 'C' : 'c';
578 str << " " << t << " " << pi << "\t" << obj.pickStatus( pi ) << endl;
585 /////////////////////////////////////////////////////////////////
587 ///////////////////////////////////////////////////////////////////
588 /////////////////////////////////////////////////////////////////
590 ///////////////////////////////////////////////////////////////////
591 #endif // ZYPP_UI_SELECTABLEIMPL_H