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/Repo.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 Repo Solvable::repo() const
63 NO_SOLVABLE_RETURN( Repo::norepo );
64 return Repo( _solvable->repo );
67 bool Solvable::isSystem() const
68 { return repo().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 const char *s = repo_lookup_str(this->get(), attr.idStr().id());
79 return s ? s : std::string();
82 unsigned Solvable::lookupNumAttribute( const SolvAttr &attr ) const
84 return repo_lookup_num(this->get(), attr.idStr().id());
87 bool Solvable::lookupBoolAttribute( const SolvAttr &attr ) const
89 return repo_lookup_num(this->get(), attr.idStr().id()) > 0;
96 const char *mediafile;
101 location_cb (void *vcbdata, ::Solvable *s, ::Repodata *data, ::Repokey *key, ::KeyValue *kv)
103 LocCallback *lc = (LocCallback *)vcbdata;
107 if (key->name == SolvAttr::mediadir.idStr().id())
110 lc->mediadir = stringpool_id2str(&data->spool, kv->id);
112 lc->mediadir = id2str(data->repo->pool, kv->id);
116 if (key->name == SolvAttr::mediafile.idStr().id())
117 lc->mediafile = kv->str;
120 if (key->name == SolvAttr::mediafile.idStr().id())
124 if (key->name == SolvAttr::medianr.idStr().id())
125 lc->medianr = kv->num;
128 /* continue walking */
132 std::string Solvable::lookupLocation(unsigned &medianr) const
134 NO_SOLVABLE_RETURN( std::string() );
135 ::Repo *repo = _solvable->repo;
136 ::Pool *pool = repo->pool;
137 Id sid = _solvable - pool->solvables;
145 for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
147 if (data->state == REPODATA_STUB || data->state == REPODATA_ERROR)
149 if (sid < data->start || sid >= data->end)
151 repodata_search(data, sid - data->start, 0, location_cb, &lc);
153 medianr = lc.medianr;
165 ret += std::string( lc.mediadir ) + "/";
169 /* If we haven't seen an explicit dirname, then prepend the arch as
172 ret += IdString(_solvable->arch).asString() + "/";
174 /* Trivial means that we can construct the rpm name from our
175 solvable data, as name-evr.arch.rpm . */
176 ret += IdString(_solvable->name).asString();
178 ret += IdString(_solvable->evr).asString();
180 ret += IdString(_solvable->arch).asString();
185 ResKind Solvable::kind() const
187 NO_SOLVABLE_RETURN( ResKind() );
188 // detect srcpackages by 'arch'
189 switch ( _solvable->arch )
193 return ResKind::srcpackage;
197 const char * ident = IdString( _solvable->name ).c_str();
198 const char * sep = ::strchr( ident, ':' );
200 // no ':' in package names (hopefully)
202 return ResKind::package;
204 // quick check for well known kinds
205 if ( sep-ident >= 4 )
209 #define OUTS(K,S) if ( !::strncmp( ident, ResKind::K.c_str(), S ) ) return ResKind::K
211 case 'c': OUTS( patch, 5 ); break;
212 case 'd': OUTS( product, 7 ); break;
213 case 'i': OUTS( script, 6 ); break;
214 case 'k': OUTS( package, 7 ); break;
215 case 'm': OUTS( atom, 4 ); break;
216 case 'p': OUTS( srcpackage, 10 ); break;
217 case 's': OUTS( message, 7 ); break;
218 case 't': OUTS( pattern, 7 ); break;
224 return ResKind( std::string( ident, sep-ident ) );
227 bool Solvable::isKind( const ResKind & kind_r ) const
229 NO_SOLVABLE_RETURN( false );
231 // detect srcpackages by 'arch'
232 if ( kind_r == ResKind::srcpackage )
234 return( _solvable->arch == ARCH_SRC || _solvable->arch == ARCH_NOSRC );
237 // no ':' in package names (hopefully)
238 const char * ident = IdString( _solvable->name ).c_str();
239 if ( kind_r == ResKind::package )
241 return( ::strchr( ident, ':' ) == 0 );
244 // look for a 'kind:' prefix
245 const char * kind = kind_r.c_str();
246 unsigned ksize = ::strlen( kind );
247 return( ::strncmp( ident, kind, ksize ) == 0
248 && ident[ksize] == ':' );
251 std::string Solvable::name() const
253 NO_SOLVABLE_RETURN( std::string() );
254 const char * ident = IdString( _solvable->name ).c_str();
255 const char * sep = ::strchr( ident, ':' );
256 return( sep ? sep+1 : ident );
259 Edition Solvable::edition() const
261 NO_SOLVABLE_RETURN( Edition() );
262 return Edition( _solvable->evr );
265 Arch Solvable::arch() const
267 NO_SOLVABLE_RETURN( Arch_noarch ); //ArchId() );
268 switch ( _solvable->arch )
272 return Arch_noarch; //ArchId( ARCH_NOARCH );
275 return Arch( IdString(_solvable->arch).asString() );
276 //return ArchId( _solvable->arch );
279 IdString Solvable::vendor() const
281 NO_SOLVABLE_RETURN( IdString() );
282 return IdString( _solvable->vendor );
285 Capabilities Solvable::operator[]( Dep which_r ) const
287 switch( which_r.inSwitch() )
289 case Dep::PROVIDES_e: return provides(); break;
290 case Dep::REQUIRES_e: return requires(); break;
291 case Dep::CONFLICTS_e: return conflicts(); break;
292 case Dep::OBSOLETES_e: return obsoletes(); break;
293 case Dep::RECOMMENDS_e: return recommends(); break;
294 case Dep::SUGGESTS_e: return suggests(); break;
295 case Dep::FRESHENS_e: return freshens(); break;
296 case Dep::ENHANCES_e: return enhances(); break;
297 case Dep::SUPPLEMENTS_e: return supplements(); break;
298 case Dep::PREREQUIRES_e: return prerequires(); break;
300 return Capabilities();
303 inline Capabilities _getCapabilities( detail::IdType * idarraydata_r, ::Offset offs_r )
305 return offs_r ? Capabilities( idarraydata_r + offs_r ) : Capabilities();
307 Capabilities Solvable::provides() const
309 NO_SOLVABLE_RETURN( Capabilities() );
310 return _getCapabilities( _solvable->repo->idarraydata, _solvable->provides );
312 Capabilities Solvable::requires() const
314 NO_SOLVABLE_RETURN( Capabilities() );
315 return _getCapabilities( _solvable->repo->idarraydata, _solvable->requires );
317 Capabilities Solvable::conflicts() const
319 NO_SOLVABLE_RETURN( Capabilities() );
320 return _getCapabilities( _solvable->repo->idarraydata, _solvable->conflicts );
322 Capabilities Solvable::obsoletes() const
324 NO_SOLVABLE_RETURN( Capabilities() );
325 return _getCapabilities( _solvable->repo->idarraydata, _solvable->obsoletes );
327 Capabilities Solvable::recommends() const
329 NO_SOLVABLE_RETURN( Capabilities() );
330 return _getCapabilities( _solvable->repo->idarraydata, _solvable->recommends );
332 Capabilities Solvable::suggests() const
334 NO_SOLVABLE_RETURN( Capabilities() );
335 return _getCapabilities( _solvable->repo->idarraydata, _solvable->suggests );
337 Capabilities Solvable::freshens() const
339 NO_SOLVABLE_RETURN( Capabilities() );
340 return _getCapabilities( _solvable->repo->idarraydata, _solvable->freshens );
342 Capabilities Solvable::enhances() const
344 NO_SOLVABLE_RETURN( Capabilities() );
345 return _getCapabilities( _solvable->repo->idarraydata, _solvable->enhances );
347 Capabilities Solvable::supplements() const
349 NO_SOLVABLE_RETURN( Capabilities() );
350 return _getCapabilities( _solvable->repo->idarraydata, _solvable->supplements );
352 Capabilities Solvable::prerequires() const
354 NO_SOLVABLE_RETURN( Capabilities() );
355 // prerequires are a subset of requires
356 ::Offset offs = _solvable->requires;
357 return offs ? Capabilities( _solvable->repo->idarraydata + offs, detail::solvablePrereqMarker )
361 ///////////////////////////////////////////////////////////////////
363 { /////////////////////////////////////////////////////////////////
364 /** Expand \ref Capability and call \c fnc_r for each namescpace:language
365 * dependency. Return #invocations of fnc_r, negative if fnc_r returned
366 * false to indicate abort.
368 int invokeOnEachSupportedLocale( Capability cap_r, function<bool (const Locale &)> fnc_r )
370 CapDetail detail( cap_r );
371 if ( detail.kind() == CapDetail::EXPRESSION )
373 switch ( detail.capRel() )
375 case CapDetail::CAP_AND:
376 case CapDetail::CAP_OR:
379 int res = invokeOnEachSupportedLocale( detail.lhs(), fnc_r );
381 return res; // negative on abort.
382 int res2 = invokeOnEachSupportedLocale( detail.rhs(), fnc_r );
384 return -res + res2; // negative on abort.
389 case CapDetail::CAP_NAMESPACE:
390 if ( detail.lhs().id() == NAMESPACE_LANGUAGE )
392 return ( !fnc_r || fnc_r( Locale( IdString(detail.rhs().id()) ) ) ) ? 1 : -1; // negative on abort.
396 case CapDetail::REL_NONE:
397 case CapDetail::CAP_WITH:
404 /** Expand \ref Capability and call \c fnc_r for each namescpace:language
405 * dependency. Return #invocations of fnc_r, negative if fnc_r returned
406 * false to indicate abort.
408 inline int invokeOnEachSupportedLocale( Capabilities cap_r, function<bool (const Locale &)> fnc_r )
411 for_( cit, cap_r.begin(), cap_r.end() )
413 int res = invokeOnEachSupportedLocale( *cit, fnc_r );
415 return -cnt + res; // negative on abort.
422 // Functor returning false if a Locale is in the set.
425 NoMatchIn( const LocaleSet & locales_r ) : _locales( locales_r ) {}
427 bool operator()( const Locale & locale_r ) const
429 return _locales.find( locale_r ) == _locales.end();
432 const LocaleSet & _locales;
435 } /////////////////////////////////////////////////////////////////
437 bool Solvable::supportsLocales() const
439 // false_c stops on 1st Locale.
440 return invokeOnEachSupportedLocale( supplements(), functor::false_c() ) < 0;
443 bool Solvable::supportsLocale( const Locale & locale_r ) const
445 // not_equal_to stops on == Locale.
446 return invokeOnEachSupportedLocale( supplements(), bind( std::not_equal_to<Locale>(), locale_r, _1 ) ) < 0;
449 bool Solvable::supportsLocale( const LocaleSet & locales_r ) const
451 if ( locales_r.empty() )
453 // NoMatchIn stops if Locale is included.
454 return invokeOnEachSupportedLocale( supplements(), NoMatchIn(locales_r) ) < 0;
457 bool Solvable::supportsRequestedLocales() const
458 { return supportsLocale( myPool().getRequestedLocales() ); }
460 void Solvable::getSupportedLocales( LocaleSet & locales_r ) const
462 invokeOnEachSupportedLocale( supplements(),
463 functor::Collector( std::inserter( locales_r, locales_r.begin() ) ) );
466 /******************************************************************
468 ** FUNCTION NAME : operator<<
469 ** FUNCTION TYPE : std::ostream &
471 std::ostream & operator<<( std::ostream & str, const Solvable & obj )
474 return str << "sat::solvable()";
476 return str << "(" << obj.id() << ")"
477 << ( obj.isKind( ResKind::srcpackage ) ? "srcpackage:" : "" ) << obj.ident()
478 << '-' << obj.edition() << '.' << obj.arch() << "("
479 << obj.repo().name() << ")";
482 /******************************************************************
484 ** FUNCTION NAME : dumpOn
485 ** FUNCTION TYPE : std::ostream &
487 std::ostream & dumpOn( std::ostream & str, const Solvable & obj )
492 #define OUTS(X) if ( ! obj[Dep::X].empty() ) str << endl << " " #X " " << obj[Dep::X]
508 /////////////////////////////////////////////////////////////////
510 ///////////////////////////////////////////////////////////////////
511 /////////////////////////////////////////////////////////////////
513 ///////////////////////////////////////////////////////////////////