libzypp
10.5.0
|
00001 /*---------------------------------------------------------------------\ 00002 | ____ _ __ __ ___ | 00003 | |__ / \ / / . \ . \ | 00004 | / / \ V /| _/ _/ | 00005 | / /__ | | | | | | | 00006 | /_____||_| |_| |_| | 00007 | | 00008 \---------------------------------------------------------------------*/ 00012 #ifndef ZYPP_UI_SELECTABLEIMPL_H 00013 #define ZYPP_UI_SELECTABLEIMPL_H 00014 00015 #include <iostream> 00016 #include "zypp/base/LogTools.h" 00017 00018 #include "zypp/base/PtrTypes.h" 00019 00020 #include "zypp/ResPool.h" 00021 #include "zypp/Resolver.h" 00022 #include "zypp/ui/Selectable.h" 00023 #include "zypp/ui/SelectableTraits.h" 00024 00025 using std::endl; 00026 00028 namespace zypp 00029 { 00030 00031 namespace ui 00032 { 00033 00035 // 00036 // CLASS NAME : Selectable::Impl 00037 // 00042 struct Selectable::Impl 00043 { 00044 public: 00045 00046 typedef SelectableTraits::AvailableItemSet AvailableItemSet; 00047 typedef SelectableTraits::available_iterator available_iterator; 00048 typedef SelectableTraits::available_const_iterator available_const_iterator; 00049 typedef SelectableTraits::available_size_type available_size_type; 00050 00051 typedef SelectableTraits::InstalledItemSet InstalledItemSet; 00052 typedef SelectableTraits::installed_iterator installed_iterator; 00053 typedef SelectableTraits::installed_const_iterator installed_const_iterator; 00054 typedef SelectableTraits::installed_size_type installed_size_type; 00055 00056 typedef SelectableTraits::PickList PickList; 00057 00058 public: 00059 template <class _Iterator> 00060 Impl( const ResObject::Kind & kind_r, 00061 const std::string & name_r, 00062 _Iterator begin_r, 00063 _Iterator end_r ) 00064 : _ident( sat::Solvable::SplitIdent( kind_r, name_r ).ident() ) 00065 , _kind( kind_r ) 00066 , _name( name_r ) 00067 { 00068 for_( it, begin_r, end_r ) 00069 { 00070 if ( it->status().isInstalled() ) 00071 _installedItems.insert( *it ); 00072 else 00073 _availableItems.insert( *it ); 00074 } 00075 } 00076 00077 public: 00079 IdString ident() const 00080 { return _ident; } 00081 00083 ResObject::Kind kind() const 00084 { return _kind; } 00085 00087 const std::string & name() const 00088 { return _name; } 00089 00091 Status status() const; 00092 00094 bool setStatus( Status state_r, ResStatus::TransactByValue causer_r ); 00095 00097 PoolItem installedObj() const 00098 { 00099 if ( installedEmpty() ) 00100 return PoolItem(); 00101 PoolItem ret( transactingInstalled() ); 00102 return ret ? ret : *_installedItems.begin(); 00103 } 00104 00109 PoolItem candidateObj() const 00110 { 00111 PoolItem ret( transactingCandidate() ); 00112 if ( ret ) 00113 return ret; 00114 return _candidate ? _candidate : defaultCandidate(); 00115 } 00116 00121 PoolItem setCandidate( const PoolItem & newCandidate_r, ResStatus::TransactByValue causer_r ); 00122 00128 PoolItem candidateObjFrom( Repository repo_r ) const 00129 { 00130 for_( it, availableBegin(), availableEnd() ) 00131 { 00132 if ( (*it)->repository() == repo_r ) 00133 return *it; 00134 } 00135 return PoolItem(); 00136 } 00137 00144 PoolItem updateCandidateObj() const 00145 { 00146 PoolItem defaultCand( defaultCandidate() ); 00147 00148 if ( multiversionInstall() ) 00149 return identicalInstalled( defaultCand ) ? PoolItem() : defaultCand; 00150 00151 if ( installedEmpty() || ! defaultCand ) 00152 return defaultCand; 00153 // Here: installed and defaultCand are non NULL and it's not a 00154 // multiversion install. 00155 00156 // update candidate must come from the highest priority repo 00157 if ( defaultCand->repoInfo().priority() != (*availableBegin())->repoInfo().priority() ) 00158 return PoolItem(); 00159 00160 PoolItem installed( installedObj() ); 00161 // check vendor change 00162 if ( ! ( ResPool::instance().resolver().allowVendorChange() 00163 || VendorAttr::instance().equivalent( defaultCand->vendor(), installed->vendor() ) ) ) 00164 return PoolItem(); 00165 00166 // check arch change (arch noarch changes are allowed) 00167 if ( defaultCand->arch() != installed->arch() 00168 && ! ( defaultCand->arch() == Arch_noarch || installed->arch() == Arch_noarch ) ) 00169 return PoolItem(); 00170 00171 // check greater edition 00172 if ( defaultCand->edition() <= installed->edition() ) 00173 return PoolItem(); 00174 00175 return defaultCand; 00176 } 00177 00179 PoolItem highestAvailableVersionObj() const 00180 { 00181 PoolItem ret; 00182 for_( it, availableBegin(), availableEnd() ) 00183 { 00184 if ( !ret || (*it).satSolvable().edition() > ret.satSolvable().edition() ) 00185 ret = *it; 00186 } 00187 return ret; 00188 } 00189 00191 bool identicalAvailable( const PoolItem & rhs ) const 00192 { return identicalAvailableObj( rhs ); } 00193 00195 bool identicalInstalled( const PoolItem & rhs ) const 00196 { return identicalInstalledObj( rhs ); } 00197 00199 PoolItem identicalAvailableObj( const PoolItem & rhs ) const 00200 { 00201 if ( !availableEmpty() && rhs ) 00202 { 00203 for_( it, _availableItems.begin(), _availableItems.end() ) 00204 { 00205 if ( identical( *it, rhs ) ) 00206 return *it; 00207 } 00208 } 00209 return PoolItem(); 00210 } 00211 00213 PoolItem identicalInstalledObj( const PoolItem & rhs ) const 00214 { 00215 if ( !installedEmpty() && rhs ) 00216 { 00217 for_( it, _installedItems.begin(), _installedItems.end() ) 00218 { 00219 if ( identical( *it, rhs ) ) 00220 return *it; 00221 } 00222 } 00223 return PoolItem(); 00224 } 00225 00227 PoolItem theObj() const 00228 { 00229 PoolItem ret( candidateObj() ); 00230 if ( ret ) 00231 return ret; 00232 return installedObj(); 00233 } 00234 00236 00237 bool availableEmpty() const 00238 { return _availableItems.empty(); } 00239 00240 available_size_type availableSize() const 00241 { return _availableItems.size(); } 00242 00243 available_const_iterator availableBegin() const 00244 { return _availableItems.begin(); } 00245 00246 available_const_iterator availableEnd() const 00247 { return _availableItems.end(); } 00248 00250 00251 bool installedEmpty() const 00252 { return _installedItems.empty(); } 00253 00254 installed_size_type installedSize() const 00255 { return _installedItems.size(); } 00256 00257 installed_iterator installedBegin() const 00258 { return _installedItems.begin(); } 00259 00260 installed_iterator installedEnd() const 00261 { return _installedItems.end(); } 00262 00264 00265 const PickList & picklist() const 00266 { 00267 if ( ! _picklistPtr ) 00268 { 00269 _picklistPtr.reset( new PickList ); 00270 // installed without identical avaialble first: 00271 for_( it, _installedItems.begin(), _installedItems.end() ) 00272 { 00273 if ( ! identicalAvailable( *it ) ) 00274 _picklistPtr->push_back( *it ); 00275 } 00276 _picklistPtr->insert( _picklistPtr->end(), availableBegin(), availableEnd() ); 00277 } 00278 return *_picklistPtr; 00279 } 00280 00281 bool picklistEmpty() const 00282 { return picklist().empty(); } 00283 00284 picklist_size_type picklistSize() const 00285 { return picklist().size(); } 00286 00287 picklist_iterator picklistBegin() const 00288 { return picklist().begin(); } 00289 00290 picklist_iterator picklistEnd() const 00291 { return picklist().end(); } 00292 00294 00295 bool isUnmaintained() const 00296 { return availableEmpty(); } 00297 00298 bool multiversionInstall() const 00299 { return sat::Pool::instance().isMultiversion( ident() ); } 00300 00301 bool pickInstall( const PoolItem & pi_r, ResStatus::TransactByValue causer_r, bool yesno_r ); 00302 00303 bool pickDelete( const PoolItem & pi_r, ResStatus::TransactByValue causer_r, bool yesno_r ); 00304 00305 Status pickStatus( const PoolItem & pi_r ) const; 00306 00307 bool setPickStatus( const PoolItem & pi_r, Status state_r, ResStatus::TransactByValue causer_r ); 00308 00310 00311 bool isUndetermined() const 00312 { 00313 PoolItem cand( candidateObj() ); 00314 return ! cand || cand.isUndetermined(); 00315 } 00316 bool isRelevant() const 00317 { 00318 PoolItem cand( candidateObj() ); 00319 return cand && cand.isRelevant(); 00320 } 00321 bool isSatisfied() const 00322 { 00323 PoolItem cand( candidateObj() ); 00324 return cand && cand.isSatisfied(); 00325 } 00326 bool isBroken() const 00327 { 00328 PoolItem cand( candidateObj() ); 00329 return cand && cand.isBroken(); 00330 } 00331 00333 ResStatus::TransactByValue modifiedBy() const; 00334 00336 bool hasLicenceConfirmed() const 00337 { return candidateObj() && candidateObj().status().isLicenceConfirmed(); } 00338 00340 void setLicenceConfirmed( bool val_r ) 00341 { if ( candidateObj() ) candidateObj().status().setLicenceConfirmed( val_r ); } 00342 00343 private: 00344 PoolItem transactingInstalled() const 00345 { 00346 for_( it, installedBegin(), installedEnd() ) 00347 { 00348 if ( (*it).status().transacts() ) 00349 return (*it); 00350 } 00351 return PoolItem(); 00352 } 00353 00354 PoolItem transactingCandidate() const 00355 { 00356 for_( it, availableBegin(), availableEnd() ) 00357 { 00358 if ( (*it).status().transacts() ) 00359 return (*it); 00360 } 00361 return PoolItem(); 00362 } 00363 00364 PoolItem defaultCandidate() const 00365 { 00366 if ( ! ( multiversionInstall() || installedEmpty() ) ) 00367 { 00368 // prefer the installed objects arch and vendor 00369 bool solver_allowVendorChange( ResPool::instance().resolver().allowVendorChange() ); 00370 for ( installed_const_iterator iit = installedBegin(); 00371 iit != installedEnd(); ++iit ) 00372 { 00373 PoolItem sameArch; // in case there's no same vendor at least stay with same arch. 00374 for ( available_const_iterator it = availableBegin(); 00375 it != availableEnd(); ++it ) 00376 { 00377 // 'same arch' includes allowed changes to/from noarch. 00378 if ( (*iit)->arch() == (*it)->arch() || (*iit)->arch() == Arch_noarch || (*it)->arch() == Arch_noarch ) 00379 { 00380 if ( ! solver_allowVendorChange ) 00381 { 00382 if ( VendorAttr::instance().equivalent( (*iit), (*it) ) ) 00383 return *it; 00384 else if ( ! sameArch ) // remember best same arch in case no same vendor found 00385 sameArch = *it; 00386 } 00387 else // same arch is sufficient 00388 return *it; 00389 } 00390 } 00391 if ( sameArch ) 00392 return sameArch; 00393 } 00394 } 00395 if ( _availableItems.empty() ) 00396 return PoolItem(); 00397 00398 return *_availableItems.begin(); 00399 } 00400 00401 bool allCandidatesLocked() const 00402 { 00403 for ( available_const_iterator it = availableBegin(); 00404 it != availableEnd(); ++it ) 00405 { 00406 if ( ! (*it).status().isLocked() ) 00407 return false; 00408 } 00409 return( ! _availableItems.empty() ); 00410 } 00411 00412 bool allInstalledLocked() const 00413 { 00414 for ( installed_const_iterator it = installedBegin(); 00415 it != installedEnd(); ++it ) 00416 { 00417 if ( ! (*it).status().isLocked() ) 00418 return false; 00419 } 00420 return( ! _installedItems.empty() ); 00421 } 00422 00423 00424 private: 00425 const IdString _ident; 00426 const ResObject::Kind _kind; 00427 const std::string _name; 00428 InstalledItemSet _installedItems; 00429 AvailableItemSet _availableItems; 00431 PoolItem _candidate; 00433 mutable scoped_ptr<PickList> _picklistPtr; 00434 }; 00436 00438 inline std::ostream & operator<<( std::ostream & str, const Selectable::Impl & obj ) 00439 { 00440 return str << '[' << obj.kind() << ']' << obj.name() << ": " << obj.status() 00441 << " (I " << obj.installedSize() << ")" 00442 << " (A " << obj.availableSize() << ")" 00443 << obj.candidateObj(); 00444 } 00445 00447 inline std::ostream & dumpOn( std::ostream & str, const Selectable::Impl & obj ) 00448 { 00449 str << '[' << obj.kind() << ']' << obj.name() << ": " << obj.status() 00450 << ( obj.multiversionInstall() ? " (multiversion)" : "") << endl; 00451 00452 if ( obj.installedEmpty() ) 00453 str << " (I 0) {}" << endl << " "; 00454 else 00455 { 00456 PoolItem icand( obj.installedObj() ); 00457 str << " (I " << obj.installedSize() << ") {" << endl; 00458 for_( it, obj.installedBegin(), obj.installedEnd() ) 00459 { 00460 char t = ' '; 00461 if ( *it == icand ) 00462 { 00463 t = 'i'; 00464 } 00465 str << " " << t << " " << *it << endl; 00466 } 00467 str << "} "; 00468 } 00469 00470 if ( obj.availableEmpty() ) 00471 { 00472 str << "(A 0) {}" << endl << " "; 00473 } 00474 else 00475 { 00476 PoolItem cand( obj.candidateObj() ); 00477 PoolItem up( obj.updateCandidateObj() ); 00478 str << "(A " << obj.availableSize() << ") {" << endl; 00479 for_( it, obj.availableBegin(), obj.availableEnd() ) 00480 { 00481 char t = ' '; 00482 if ( *it == cand ) 00483 { 00484 t = *it == up ? 'C' : 'c'; 00485 } 00486 else if ( *it == up ) 00487 { 00488 t = 'u'; 00489 } 00490 str << " " << t << " " << *it << endl; 00491 } 00492 str << "} "; 00493 } 00494 00495 if ( obj.picklistEmpty() ) 00496 { 00497 str << "(P 0) {}"; 00498 } 00499 else 00500 { 00501 PoolItem cand( obj.candidateObj() ); 00502 PoolItem up( obj.updateCandidateObj() ); 00503 str << "(P " << obj.picklistSize() << ") {" << endl; 00504 for_( it, obj.picklistBegin(), obj.picklistEnd() ) 00505 { 00506 char t = ' '; 00507 if ( *it == cand ) 00508 { 00509 t = *it == up ? 'C' : 'c'; 00510 } 00511 else if ( *it == up ) 00512 { 00513 t = 'u'; 00514 } 00515 str << " " << t << " " << *it << "\t" << obj.pickStatus( *it ) << endl; 00516 } 00517 str << "} "; 00518 } 00519 00520 return str; 00521 } 00523 } // namespace ui 00526 } // namespace zypp 00528 #endif // ZYPP_UI_SELECTABLEIMPL_H