#include "zypp/base/Logger.h"
#include "zypp/base/Gettext.h"
#include "zypp/base/Exception.h"
+#include "zypp/base/Functional.h"
+#include "zypp/base/Collector.h"
#include "zypp/sat/detail/PoolImpl.h"
#include "zypp/sat/Solvable.h"
-#include "zypp/sat/Repo.h"
+#include "zypp/sat/Pool.h"
+#include "zypp/Repository.h"
+#include "zypp/OnMediaLocation.h"
using std::endl;
namespace sat
{ /////////////////////////////////////////////////////////////////
- const Solvable Solvable::nosolvable;
+ Solvable::SplitIdent::SplitIdent( IdString ident_r )
+ : _ident( ident_r )
+ {
+ if ( ! ident_r )
+ return;
+
+ const char * ident = ident_r.c_str();
+ const char * sep = ::strchr( ident, ':' );
+
+ // no ':' in package names (hopefully)
+ if ( ! sep )
+ {
+ _kind = ResKind::package;
+ _name = ident_r;
+ return;
+ }
+
+ // save name
+ _name = IdString( sep+1 );
+ // quick check for well known kinds
+ if ( sep-ident >= 4 )
+ {
+ switch ( ident[3] )
+ {
+#define OUTS(K,S) if ( !::strncmp( ident, ResKind::K.c_str(), S ) ) _kind = ResKind::K
+ // ----v
+ case 'c': OUTS( patch, 5 ); return; break;
+ case 'd': OUTS( product, 7 ); return; break;
+ case 'k': OUTS( package, 7 ); return; break;
+ case 'p': OUTS( srcpackage, 10 ); return; break;
+ case 't': OUTS( pattern, 7 ); return; break;
+#undef OUTS
+ }
+ }
+
+ // an unknown kind
+ _kind = ResKind( std::string( ident, sep-ident ) );
+ }
+
+ Solvable::SplitIdent::SplitIdent( ResKind kind_r, IdString name_r )
+ : _kind( kind_r )
+ , _name( name_r )
+ {
+ if ( kind_r == ResKind::package || kind_r == ResKind::srcpackage )
+ _ident = _name;
+ else
+ _ident = IdString( str::form( "%s:%s", kind_r.c_str(), name_r.c_str() ) );
+ }
+
+ Solvable::SplitIdent::SplitIdent( ResKind kind_r, const C_Str & name_r )
+ : _kind( kind_r )
+ , _name( name_r )
+ {
+ if ( kind_r == ResKind::package || kind_r == ResKind::srcpackage )
+ _ident = _name;
+ else
+ _ident = IdString( str::form( "%s:%s", kind_r.c_str(), name_r.c_str() ) );
+ }
+
+ /////////////////////////////////////////////////////////////////
+
+ const Solvable Solvable::noSolvable;
/////////////////////////////////////////////////////////////////
Solvable Solvable::nextInRepo() const
{
- NO_SOLVABLE_RETURN( nosolvable );
+ NO_SOLVABLE_RETURN( noSolvable );
for ( detail::SolvableIdType next = _id+1; next < unsigned(_solvable->repo->end); ++next )
{
::_Solvable * nextS( myPool().getSolvable( next ) );
return Solvable( next );
}
}
- return nosolvable;
+ return noSolvable;
}
- Repo Solvable::repo() const
+ Repository Solvable::repository() const
{
- NO_SOLVABLE_RETURN( Repo::norepo );
- return Repo( _solvable->repo );
+ NO_SOLVABLE_RETURN( Repository::noRepository );
+ return Repository( _solvable->repo );
}
bool Solvable::isSystem() const
- { return repo().isSystemRepo(); }
+ {
+ NO_SOLVABLE_RETURN( _id == detail::systemSolvableId );
+ return Repository( _solvable->repo ).isSystemRepo();
+ }
IdString Solvable::ident() const
{
return IdString( _solvable->name );
}
- std::string Solvable::lookupStrAttribute( const SolvAttr &attr ) const
+ std::string Solvable::lookupStrAttribute( const SolvAttr & attr ) const
{
- const char *s = repo_lookup_str(this->get(), attr.idStr().id());
+ NO_SOLVABLE_RETURN( std::string() );
+ const char * s = ::solvable_lookup_str( _solvable, attr.id() );
return s ? s : std::string();
}
- unsigned Solvable::lookupNumAttribute( const SolvAttr &attr ) const
+ std::string Solvable::lookupStrAttribute( const SolvAttr & attr, const Locale & lang_r ) const
{
- return repo_lookup_num(this->get(), attr.idStr().id());
+ NO_SOLVABLE_RETURN( std::string() );
+ const char * s = 0;
+ if ( lang_r == Locale::noCode )
+ {
+ s = ::solvable_lookup_str_poollang( _solvable, attr.id() );
+ }
+ else
+ {
+ s = ::solvable_lookup_str_lang( _solvable, attr.id(), lang_r.code().c_str() );
+ }
+ return s ? s : std::string();
+ }
+
+ unsigned Solvable::lookupNumAttribute( const SolvAttr & attr ) const
+ {
+ NO_SOLVABLE_RETURN( 0 );
+ return ::solvable_lookup_num( _solvable, attr.id(), 0 );
}
-
- bool Solvable::lookupBoolAttribute( const SolvAttr &attr ) const
+
+ bool Solvable::lookupBoolAttribute( const SolvAttr & attr ) const
{
- return repo_lookup_num(this->get(), attr.idStr().id()) > 0;
+ NO_SOLVABLE_RETURN( false );
+ return ::solvable_lookup_bool( _solvable, attr.id() );
}
- struct LocCallback
+ detail::IdType Solvable::lookupIdAttribute( const SolvAttr & attr ) const
{
- unsigned medianr;
- const char *mediadir;
- const char *mediafile;
- int trivial;
- };
+ NO_SOLVABLE_RETURN( detail::noId );
+ return ::solvable_lookup_id( _solvable, attr.id() );
+ }
- static int
- location_cb (void *vcbdata, ::Solvable *s, ::Repodata *data, ::Repokey *key, ::KeyValue *kv)
+ CheckSum Solvable::lookupCheckSumAttribute( const SolvAttr & attr ) const
{
- LocCallback *lc = (LocCallback *)vcbdata;
- switch (key->type)
+ NO_SOLVABLE_RETURN( CheckSum() );
+ detail::IdType chksumtype = 0;
+ const char * s = ::solvable_lookup_checksum( _solvable, attr.id(), &chksumtype );
+ if ( ! s )
+ return CheckSum();
+ switch ( chksumtype )
{
- 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;
+ case REPOKEY_TYPE_MD5: return CheckSum::md5( s );
+ case REPOKEY_TYPE_SHA1: return CheckSum::sha1( s );
+ case REPOKEY_TYPE_SHA256: return CheckSum::sha256( s );
}
- /* continue walking */
- return 0;
+ return CheckSum( std::string(), s ); // try to autodetect
}
- std::string Solvable::lookupLocation(unsigned &medianr) const
+ OnMediaLocation Solvable::lookupLocation() const
+ //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.trivial)
- {
- if (lc.mediafile)
- ret += lc.mediafile;
- return ret;
- }
+ NO_SOLVABLE_RETURN( OnMediaLocation() );
+ // medianumber and path
+ unsigned medianr;
+ char * file = ::solvable_get_location( _solvable, &medianr );
+ if ( ! file )
+ return OnMediaLocation();
- if (lc.mediadir)
- {
- ret += std::string( lc.mediadir ) + "/";
- }
- else
+ OnMediaLocation ret;
+
+ Pathname path;
+ if ( repository().info().type().toEnum() == repo::RepoType::YAST2_e )
{
- /* If we haven't seen an explicit dirname, then prepend the arch as
- directory. */
- ret += "suse/";
- ret += IdString(_solvable->arch).asString() + "/";
+#warning STILL HARDCODED /suse PREFIX in location
+ // (ma@) loading a susetags repo search for a solvable with attribute
+ // susetags:datadir. this is the prefix. store it in RepoInfo(?).
+ path = "suse";
}
- /* Trivial means that we can construct the rpm name from our
- solvable data, as name-evr.arch.rpm . */
- ret += IdString(_solvable->name).asString();
- ret += '-';
- ret += IdString(_solvable->evr).asString();
- ret += '.';
- ret += IdString(_solvable->arch).asString();
- ret += ".rpm";
+ ret.setLocation ( path/file, medianr );
+ ret.setDownloadSize( ByteCount( lookupNumAttribute( SolvAttr::downloadsize ), ByteCount::K ) );
+ ret.setChecksum ( lookupCheckSumAttribute( SolvAttr::checksum ) );
+ // Not needed/available for solvables?
+ //ret.setOpenSize ( ByteCount( lookupNumAttribute( SolvAttr::opensize ), ByteCount::K ) );
+ //ret.setOpenChecksum( lookupCheckSumAttribute( SolvAttr::openchecksum ) );
return ret;
}
// ----v
case 'c': OUTS( patch, 5 ); break;
case 'd': OUTS( product, 7 ); break;
- case 'i': OUTS( script, 6 ); break;
case 'k': OUTS( package, 7 ); break;
- case 'm': OUTS( atom, 4 ); break;
case 'p': OUTS( srcpackage, 10 ); break;
- case 's': OUTS( message, 7 ); break;
case 't': OUTS( pattern, 7 ); break;
#undef OUTS
}
NO_SOLVABLE_RETURN( false );
// detect srcpackages by 'arch'
- if ( kind_r == ResKind::srcpackage )
+ switch ( _solvable->arch )
{
- return( _solvable->arch == ARCH_SRC || _solvable->arch == ARCH_NOSRC );
+ case ARCH_SRC:
+ case ARCH_NOSRC:
+ return( kind_r == ResKind::srcpackage );
+ break;
}
// no ':' in package names (hopefully)
: Capabilities();
}
+ ///////////////////////////////////////////////////////////////////
+ namespace
+ { /////////////////////////////////////////////////////////////////
+ /** Expand \ref Capability and call \c fnc_r for each namescpace:language
+ * dependency. Return #invocations of fnc_r, negative if fnc_r returned
+ * false to indicate abort.
+ */
+ int invokeOnEachSupportedLocale( Capability cap_r, function<bool (const Locale &)> fnc_r )
+ {
+ CapDetail detail( cap_r );
+ if ( detail.kind() == CapDetail::EXPRESSION )
+ {
+ switch ( detail.capRel() )
+ {
+ case CapDetail::CAP_AND:
+ case CapDetail::CAP_OR:
+ // expand
+ {
+ int res = invokeOnEachSupportedLocale( detail.lhs(), fnc_r );
+ if ( res < 0 )
+ return res; // negative on abort.
+ int res2 = invokeOnEachSupportedLocale( detail.rhs(), fnc_r );
+ if ( res2 < 0 )
+ return -res + res2; // negative on abort.
+ return res + res2;
+ }
+ break;
+
+ case CapDetail::CAP_NAMESPACE:
+ if ( detail.lhs().id() == NAMESPACE_LANGUAGE )
+ {
+ return ( !fnc_r || fnc_r( Locale( IdString(detail.rhs().id()) ) ) ) ? 1 : -1; // negative on abort.
+ }
+ break;
+
+ case CapDetail::REL_NONE:
+ case CapDetail::CAP_WITH:
+ case CapDetail::CAP_ARCH:
+ break; // unwanted
+ }
+ }
+ return 0;
+ }
+
+ /** Expand \ref Capability and call \c fnc_r for each namescpace:language
+ * dependency. Return #invocations of fnc_r, negative if fnc_r returned
+ * false to indicate abort.
+ */
+ inline int invokeOnEachSupportedLocale( Capabilities cap_r, function<bool (const Locale &)> fnc_r )
+ {
+ int cnt = 0;
+ for_( cit, cap_r.begin(), cap_r.end() )
+ {
+ int res = invokeOnEachSupportedLocale( *cit, fnc_r );
+ if ( res < 0 )
+ return -cnt + res; // negative on abort.
+ cnt += res;
+ }
+ return cnt;
+ }
+ //@}
+
+ // Functor returning false if a Locale is in the set.
+ struct NoMatchIn
+ {
+ NoMatchIn( const LocaleSet & locales_r ) : _locales( locales_r ) {}
+
+ bool operator()( const Locale & locale_r ) const
+ {
+ return _locales.find( locale_r ) == _locales.end();
+ }
+
+ const LocaleSet & _locales;
+ };
+
+ } /////////////////////////////////////////////////////////////////
+
+ bool Solvable::supportsLocales() const
+ {
+ // false_c stops on 1st Locale.
+ return invokeOnEachSupportedLocale( supplements(), functor::false_c() ) < 0;
+ }
+
+ bool Solvable::supportsLocale( const Locale & locale_r ) const
+ {
+ // not_equal_to stops on == Locale.
+ return invokeOnEachSupportedLocale( supplements(), bind( std::not_equal_to<Locale>(), locale_r, _1 ) ) < 0;
+ }
+
+ bool Solvable::supportsLocale( const LocaleSet & locales_r ) const
+ {
+ if ( locales_r.empty() )
+ return false;
+ // NoMatchIn stops if Locale is included.
+ return invokeOnEachSupportedLocale( supplements(), NoMatchIn(locales_r) ) < 0;
+ }
+
+ bool Solvable::supportsRequestedLocales() const
+ { return supportsLocale( myPool().getRequestedLocales() ); }
+
+ void Solvable::getSupportedLocales( LocaleSet & locales_r ) const
+ {
+ invokeOnEachSupportedLocale( supplements(),
+ functor::Collector( std::inserter( locales_r, locales_r.begin() ) ) );
+ }
+
/******************************************************************
**
** FUNCTION NAME : operator<<
std::ostream & operator<<( std::ostream & str, const Solvable & obj )
{
if ( ! obj )
- return str << "sat::solvable()";
+ return str << (obj.isSystem() ? "systemSolvable" : "noSolvable" );
- return str << "sat::solvable(" << obj.id() << "|"
+ return str << "(" << obj.id() << ")"
<< ( obj.isKind( ResKind::srcpackage ) ? "srcpackage:" : "" ) << obj.ident()
- << '-' << obj.edition() << '.' << obj.arch() << "){"
- << obj.repo().name() << "}";
+ << '-' << obj.edition() << '.' << obj.arch() << "("
+ << obj.repository().alias() << ")";
}
/******************************************************************