1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/sat/Solvable.cc
14 #include "zypp/base/Logger.h"
15 #include "zypp/base/Gettext.h"
16 #include "zypp/base/Exception.h"
17 #include "zypp/base/Functional.h"
18 #include "zypp/base/Collector.h"
20 #include "zypp/sat/detail/PoolImpl.h"
21 #include "zypp/sat/Solvable.h"
22 #include "zypp/sat/Pool.h"
23 #include "zypp/sat/LookupAttr.h"
25 #include "zypp/Repository.h"
26 #include "zypp/OnMediaLocation.h"
27 #include "zypp/ZConfig.h"
31 ///////////////////////////////////////////////////////////////////
33 { /////////////////////////////////////////////////////////////////
34 ///////////////////////////////////////////////////////////////////
36 { /////////////////////////////////////////////////////////////////
38 Solvable::SplitIdent::SplitIdent( IdString ident_r )
44 const char * ident = ident_r.c_str();
45 const char * sep = ::strchr( ident, ':' );
47 // no ':' in package names (hopefully)
50 _kind = ResKind::package;
56 _name = IdString( sep+1 );
57 // quick check for well known kinds
62 #define OUTS(K,S) if ( !::strncmp( ident, ResKind::K.c_str(), S ) ) _kind = ResKind::K
64 case 'c': OUTS( patch, 5 ); return; break;
65 case 'd': OUTS( product, 7 ); return; break;
66 case 'k': OUTS( package, 7 ); return; break;
67 case 'p': OUTS( srcpackage, 10 ); return; break;
68 case 't': OUTS( pattern, 7 ); return; break;
74 _kind = ResKind( std::string( ident, sep-ident ) );
77 Solvable::SplitIdent::SplitIdent( ResKind kind_r, IdString name_r )
81 if ( kind_r == ResKind::package || kind_r == ResKind::srcpackage )
84 _ident = IdString( str::form( "%s:%s", kind_r.c_str(), name_r.c_str() ) );
87 Solvable::SplitIdent::SplitIdent( ResKind kind_r, const C_Str & name_r )
91 if ( kind_r == ResKind::package || kind_r == ResKind::srcpackage )
94 _ident = IdString( str::form( "%s:%s", kind_r.c_str(), name_r.c_str() ) );
97 /////////////////////////////////////////////////////////////////
99 const Solvable Solvable::noSolvable;
101 /////////////////////////////////////////////////////////////////
103 ::_Solvable * Solvable::get() const
104 { return myPool().getSolvable( _id ); }
106 #define NO_SOLVABLE_RETURN( VAL ) \
107 ::_Solvable * _solvable( get() ); \
108 if ( ! _solvable ) return VAL
110 Solvable Solvable::nextInPool() const
111 { return Solvable( myPool().getNextId( _id ) ); }
113 Solvable Solvable::nextInRepo() const
115 NO_SOLVABLE_RETURN( noSolvable );
116 for ( detail::SolvableIdType next = _id+1; next < unsigned(_solvable->repo->end); ++next )
118 ::_Solvable * nextS( myPool().getSolvable( next ) );
119 if ( nextS && nextS->repo == _solvable->repo )
121 return Solvable( next );
127 Repository Solvable::repository() const
129 NO_SOLVABLE_RETURN( Repository::noRepository );
130 return Repository( _solvable->repo );
133 bool Solvable::isSystem() const
135 NO_SOLVABLE_RETURN( _id == detail::systemSolvableId );
136 return myPool().isSystemRepo( _solvable->repo );
139 IdString Solvable::ident() const
141 NO_SOLVABLE_RETURN( IdString() );
142 return IdString( _solvable->name );
145 std::string Solvable::lookupStrAttribute( const SolvAttr & attr ) const
147 NO_SOLVABLE_RETURN( std::string() );
148 const char * s = ::solvable_lookup_str( _solvable, attr.id() );
149 return s ? s : std::string();
152 std::string Solvable::lookupStrAttribute( const SolvAttr & attr, const Locale & lang_r ) const
154 NO_SOLVABLE_RETURN( std::string() );
156 if ( lang_r == Locale::noCode )
158 s = ::solvable_lookup_str_poollang( _solvable, attr.id() );
162 s = ::solvable_lookup_str_lang( _solvable, attr.id(), lang_r.code().c_str() );
164 return s ? s : std::string();
167 unsigned Solvable::lookupNumAttribute( const SolvAttr & attr ) const
169 NO_SOLVABLE_RETURN( 0 );
170 return ::solvable_lookup_num( _solvable, attr.id(), 0 );
173 bool Solvable::lookupBoolAttribute( const SolvAttr & attr ) const
175 NO_SOLVABLE_RETURN( false );
176 return ::solvable_lookup_bool( _solvable, attr.id() );
179 detail::IdType Solvable::lookupIdAttribute( const SolvAttr & attr ) const
181 NO_SOLVABLE_RETURN( detail::noId );
182 return ::solvable_lookup_id( _solvable, attr.id() );
185 CheckSum Solvable::lookupCheckSumAttribute( const SolvAttr & attr ) const
187 NO_SOLVABLE_RETURN( CheckSum() );
188 detail::IdType chksumtype = 0;
189 const char * s = ::solvable_lookup_checksum( _solvable, attr.id(), &chksumtype );
192 switch ( chksumtype )
194 case REPOKEY_TYPE_MD5: return CheckSum::md5( s );
195 case REPOKEY_TYPE_SHA1: return CheckSum::sha1( s );
196 case REPOKEY_TYPE_SHA256: return CheckSum::sha256( s );
198 return CheckSum( std::string(), s ); // try to autodetect
201 OnMediaLocation Solvable::lookupLocation() const
202 //std::string Solvable::lookupLocation( unsigned & medianr ) const
204 NO_SOLVABLE_RETURN( OnMediaLocation() );
205 // medianumber and path
207 char * file = ::solvable_get_location( _solvable, &medianr );
209 return OnMediaLocation();
214 static const sat::SolvAttr susetagsDatadir( "susetags:datadir" );
215 switch ( repository().info().type().toEnum() )
217 case repo::RepoType::NONE_e:
219 sat::LookupAttr datadir( susetagsDatadir, repository() );
220 if ( ! datadir.empty() )
222 repository().info().setProbedType( repo::RepoType::YAST2_e );
223 path = datadir.begin().asString();
225 path = datadir.empty() ? "suse" : datadir.begin().c_str();
229 case repo::RepoType::YAST2_e:
231 sat::LookupAttr datadir( susetagsDatadir, repository() );
232 path = datadir.empty() ? "suse" : datadir.begin().c_str();
239 ret.setLocation ( path/file, medianr );
240 ret.setDownloadSize( ByteCount( lookupNumAttribute( SolvAttr::downloadsize ), ByteCount::K ) );
241 ret.setChecksum ( lookupCheckSumAttribute( SolvAttr::checksum ) );
242 // Not needed/available for solvables?
243 //ret.setOpenSize ( ByteCount( lookupNumAttribute( SolvAttr::opensize ), ByteCount::K ) );
244 //ret.setOpenChecksum( lookupCheckSumAttribute( SolvAttr::openchecksum ) );
248 ResKind Solvable::kind() const
250 NO_SOLVABLE_RETURN( ResKind() );
251 // detect srcpackages by 'arch'
252 switch ( _solvable->arch )
256 return ResKind::srcpackage;
260 const char * ident = IdString( _solvable->name ).c_str();
261 const char * sep = ::strchr( ident, ':' );
263 // no ':' in package names (hopefully)
265 return ResKind::package;
267 // quick check for well known kinds
268 if ( sep-ident >= 4 )
272 #define OUTS(K,S) if ( !::strncmp( ident, ResKind::K.c_str(), S ) ) return ResKind::K
274 case 'c': OUTS( patch, 5 ); break;
275 case 'd': OUTS( product, 7 ); break;
276 case 'k': OUTS( package, 7 ); break;
277 case 'p': OUTS( srcpackage, 10 ); break;
278 case 't': OUTS( pattern, 7 ); break;
284 return ResKind( std::string( ident, sep-ident ) );
287 bool Solvable::isKind( const ResKind & kind_r ) const
289 NO_SOLVABLE_RETURN( false );
291 // detect srcpackages by 'arch'
292 switch ( _solvable->arch )
296 return( kind_r == ResKind::srcpackage );
300 // no ':' in package names (hopefully)
301 const char * ident = IdString( _solvable->name ).c_str();
302 if ( kind_r == ResKind::package )
304 return( ::strchr( ident, ':' ) == 0 );
307 // look for a 'kind:' prefix
308 const char * kind = kind_r.c_str();
309 unsigned ksize = ::strlen( kind );
310 return( ::strncmp( ident, kind, ksize ) == 0
311 && ident[ksize] == ':' );
314 std::string Solvable::name() const
316 NO_SOLVABLE_RETURN( std::string() );
317 const char * ident = IdString( _solvable->name ).c_str();
318 const char * sep = ::strchr( ident, ':' );
319 return( sep ? sep+1 : ident );
322 Edition Solvable::edition() const
324 NO_SOLVABLE_RETURN( Edition() );
325 return Edition( _solvable->evr );
328 Arch Solvable::arch() const
330 NO_SOLVABLE_RETURN( Arch_noarch ); //ArchId() );
331 switch ( _solvable->arch )
335 return Arch_noarch; //ArchId( ARCH_NOARCH );
338 return Arch( IdString(_solvable->arch).asString() );
339 //return ArchId( _solvable->arch );
342 bool Solvable::installOnly() const
344 std::set<IdString> multiversion = ZConfig::instance().multiversion();
345 if (multiversion.find(ident()) != multiversion.end())
350 IdString Solvable::vendor() const
352 NO_SOLVABLE_RETURN( IdString() );
353 return IdString( _solvable->vendor );
356 Capabilities Solvable::operator[]( Dep which_r ) const
358 switch( which_r.inSwitch() )
360 case Dep::PROVIDES_e: return provides(); break;
361 case Dep::REQUIRES_e: return requires(); break;
362 case Dep::CONFLICTS_e: return conflicts(); break;
363 case Dep::OBSOLETES_e: return obsoletes(); break;
364 case Dep::RECOMMENDS_e: return recommends(); break;
365 case Dep::SUGGESTS_e: return suggests(); break;
366 case Dep::ENHANCES_e: return enhances(); break;
367 case Dep::SUPPLEMENTS_e: return supplements(); break;
368 case Dep::PREREQUIRES_e: return prerequires(); break;
370 return Capabilities();
373 inline Capabilities _getCapabilities( detail::IdType * idarraydata_r, ::Offset offs_r )
375 return offs_r ? Capabilities( idarraydata_r + offs_r ) : Capabilities();
377 Capabilities Solvable::provides() const
379 NO_SOLVABLE_RETURN( Capabilities() );
380 return _getCapabilities( _solvable->repo->idarraydata, _solvable->provides );
382 Capabilities Solvable::requires() const
384 NO_SOLVABLE_RETURN( Capabilities() );
385 return _getCapabilities( _solvable->repo->idarraydata, _solvable->requires );
387 Capabilities Solvable::conflicts() const
389 NO_SOLVABLE_RETURN( Capabilities() );
390 return _getCapabilities( _solvable->repo->idarraydata, _solvable->conflicts );
392 Capabilities Solvable::obsoletes() const
394 NO_SOLVABLE_RETURN( Capabilities() );
395 return _getCapabilities( _solvable->repo->idarraydata, _solvable->obsoletes );
397 Capabilities Solvable::recommends() const
399 NO_SOLVABLE_RETURN( Capabilities() );
400 return _getCapabilities( _solvable->repo->idarraydata, _solvable->recommends );
402 Capabilities Solvable::suggests() const
404 NO_SOLVABLE_RETURN( Capabilities() );
405 return _getCapabilities( _solvable->repo->idarraydata, _solvable->suggests );
407 Capabilities Solvable::enhances() const
409 NO_SOLVABLE_RETURN( Capabilities() );
410 return _getCapabilities( _solvable->repo->idarraydata, _solvable->enhances );
412 Capabilities Solvable::supplements() const
414 NO_SOLVABLE_RETURN( Capabilities() );
415 return _getCapabilities( _solvable->repo->idarraydata, _solvable->supplements );
417 Capabilities Solvable::prerequires() const
419 NO_SOLVABLE_RETURN( Capabilities() );
420 // prerequires are a subset of requires
421 ::Offset offs = _solvable->requires;
422 return offs ? Capabilities( _solvable->repo->idarraydata + offs, detail::solvablePrereqMarker )
426 ///////////////////////////////////////////////////////////////////
428 { /////////////////////////////////////////////////////////////////
429 /** Expand \ref Capability and call \c fnc_r for each namescpace:language
430 * dependency. Return #invocations of fnc_r, negative if fnc_r returned
431 * false to indicate abort.
433 int invokeOnEachSupportedLocale( Capability cap_r, function<bool (const Locale &)> fnc_r )
435 CapDetail detail( cap_r );
436 if ( detail.kind() == CapDetail::EXPRESSION )
438 switch ( detail.capRel() )
440 case CapDetail::CAP_AND:
441 case CapDetail::CAP_OR:
444 int res = invokeOnEachSupportedLocale( detail.lhs(), fnc_r );
446 return res; // negative on abort.
447 int res2 = invokeOnEachSupportedLocale( detail.rhs(), fnc_r );
449 return -res + res2; // negative on abort.
454 case CapDetail::CAP_NAMESPACE:
455 if ( detail.lhs().id() == NAMESPACE_LANGUAGE )
457 return ( !fnc_r || fnc_r( Locale( IdString(detail.rhs().id()) ) ) ) ? 1 : -1; // negative on abort.
461 case CapDetail::REL_NONE:
462 case CapDetail::CAP_WITH:
463 case CapDetail::CAP_ARCH:
470 /** Expand \ref Capability and call \c fnc_r for each namescpace:language
471 * dependency. Return #invocations of fnc_r, negative if fnc_r returned
472 * false to indicate abort.
474 inline int invokeOnEachSupportedLocale( Capabilities cap_r, function<bool (const Locale &)> fnc_r )
477 for_( cit, cap_r.begin(), cap_r.end() )
479 int res = invokeOnEachSupportedLocale( *cit, fnc_r );
481 return -cnt + res; // negative on abort.
488 // Functor returning false if a Locale is in the set.
491 NoMatchIn( const LocaleSet & locales_r ) : _locales( locales_r ) {}
493 bool operator()( const Locale & locale_r ) const
495 return _locales.find( locale_r ) == _locales.end();
498 const LocaleSet & _locales;
501 } /////////////////////////////////////////////////////////////////
503 bool Solvable::supportsLocales() const
505 // false_c stops on 1st Locale.
506 return invokeOnEachSupportedLocale( supplements(), functor::false_c() ) < 0;
509 bool Solvable::supportsLocale( const Locale & locale_r ) const
511 // not_equal_to stops on == Locale.
512 return invokeOnEachSupportedLocale( supplements(), bind( std::not_equal_to<Locale>(), locale_r, _1 ) ) < 0;
515 bool Solvable::supportsLocale( const LocaleSet & locales_r ) const
517 if ( locales_r.empty() )
519 // NoMatchIn stops if Locale is included.
520 return invokeOnEachSupportedLocale( supplements(), NoMatchIn(locales_r) ) < 0;
523 bool Solvable::supportsRequestedLocales() const
524 { return supportsLocale( myPool().getRequestedLocales() ); }
526 void Solvable::getSupportedLocales( LocaleSet & locales_r ) const
528 invokeOnEachSupportedLocale( supplements(),
529 functor::Collector( std::inserter( locales_r, locales_r.begin() ) ) );
532 /******************************************************************
534 ** FUNCTION NAME : operator<<
535 ** FUNCTION TYPE : std::ostream &
537 std::ostream & operator<<( std::ostream & str, const Solvable & obj )
540 return str << (obj.isSystem() ? "systemSolvable" : "noSolvable" );
542 return str << "(" << obj.id() << ")"
543 << ( obj.isKind( ResKind::srcpackage ) ? "srcpackage:" : "" ) << obj.ident()
544 << '-' << obj.edition() << '.' << obj.arch() << "("
545 << obj.repository().alias() << ")";
548 /******************************************************************
550 ** FUNCTION NAME : dumpOn
551 ** FUNCTION TYPE : std::ostream &
553 std::ostream & dumpOn( std::ostream & str, const Solvable & obj )
558 #define OUTS(X) if ( ! obj[Dep::X].empty() ) str << endl << " " #X " " << obj[Dep::X]
573 /////////////////////////////////////////////////////////////////
575 ///////////////////////////////////////////////////////////////////
576 /////////////////////////////////////////////////////////////////
578 ///////////////////////////////////////////////////////////////////