From 96c043c3cc12d27e8de24449298ae4266a8b0744 Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Thu, 7 Feb 2008 04:06:22 +0000 Subject: [PATCH] Implement a lookupLocation function. The location is stored in a clever way, so a helper function is necessary, that is further complicated by the wish to iterate over the attributes for a solvable only once, although we need up to three separate attributes to form the location. --- zypp/sat/Solvable.cc | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++- zypp/sat/Solvable.h | 9 +++++- 2 files changed, 95 insertions(+), 2 deletions(-) diff --git a/zypp/sat/Solvable.cc b/zypp/sat/Solvable.cc index 8b12701..39a0ba9 100644 --- a/zypp/sat/Solvable.cc +++ b/zypp/sat/Solvable.cc @@ -77,11 +77,97 @@ namespace zypp return s ? s : std::string(); } - int Solvable::lookupNumAttribute( const SolvAttr &attr ) const + unsigned Solvable::lookupNumAttribute( const SolvAttr &attr ) const { return repo_lookup_num(this->get(), attr.idStr().id()); } + struct LocCallback + { + unsigned medianr; + const char *mediadir; + const char *mediafile; + int trivial; + }; + + static int + location_cb (void *vcbdata, ::Solvable *s, ::Repodata *data, ::Repokey *key, ::KeyValue *kv) + { + LocCallback *lc = (LocCallback *)vcbdata; + switch (key->type) + { + case TYPE_ID: + if (key->name == SolvAttr::mediadir.idStr().id()) + { + if (data->localpool) + lc->mediadir = stringpool_id2str(&data->spool, kv->id); + else + lc->mediadir = id2str(data->repo->pool, kv->id); + } + break; + case TYPE_STR: + if (key->name == SolvAttr::mediafile.idStr().id()) + lc->mediafile = kv->str; + break; + case TYPE_VOID: + if (key->name == SolvAttr::mediafile.idStr().id()) + lc->trivial = 1; + break; + case TYPE_CONSTANT: + if (key->name == SolvAttr::medianr.idStr().id()) + lc->medianr = kv->num; + break; + } + /* continue walking */ + return 0; + } + + std::string Solvable::lookupLocation(unsigned &medianr) const + { + NO_SOLVABLE_RETURN( std::string() ); + ::Repo *repo = _solvable->repo; + ::Pool *pool = repo->pool; + Id sid = _solvable - pool->solvables; + ::Repodata *data; + unsigned i; + LocCallback lc; + lc.medianr = 1; + lc.mediadir = 0; + lc.mediafile = 0; + lc.trivial = 0; + for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++) + { + if (data->state == REPODATA_STUB || data->state == REPODATA_ERROR) + continue; + if (sid < data->start || sid >= data->end) + continue; + repodata_search(data, sid - data->start, 0, location_cb, &lc); + } + medianr = lc.medianr; + std::string ret; + if (lc.mediadir) + ret += std::string( lc.mediadir ) + "/"; + if (!lc.trivial) + { + if (lc.mediafile) + ret += lc.mediafile; + return ret; + } + /* Trivial means that we can construct the rpm name from our + solvable data, as name-evr.arch.rpm . */ + /* If we haven't seen an explicit dirname, then prepend the arch as + directory. */ + if (!lc.mediadir) + ret += IdString(_solvable->arch).asString() + "/"; + ret += IdString(_solvable->name).asString(); + ret += '-'; + ret += IdString(_solvable->evr).asString(); + ret += '.'; + ret += IdString(_solvable->arch).asString(); + ret += ".rpm"; + return ret; + } + ResKind Solvable::kind() const { NO_SOLVABLE_RETURN( ResKind() ); diff --git a/zypp/sat/Solvable.h b/zypp/sat/Solvable.h index 1075a2c..9bda209 100644 --- a/zypp/sat/Solvable.h +++ b/zypp/sat/Solvable.h @@ -89,7 +89,14 @@ namespace zypp * returns the numeric attribute value for \ref attr * or 0 if it does not exists. */ - int lookupNumAttribute( const SolvAttr &attr ) const; + unsigned lookupNumAttribute( const SolvAttr &attr ) const; + + /** + * returns the media location: media number in \ref medianr, + * file name as return value. The file name is possibly prepended + * with a subdirectory. + */ + std::string lookupLocation(unsigned &medianr) const; public: /** The identifier. -- 2.7.4