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"
18 #include "zypp/sat/detail/PoolImpl.h"
19 #include "zypp/sat/Solvable.h"
20 #include "zypp/sat/Repo.h"
24 ///////////////////////////////////////////////////////////////////
26 { /////////////////////////////////////////////////////////////////
27 ///////////////////////////////////////////////////////////////////
29 { /////////////////////////////////////////////////////////////////
31 const Solvable Solvable::nosolvable;
33 /////////////////////////////////////////////////////////////////
35 ::_Solvable * Solvable::get() const
36 { return myPool().getSolvable( _id ); }
38 #define NO_SOLVABLE_RETURN( VAL ) \
39 ::_Solvable * _solvable( get() ); \
40 if ( ! _solvable ) return VAL
42 Solvable Solvable::nextInPool() const
43 { return Solvable( myPool().getNextId( _id ) ); }
45 Solvable Solvable::nextInRepo() const
47 NO_SOLVABLE_RETURN( nosolvable );
48 for ( detail::SolvableIdType next = _id+1; next < unsigned(_solvable->repo->end); ++next )
50 ::_Solvable * nextS( myPool().getSolvable( next ) );
51 if ( nextS && nextS->repo == _solvable->repo )
53 return Solvable( next );
59 Repo Solvable::repo() const
61 NO_SOLVABLE_RETURN( Repo::norepo );
62 return Repo( _solvable->repo );
65 bool Solvable::isSystem() const
66 { return repo().isSystemRepo(); }
68 IdString Solvable::ident() const
70 NO_SOLVABLE_RETURN( IdString() );
71 return IdString( _solvable->name );
74 std::string Solvable::lookupStrAttribute( const SolvAttr &attr ) const
76 const char *s = repo_lookup_str(this->get(), attr.idStr().id());
77 return s ? s : std::string();
80 unsigned Solvable::lookupNumAttribute( const SolvAttr &attr ) const
82 return repo_lookup_num(this->get(), attr.idStr().id());
89 const char *mediafile;
94 location_cb (void *vcbdata, ::Solvable *s, ::Repodata *data, ::Repokey *key, ::KeyValue *kv)
96 LocCallback *lc = (LocCallback *)vcbdata;
100 if (key->name == SolvAttr::mediadir.idStr().id())
103 lc->mediadir = stringpool_id2str(&data->spool, kv->id);
105 lc->mediadir = id2str(data->repo->pool, kv->id);
109 if (key->name == SolvAttr::mediafile.idStr().id())
110 lc->mediafile = kv->str;
113 if (key->name == SolvAttr::mediafile.idStr().id())
117 if (key->name == SolvAttr::medianr.idStr().id())
118 lc->medianr = kv->num;
121 /* continue walking */
125 std::string Solvable::lookupLocation(unsigned &medianr) const
127 NO_SOLVABLE_RETURN( std::string() );
128 ::Repo *repo = _solvable->repo;
129 ::Pool *pool = repo->pool;
130 Id sid = _solvable - pool->solvables;
138 for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
140 if (data->state == REPODATA_STUB || data->state == REPODATA_ERROR)
142 if (sid < data->start || sid >= data->end)
144 repodata_search(data, sid - data->start, 0, location_cb, &lc);
146 medianr = lc.medianr;
149 ret += std::string( lc.mediadir ) + "/";
156 /* Trivial means that we can construct the rpm name from our
157 solvable data, as name-evr.arch.rpm . */
158 /* If we haven't seen an explicit dirname, then prepend the arch as
161 ret += IdString(_solvable->arch).asString() + "/";
162 ret += IdString(_solvable->name).asString();
164 ret += IdString(_solvable->evr).asString();
166 ret += IdString(_solvable->arch).asString();
171 ResKind Solvable::kind() const
173 NO_SOLVABLE_RETURN( ResKind() );
174 // detect srcpackages by 'arch'
175 switch ( _solvable->arch )
179 return ResKind::srcpackage;
183 const char * ident = IdString( _solvable->name ).c_str();
184 const char * sep = ::strchr( ident, ':' );
186 // no ':' in package names (hopefully)
188 return ResKind::package;
190 // quick check for well known kinds
191 if ( sep-ident >= 4 )
195 #define OUTS(K,S) if ( ::strncmp( ident, ResKind::K.c_str(), S ) ) return ResKind::K
197 case 'c': OUTS( patch, 5 ); break;
198 case 'd': OUTS( product, 7 ); break;
199 case 'i': OUTS( script, 6 ); break;
200 case 'k': OUTS( package, 7 ); break;
201 case 'm': OUTS( atom, 4 ); break;
202 case 'p': OUTS( srcpackage, 10 ); break;
203 case 's': OUTS( message, 7 ); break;
204 case 't': OUTS( pattern, 7 ); break;
210 return ResKind( std::string( ident, sep-ident ) );
213 bool Solvable::isKind( const ResKind & kind_r ) const
215 NO_SOLVABLE_RETURN( false );
217 // detect srcpackages by 'arch'
218 if ( kind_r == ResKind::srcpackage )
220 return( _solvable->arch == ARCH_SRC || _solvable->arch == ARCH_NOSRC );
223 // no ':' in package names (hopefully)
224 const char * ident = IdString( _solvable->name ).c_str();
225 if ( kind_r == ResKind::package )
227 return( ::strchr( ident, ':' ) == 0 );
230 // look for a 'kind:' prefix
231 const char * kind = kind_r.c_str();
232 unsigned ksize = ::strlen( kind );
233 return( ::strncmp( ident, kind, ksize ) == 0
234 && ident[ksize] == ':' );
237 std::string Solvable::name() const
239 NO_SOLVABLE_RETURN( std::string() );
240 const char * ident = IdString( _solvable->name ).c_str();
241 const char * sep = ::strchr( ident, ':' );
242 return( sep ? sep+1 : ident );
245 Edition Solvable::edition() const
247 NO_SOLVABLE_RETURN( Edition() );
248 return Edition( _solvable->evr );
251 Arch Solvable::arch() const
253 NO_SOLVABLE_RETURN( Arch_noarch ); //ArchId() );
254 switch ( _solvable->arch )
258 return Arch_noarch; //ArchId( ARCH_NOARCH );
261 return Arch( IdString(_solvable->arch).asString() );
262 //return ArchId( _solvable->arch );
265 IdString Solvable::vendor() const
267 NO_SOLVABLE_RETURN( IdString() );
268 return IdString( _solvable->vendor );
271 Capabilities Solvable::operator[]( Dep which_r ) const
273 NO_SOLVABLE_RETURN( Capabilities() );
275 switch( which_r.inSwitch() )
277 case Dep::PROVIDES_e: offs = _solvable->provides; break;
278 case Dep::REQUIRES_e: offs = _solvable->requires; break;
279 case Dep::CONFLICTS_e: offs = _solvable->conflicts; break;
280 case Dep::OBSOLETES_e: offs = _solvable->obsoletes; break;
281 case Dep::RECOMMENDS_e: offs = _solvable->recommends; break;
282 case Dep::SUGGESTS_e: offs = _solvable->suggests; break;
283 case Dep::FRESHENS_e: offs = _solvable->freshens; break;
284 case Dep::ENHANCES_e: offs = _solvable->enhances; break;
285 case Dep::SUPPLEMENTS_e: offs = _solvable->supplements; break;
287 case Dep::PREREQUIRES_e:
288 // prerequires are a subset of requires
289 if ( (offs = _solvable->requires) )
290 return Capabilities( _solvable->repo->idarraydata + offs, detail::solvablePrereqMarker );
292 return Capabilities();
296 return offs ? Capabilities( _solvable->repo->idarraydata + offs )
300 /******************************************************************
302 ** FUNCTION NAME : operator<<
303 ** FUNCTION TYPE : std::ostream &
305 std::ostream & operator<<( std::ostream & str, const Solvable & obj )
308 return str << "sat::solvable()";
310 return str << "sat::solvable(" << obj.id() << "|"
311 << ( obj.isKind( ResKind::srcpackage ) ? "srcpackage:" : "" ) << obj.ident()
312 << '-' << obj.edition() << '.' << obj.arch() << "){"
313 << obj.repo().name() << "}";
316 /******************************************************************
318 ** FUNCTION NAME : dumpOn
319 ** FUNCTION TYPE : std::ostream &
321 std::ostream & dumpOn( std::ostream & str, const Solvable & obj )
326 #define OUTS(X) if ( ! obj[Dep::X].empty() ) str << endl << " " #X " " << obj[Dep::X]
342 /////////////////////////////////////////////////////////////////
344 ///////////////////////////////////////////////////////////////////
345 /////////////////////////////////////////////////////////////////
347 ///////////////////////////////////////////////////////////////////