libzypp 8.13.6
|
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/ZConfig.h" 00021 #include "zypp/ui/Selectable.h" 00022 #include "zypp/ui/SelectableTraits.h" 00023 00024 using std::endl; 00025 00027 namespace zypp 00028 { 00029 00030 namespace ui 00031 { 00032 00034 // 00035 // CLASS NAME : Selectable::Impl 00036 // 00041 struct Selectable::Impl 00042 { 00043 public: 00044 00045 typedef SelectableTraits::AvailableItemSet AvailableItemSet; 00046 typedef SelectableTraits::available_iterator available_iterator; 00047 typedef SelectableTraits::available_const_iterator available_const_iterator; 00048 typedef SelectableTraits::available_size_type available_size_type; 00049 00050 typedef SelectableTraits::InstalledItemSet InstalledItemSet; 00051 typedef SelectableTraits::installed_iterator installed_iterator; 00052 typedef SelectableTraits::installed_const_iterator installed_const_iterator; 00053 typedef SelectableTraits::installed_size_type installed_size_type; 00054 00055 typedef SelectableTraits::PickList PickList; 00056 00057 public: 00058 template <class _Iterator> 00059 Impl( const ResObject::Kind & kind_r, 00060 const std::string & name_r, 00061 _Iterator begin_r, 00062 _Iterator end_r ) 00063 : _ident( sat::Solvable::SplitIdent( kind_r, name_r ).ident() ) 00064 , _kind( kind_r ) 00065 , _name( name_r ) 00066 { 00067 for_( it, begin_r, end_r ) 00068 { 00069 if ( it->status().isInstalled() ) 00070 _installedItems.insert( *it ); 00071 else 00072 _availableItems.insert( *it ); 00073 } 00074 _defaultCandidate = defaultCandidate(); 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 if ( multiversionInstall() || installedEmpty() || ! _defaultCandidate ) 00147 return _defaultCandidate; 00148 // Here: installed and _defaultCandidate are non NULL and it's not a 00149 // multiversion install. 00150 00151 // update candidate must come from the highest priority repo 00152 if ( _defaultCandidate->repoInfo().priority() != (*availableBegin())->repoInfo().priority() ) 00153 return PoolItem(); 00154 00155 PoolItem installed( installedObj() ); 00156 // check vendor change 00157 if ( ! ( ZConfig::instance().solver_allowVendorChange() 00158 || VendorAttr::instance().equivalent( _defaultCandidate->vendor(), installed->vendor() ) ) ) 00159 return PoolItem(); 00160 00161 // check arch change (arch noarch changes are allowed) 00162 if ( _defaultCandidate->arch() != installed->arch() 00163 && ! ( _defaultCandidate->arch() == Arch_noarch || installed->arch() == Arch_noarch ) ) 00164 return PoolItem(); 00165 00166 // check greater edition 00167 if ( _defaultCandidate->edition() <= installed->edition() ) 00168 return PoolItem(); 00169 00170 return _defaultCandidate; 00171 } 00172 00174 PoolItem highestAvailableVersionObj() const 00175 { 00176 PoolItem ret; 00177 for_( it, availableBegin(), availableEnd() ) 00178 { 00179 if ( !ret || (*it).satSolvable().edition() > ret.satSolvable().edition() ) 00180 ret = *it; 00181 } 00182 return ret; 00183 } 00184 00186 bool identicalAvailable( const PoolItem & rhs ) const 00187 { 00188 if ( !availableEmpty() && rhs ) 00189 { 00190 for_( it, _availableItems.begin(), _availableItems.end() ) 00191 { 00192 if ( identical( *it, rhs ) ) 00193 return true; 00194 } 00195 } 00196 return false; 00197 } 00198 00200 bool identicalInstalled( const PoolItem & rhs ) const 00201 { 00202 if ( !installedEmpty() && rhs ) 00203 { 00204 for_( it, _installedItems.begin(), _installedItems.end() ) 00205 { 00206 if ( identical( *it, rhs ) ) 00207 return true; 00208 } 00209 } 00210 return false; 00211 } 00212 00214 PoolItem theObj() const 00215 { 00216 PoolItem ret( candidateObj() ); 00217 if ( ret ) 00218 return ret; 00219 return installedObj(); 00220 } 00221 00223 00224 bool availableEmpty() const 00225 { return _availableItems.empty(); } 00226 00227 available_size_type availableSize() const 00228 { return _availableItems.size(); } 00229 00230 available_const_iterator availableBegin() const 00231 { return _availableItems.begin(); } 00232 00233 available_const_iterator availableEnd() const 00234 { return _availableItems.end(); } 00235 00237 00238 bool installedEmpty() const 00239 { return _installedItems.empty(); } 00240 00241 installed_size_type installedSize() const 00242 { return _installedItems.size(); } 00243 00244 installed_iterator installedBegin() const 00245 { return _installedItems.begin(); } 00246 00247 installed_iterator installedEnd() const 00248 { return _installedItems.end(); } 00249 00251 00252 const PickList & picklist() const 00253 { 00254 if ( ! _picklistPtr ) 00255 { 00256 _picklistPtr.reset( new PickList ); 00257 // installed without identical avaialble first: 00258 for_( it, _installedItems.begin(), _installedItems.end() ) 00259 { 00260 if ( ! identicalAvailable( *it ) ) 00261 _picklistPtr->push_back( *it ); 00262 } 00263 _picklistPtr->insert( _picklistPtr->end(), availableBegin(), availableEnd() ); 00264 } 00265 return *_picklistPtr; 00266 } 00267 00268 bool picklistEmpty() const 00269 { return picklist().empty(); } 00270 00271 picklist_size_type picklistSize() const 00272 { return picklist().size(); } 00273 00274 picklist_iterator picklistBegin() const 00275 { return picklist().begin(); } 00276 00277 picklist_iterator picklistEnd() const 00278 { return picklist().end(); } 00279 00281 00282 bool isUnmaintained() const 00283 { return availableEmpty(); } 00284 00285 bool multiversionInstall() const 00286 { return theObj().satSolvable().multiversionInstall(); } 00287 00288 bool pickInstall( const PoolItem & pi_r, ResStatus::TransactByValue causer_r, bool yesno_r ); 00289 00290 bool pickDelete( const PoolItem & pi_r, ResStatus::TransactByValue causer_r, bool yesno_r ); 00291 00292 Status pickStatus( const PoolItem & pi_r ) const; 00293 00294 bool setPickStatus( const PoolItem & pi_r, Status state_r, ResStatus::TransactByValue causer_r ); 00295 00297 00298 bool isUndetermined() const 00299 { 00300 PoolItem cand( candidateObj() ); 00301 return ! cand || cand.isUndetermined(); 00302 } 00303 bool isRelevant() const 00304 { 00305 PoolItem cand( candidateObj() ); 00306 return cand && cand.isRelevant(); 00307 } 00308 bool isSatisfied() const 00309 { 00310 PoolItem cand( candidateObj() ); 00311 return cand && cand.isSatisfied(); 00312 } 00313 bool isBroken() const 00314 { 00315 PoolItem cand( candidateObj() ); 00316 return cand && cand.isBroken(); 00317 } 00318 00320 ResStatus::TransactByValue modifiedBy() const; 00321 00323 bool hasLicenceConfirmed() const 00324 { return candidateObj() && candidateObj().status().isLicenceConfirmed(); } 00325 00327 void setLicenceConfirmed( bool val_r ) 00328 { if ( candidateObj() ) candidateObj().status().setLicenceConfirmed( val_r ); } 00329 00330 private: 00331 PoolItem transactingInstalled() const 00332 { 00333 for_( it, installedBegin(), installedEnd() ) 00334 { 00335 if ( (*it).status().transacts() ) 00336 return (*it); 00337 } 00338 return PoolItem(); 00339 } 00340 00341 PoolItem transactingCandidate() const 00342 { 00343 for_( it, availableBegin(), availableEnd() ) 00344 { 00345 if ( (*it).status().transacts() ) 00346 return (*it); 00347 } 00348 return PoolItem(); 00349 } 00350 00351 PoolItem defaultCandidate() const 00352 { 00353 if ( ! ( multiversionInstall() || installedEmpty() ) ) 00354 { 00355 // prefer the installed objects arch and vendor 00356 bool solver_allowVendorChange( ZConfig::instance().solver_allowVendorChange() ); 00357 for ( installed_const_iterator iit = installedBegin(); 00358 iit != installedEnd(); ++iit ) 00359 { 00360 PoolItem sameArch; // in case there's no same vendor at least stay with same arch. 00361 for ( available_const_iterator it = availableBegin(); 00362 it != availableEnd(); ++it ) 00363 { 00364 // 'same arch' includes allowed changes to/from noarch. 00365 if ( (*iit)->arch() == (*it)->arch() || (*iit)->arch() == Arch_noarch || (*it)->arch() == Arch_noarch ) 00366 { 00367 if ( ! solver_allowVendorChange ) 00368 { 00369 if ( VendorAttr::instance().equivalent( (*iit), (*it) ) ) 00370 return *it; 00371 else if ( ! sameArch ) // remember best same arch in case no same vendor found 00372 sameArch = *it; 00373 } 00374 else // same arch is sufficient 00375 return *it; 00376 } 00377 } 00378 if ( sameArch ) 00379 return sameArch; 00380 } 00381 } 00382 if ( _availableItems.empty() ) 00383 return PoolItem(); 00384 00385 return *_availableItems.begin(); 00386 } 00387 00388 bool allCandidatesLocked() const 00389 { 00390 for ( available_const_iterator it = availableBegin(); 00391 it != availableEnd(); ++it ) 00392 { 00393 if ( ! (*it).status().isLocked() ) 00394 return false; 00395 } 00396 return( ! _availableItems.empty() ); 00397 } 00398 00399 bool allInstalledLocked() const 00400 { 00401 for ( installed_const_iterator it = installedBegin(); 00402 it != installedEnd(); ++it ) 00403 { 00404 if ( ! (*it).status().isLocked() ) 00405 return false; 00406 } 00407 return( ! _installedItems.empty() ); 00408 } 00409 00410 00411 private: 00412 const IdString _ident; 00413 const ResObject::Kind _kind; 00414 const std::string _name; 00415 InstalledItemSet _installedItems; 00416 AvailableItemSet _availableItems; 00418 PoolItem _defaultCandidate; 00420 PoolItem _candidate; 00422 mutable scoped_ptr<PickList> _picklistPtr; 00423 }; 00425 00427 inline std::ostream & operator<<( std::ostream & str, const Selectable::Impl & obj ) 00428 { 00429 return str << '[' << obj.kind() << ']' << obj.name() << ": " << obj.status() 00430 << " (I " << obj.installedSize() << ")" 00431 << " (A " << obj.availableSize() << ")" 00432 << obj.candidateObj(); 00433 } 00434 00436 inline std::ostream & dumpOn( std::ostream & str, const Selectable::Impl & obj ) 00437 { 00438 str << '[' << obj.kind() << ']' << obj.name() << ": " << obj.status() 00439 << ( obj.multiversionInstall() ? " (multiversion)" : "") << endl; 00440 00441 if ( obj.installedEmpty() ) 00442 str << " (I 0) {}" << endl << " "; 00443 else 00444 { 00445 PoolItem icand( obj.installedObj() ); 00446 str << " (I " << obj.installedSize() << ") {" << endl; 00447 for_( it, obj.installedBegin(), obj.installedEnd() ) 00448 { 00449 char t = ' '; 00450 if ( *it == icand ) 00451 { 00452 t = 'i'; 00453 } 00454 str << " " << t << " " << *it << endl; 00455 } 00456 str << "} "; 00457 } 00458 00459 if ( obj.availableEmpty() ) 00460 { 00461 str << "(A 0) {}" << endl << " "; 00462 } 00463 else 00464 { 00465 PoolItem cand( obj.candidateObj() ); 00466 PoolItem up( obj.updateCandidateObj() ); 00467 str << "(A " << obj.availableSize() << ") {" << endl; 00468 for_( it, obj.availableBegin(), obj.availableEnd() ) 00469 { 00470 char t = ' '; 00471 if ( *it == cand ) 00472 { 00473 t = *it == up ? 'C' : 'c'; 00474 } 00475 else if ( *it == up ) 00476 { 00477 t = 'u'; 00478 } 00479 str << " " << t << " " << *it << endl; 00480 } 00481 str << "} "; 00482 } 00483 00484 if ( obj.picklistEmpty() ) 00485 { 00486 str << "(P 0) {}"; 00487 } 00488 else 00489 { 00490 PoolItem cand( obj.candidateObj() ); 00491 PoolItem up( obj.updateCandidateObj() ); 00492 str << "(P " << obj.picklistSize() << ") {" << endl; 00493 for_( it, obj.picklistBegin(), obj.picklistEnd() ) 00494 { 00495 char t = ' '; 00496 if ( *it == cand ) 00497 { 00498 t = *it == up ? 'C' : 'c'; 00499 } 00500 else if ( *it == up ) 00501 { 00502 t = 'u'; 00503 } 00504 str << " " << t << " " << *it << "\t" << obj.pickStatus( *it ) << endl; 00505 } 00506 str << "} "; 00507 } 00508 00509 return str; 00510 } 00512 } // namespace ui 00515 } // namespace zypp 00517 #endif // ZYPP_UI_SELECTABLEIMPL_H