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/Repository.h"
26 ///////////////////////////////////////////////////////////////////
28 { /////////////////////////////////////////////////////////////////
29 ///////////////////////////////////////////////////////////////////
31 { /////////////////////////////////////////////////////////////////
33 const Solvable Solvable::nosolvable;
35 /////////////////////////////////////////////////////////////////
37 ::_Solvable * Solvable::get() const
38 { return myPool().getSolvable( _id ); }
40 #define NO_SOLVABLE_RETURN( VAL ) \
41 ::_Solvable * _solvable( get() ); \
42 if ( ! _solvable ) return VAL
44 Solvable Solvable::nextInPool() const
45 { return Solvable( myPool().getNextId( _id ) ); }
47 Solvable Solvable::nextInRepo() const
49 NO_SOLVABLE_RETURN( nosolvable );
50 for ( detail::SolvableIdType next = _id+1; next < unsigned(_solvable->repo->end); ++next )
52 ::_Solvable * nextS( myPool().getSolvable( next ) );
53 if ( nextS && nextS->repo == _solvable->repo )
55 return Solvable( next );
61 Repository Solvable::repository() const
63 NO_SOLVABLE_RETURN( Repository::noRepository );
64 return Repository( _solvable->repo );
67 bool Solvable::isSystem() const
68 { return repository().isSystemRepo(); }
70 IdString Solvable::ident() const
72 NO_SOLVABLE_RETURN( IdString() );
73 return IdString( _solvable->name );
76 std::string Solvable::lookupStrAttribute( const SolvAttr & attr ) const
78 NO_SOLVABLE_RETURN( std::string() );
79 const char *s = ::repo_lookup_str( _solvable, attr.idStr().id() );
80 return s ? s : std::string();
83 std::string Solvable::lookupStrAttribute( const SolvAttr & attr, const Locale & lang_r ) const
85 #warning FIX RETRIEVIENG TRANSLATIONS
86 return lookupStrAttribute( attr );
89 unsigned Solvable::lookupNumAttribute( const SolvAttr & attr ) const
91 NO_SOLVABLE_RETURN( 0 );
92 return ::repo_lookup_num( _solvable, attr.idStr().id() );
95 bool Solvable::lookupBoolAttribute( const SolvAttr & attr ) const
97 NO_SOLVABLE_RETURN( false );
98 return ::repo_lookup_num( _solvable, attr.idStr().id() );
101 std::string Solvable::lookupLocation(unsigned &medianr) const
103 NO_SOLVABLE_RETURN( std::string() );
105 char *l = solvable_get_location(_solvable, &nr);
107 // /* XXX This datadir should be part of RepoInfo. */
108 // if (repoInfo().type().toEnum() == repo::RepoType::YAST2_e)
109 // filename = std::string("suse/") + filename;
110 return l ? std::string(l) : std::string();
113 ResKind Solvable::kind() const
115 NO_SOLVABLE_RETURN( ResKind() );
116 // detect srcpackages by 'arch'
117 switch ( _solvable->arch )
121 return ResKind::srcpackage;
125 const char * ident = IdString( _solvable->name ).c_str();
126 const char * sep = ::strchr( ident, ':' );
128 // no ':' in package names (hopefully)
130 return ResKind::package;
132 // quick check for well known kinds
133 if ( sep-ident >= 4 )
137 #define OUTS(K,S) if ( !::strncmp( ident, ResKind::K.c_str(), S ) ) return ResKind::K
139 case 'c': OUTS( patch, 5 ); break;
140 case 'd': OUTS( product, 7 ); break;
141 case 'i': OUTS( script, 6 ); break;
142 case 'k': OUTS( package, 7 ); break;
143 case 'm': OUTS( atom, 4 ); break;
144 case 'p': OUTS( srcpackage, 10 ); break;
145 case 's': OUTS( message, 7 ); break;
146 case 't': OUTS( pattern, 7 ); break;
152 return ResKind( std::string( ident, sep-ident ) );
155 bool Solvable::isKind( const ResKind & kind_r ) const
157 NO_SOLVABLE_RETURN( false );
159 // detect srcpackages by 'arch'
160 if ( kind_r == ResKind::srcpackage )
162 return( _solvable->arch == ARCH_SRC || _solvable->arch == ARCH_NOSRC );
165 // no ':' in package names (hopefully)
166 const char * ident = IdString( _solvable->name ).c_str();
167 if ( kind_r == ResKind::package )
169 return( ::strchr( ident, ':' ) == 0 );
172 // look for a 'kind:' prefix
173 const char * kind = kind_r.c_str();
174 unsigned ksize = ::strlen( kind );
175 return( ::strncmp( ident, kind, ksize ) == 0
176 && ident[ksize] == ':' );
179 std::string Solvable::name() const
181 NO_SOLVABLE_RETURN( std::string() );
182 const char * ident = IdString( _solvable->name ).c_str();
183 const char * sep = ::strchr( ident, ':' );
184 return( sep ? sep+1 : ident );
187 Edition Solvable::edition() const
189 NO_SOLVABLE_RETURN( Edition() );
190 return Edition( _solvable->evr );
193 Arch Solvable::arch() const
195 NO_SOLVABLE_RETURN( Arch_noarch ); //ArchId() );
196 switch ( _solvable->arch )
200 return Arch_noarch; //ArchId( ARCH_NOARCH );
203 return Arch( IdString(_solvable->arch).asString() );
204 //return ArchId( _solvable->arch );
207 IdString Solvable::vendor() const
209 NO_SOLVABLE_RETURN( IdString() );
210 return IdString( _solvable->vendor );
213 Capabilities Solvable::operator[]( Dep which_r ) const
215 switch( which_r.inSwitch() )
217 case Dep::PROVIDES_e: return provides(); break;
218 case Dep::REQUIRES_e: return requires(); break;
219 case Dep::CONFLICTS_e: return conflicts(); break;
220 case Dep::OBSOLETES_e: return obsoletes(); break;
221 case Dep::RECOMMENDS_e: return recommends(); break;
222 case Dep::SUGGESTS_e: return suggests(); break;
223 case Dep::FRESHENS_e: return freshens(); break;
224 case Dep::ENHANCES_e: return enhances(); break;
225 case Dep::SUPPLEMENTS_e: return supplements(); break;
226 case Dep::PREREQUIRES_e: return prerequires(); break;
228 return Capabilities();
231 inline Capabilities _getCapabilities( detail::IdType * idarraydata_r, ::Offset offs_r )
233 return offs_r ? Capabilities( idarraydata_r + offs_r ) : Capabilities();
235 Capabilities Solvable::provides() const
237 NO_SOLVABLE_RETURN( Capabilities() );
238 return _getCapabilities( _solvable->repo->idarraydata, _solvable->provides );
240 Capabilities Solvable::requires() const
242 NO_SOLVABLE_RETURN( Capabilities() );
243 return _getCapabilities( _solvable->repo->idarraydata, _solvable->requires );
245 Capabilities Solvable::conflicts() const
247 NO_SOLVABLE_RETURN( Capabilities() );
248 return _getCapabilities( _solvable->repo->idarraydata, _solvable->conflicts );
250 Capabilities Solvable::obsoletes() const
252 NO_SOLVABLE_RETURN( Capabilities() );
253 return _getCapabilities( _solvable->repo->idarraydata, _solvable->obsoletes );
255 Capabilities Solvable::recommends() const
257 NO_SOLVABLE_RETURN( Capabilities() );
258 return _getCapabilities( _solvable->repo->idarraydata, _solvable->recommends );
260 Capabilities Solvable::suggests() const
262 NO_SOLVABLE_RETURN( Capabilities() );
263 return _getCapabilities( _solvable->repo->idarraydata, _solvable->suggests );
265 Capabilities Solvable::freshens() const
267 NO_SOLVABLE_RETURN( Capabilities() );
268 return _getCapabilities( _solvable->repo->idarraydata, _solvable->freshens );
270 Capabilities Solvable::enhances() const
272 NO_SOLVABLE_RETURN( Capabilities() );
273 return _getCapabilities( _solvable->repo->idarraydata, _solvable->enhances );
275 Capabilities Solvable::supplements() const
277 NO_SOLVABLE_RETURN( Capabilities() );
278 return _getCapabilities( _solvable->repo->idarraydata, _solvable->supplements );
280 Capabilities Solvable::prerequires() const
282 NO_SOLVABLE_RETURN( Capabilities() );
283 // prerequires are a subset of requires
284 ::Offset offs = _solvable->requires;
285 return offs ? Capabilities( _solvable->repo->idarraydata + offs, detail::solvablePrereqMarker )
289 ///////////////////////////////////////////////////////////////////
291 { /////////////////////////////////////////////////////////////////
292 /** Expand \ref Capability and call \c fnc_r for each namescpace:language
293 * dependency. Return #invocations of fnc_r, negative if fnc_r returned
294 * false to indicate abort.
296 int invokeOnEachSupportedLocale( Capability cap_r, function<bool (const Locale &)> fnc_r )
298 CapDetail detail( cap_r );
299 if ( detail.kind() == CapDetail::EXPRESSION )
301 switch ( detail.capRel() )
303 case CapDetail::CAP_AND:
304 case CapDetail::CAP_OR:
307 int res = invokeOnEachSupportedLocale( detail.lhs(), fnc_r );
309 return res; // negative on abort.
310 int res2 = invokeOnEachSupportedLocale( detail.rhs(), fnc_r );
312 return -res + res2; // negative on abort.
317 case CapDetail::CAP_NAMESPACE:
318 if ( detail.lhs().id() == NAMESPACE_LANGUAGE )
320 return ( !fnc_r || fnc_r( Locale( IdString(detail.rhs().id()) ) ) ) ? 1 : -1; // negative on abort.
324 case CapDetail::REL_NONE:
325 case CapDetail::CAP_WITH:
332 /** Expand \ref Capability and call \c fnc_r for each namescpace:language
333 * dependency. Return #invocations of fnc_r, negative if fnc_r returned
334 * false to indicate abort.
336 inline int invokeOnEachSupportedLocale( Capabilities cap_r, function<bool (const Locale &)> fnc_r )
339 for_( cit, cap_r.begin(), cap_r.end() )
341 int res = invokeOnEachSupportedLocale( *cit, fnc_r );
343 return -cnt + res; // negative on abort.
350 // Functor returning false if a Locale is in the set.
353 NoMatchIn( const LocaleSet & locales_r ) : _locales( locales_r ) {}
355 bool operator()( const Locale & locale_r ) const
357 return _locales.find( locale_r ) == _locales.end();
360 const LocaleSet & _locales;
363 } /////////////////////////////////////////////////////////////////
365 bool Solvable::supportsLocales() const
367 // false_c stops on 1st Locale.
368 return invokeOnEachSupportedLocale( supplements(), functor::false_c() ) < 0;
371 bool Solvable::supportsLocale( const Locale & locale_r ) const
373 // not_equal_to stops on == Locale.
374 return invokeOnEachSupportedLocale( supplements(), bind( std::not_equal_to<Locale>(), locale_r, _1 ) ) < 0;
377 bool Solvable::supportsLocale( const LocaleSet & locales_r ) const
379 if ( locales_r.empty() )
381 // NoMatchIn stops if Locale is included.
382 return invokeOnEachSupportedLocale( supplements(), NoMatchIn(locales_r) ) < 0;
385 bool Solvable::supportsRequestedLocales() const
386 { return supportsLocale( myPool().getRequestedLocales() ); }
388 void Solvable::getSupportedLocales( LocaleSet & locales_r ) const
390 invokeOnEachSupportedLocale( supplements(),
391 functor::Collector( std::inserter( locales_r, locales_r.begin() ) ) );
394 /******************************************************************
396 ** FUNCTION NAME : operator<<
397 ** FUNCTION TYPE : std::ostream &
399 std::ostream & operator<<( std::ostream & str, const Solvable & obj )
402 return str << "sat::solvable()";
404 return str << "(" << obj.id() << ")"
405 << ( obj.isKind( ResKind::srcpackage ) ? "srcpackage:" : "" ) << obj.ident()
406 << '-' << obj.edition() << '.' << obj.arch() << "("
407 << obj.repository().name() << ")";
410 /******************************************************************
412 ** FUNCTION NAME : dumpOn
413 ** FUNCTION TYPE : std::ostream &
415 std::ostream & dumpOn( std::ostream & str, const Solvable & obj )
420 #define OUTS(X) if ( ! obj[Dep::X].empty() ) str << endl << " " #X " " << obj[Dep::X]
436 /////////////////////////////////////////////////////////////////
438 ///////////////////////////////////////////////////////////////////
439 /////////////////////////////////////////////////////////////////
441 ///////////////////////////////////////////////////////////////////