#include "zypp/base/Exception.h"
#include "zypp/base/Functional.h"
#include "zypp/base/Collector.h"
+#include "zypp/base/Xml.h"
#include "zypp/sat/detail/PoolImpl.h"
#include "zypp/sat/Solvable.h"
#include "zypp/sat/Pool.h"
+#include "zypp/sat/LookupAttr.h"
+
#include "zypp/Repository.h"
#include "zypp/OnMediaLocation.h"
+#include "zypp/ZConfig.h"
using std::endl;
namespace sat
{ /////////////////////////////////////////////////////////////////
- Solvable::SplitIdent::SplitIdent( IdString ident_r )
- : _ident( ident_r )
+ namespace
{
- if ( ! ident_r )
- return;
-
- const char * ident = ident_r.c_str();
- const char * sep = ::strchr( ident, ':' );
-
- // no ':' in package names (hopefully)
- if ( ! sep )
+ void _doSplit( IdString & _ident, ResKind & _kind, IdString & _name )
{
- _kind = ResKind::package;
- _name = ident_r;
- return;
+ if ( ! _ident )
+ return;
+
+ ResKind explicitKind = ResKind::explicitBuiltin( _ident.c_str() );
+ // NOTE: kind package and srcpackage do not have namespaced ident!
+ if ( ! explicitKind )
+ {
+ _name = _ident;
+ // No kind defaults to package
+ if ( !_kind )
+ _kind = ResKind::package;
+ else if ( ! ( _kind == ResKind::package || _kind == ResKind::srcpackage ) )
+ _ident = IdString( str::form( "%s:%s", _kind.c_str(), _ident.c_str() ) );
+ }
+ else
+ {
+ // strip kind spec from name
+ _name = IdString( ::strchr( _ident.c_str(), ':' )+1 );
+ _kind = explicitKind;
+ if ( _kind == ResKind::package || _kind == ResKind::srcpackage )
+ _ident = _name;
+ }
+ 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 'i': OUTS( script, 6 ); return; break;
- case 'k': OUTS( package, 7 ); return; break;
- case 'm': OUTS( atom, 4 ); return; break;
- case 'p': OUTS( srcpackage, 10 ); return; break;
- case 's': OUTS( message, 7 ); return; break;
- case 't': OUTS( pattern, 7 ); return; break;
-#undef OUTS
- }
- }
+ Solvable::SplitIdent::SplitIdent( IdString ident_r )
+ : _ident( ident_r )
+ { _doSplit( _ident, _kind, _name ); }
- // an unknown kind
- _kind = ResKind( std::string( ident, sep-ident ) );
- }
+ Solvable::SplitIdent::SplitIdent( const char * ident_r )
+ : _ident( ident_r )
+ { _doSplit( _ident, _kind, _name ); }
+
+ Solvable::SplitIdent::SplitIdent( const std::string & ident_r )
+ : _ident( ident_r )
+ { _doSplit( _ident, _kind, _name ); }
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() ) );
- }
+ : _ident( name_r )
+ , _kind( kind_r )
+ { _doSplit( _ident, _kind, _name ); }
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() ) );
- }
+ : _ident( name_r )
+ , _kind( kind_r )
+ { _doSplit( _ident, _kind, _name ); }
/////////////////////////////////////////////////////////////////
bool Solvable::isSystem() const
{
NO_SOLVABLE_RETURN( _id == detail::systemSolvableId );
- return Repository( _solvable->repo ).isSystemRepo();
+ return myPool().isSystemRepo( _solvable->repo );
+ }
+
+ bool Solvable::onSystemByUser() const
+ {
+ return isSystem() && myPool().isOnSystemByUser( ident() );
}
IdString Solvable::ident() const
}
else
{
- s = ::solvable_lookup_str_lang( _solvable, attr.id(), lang_r.code().c_str() );
+ for ( Locale l( lang_r ); l != Locale::noCode; l = l.fallback() )
+ if ( (s = ::solvable_lookup_str_lang( _solvable, attr.id(), l.code().c_str(), 0 )) )
+ return s;
+ // here: no matching locale, so use default
+ s = ::solvable_lookup_str_lang( _solvable, attr.id(), 0, 0 );
}
return s ? s : std::string();
}
- unsigned Solvable::lookupNumAttribute( const SolvAttr & attr ) const
+ unsigned long long Solvable::lookupNumAttribute( const SolvAttr & attr ) const
{
NO_SOLVABLE_RETURN( 0 );
return ::solvable_lookup_num( _solvable, attr.id(), 0 );
{
case REPOKEY_TYPE_MD5: return CheckSum::md5( s );
case REPOKEY_TYPE_SHA1: return CheckSum::sha1( s );
+ case REPOKEY_TYPE_SHA224: return CheckSum::sha224( s );
case REPOKEY_TYPE_SHA256: return CheckSum::sha256( s );
+ case REPOKEY_TYPE_SHA384: return CheckSum::sha384( s );
+ case REPOKEY_TYPE_SHA512: return CheckSum::sha512( s );
}
return CheckSum( std::string(), s ); // try to autodetect
}
+ ///////////////////////////////////////////////////////////////////
+ namespace
+ {
+ inline Pathname lookupDatadirIn( Repository repor_r )
+ {
+ static const sat::SolvAttr susetagsDatadir( "susetags:datadir" );
+ Pathname ret;
+ // First look for repo attribute "susetags:datadir". If not found,
+ // look into the solvables as Code11 libsolv placed it there.
+ sat::LookupRepoAttr datadir( susetagsDatadir, repor_r );
+ if ( ! datadir.empty() )
+ ret = datadir.begin().asString();
+ else
+ {
+ sat::LookupAttr datadir( susetagsDatadir, repor_r );
+ if ( ! datadir.empty() )
+ ret = datadir.begin().asString();
+ }
+ return ret;
+ }
+ }
+ ///////////////////////////////////////////////////////////////////
+
OnMediaLocation Solvable::lookupLocation() const
- //std::string Solvable::lookupLocation( unsigned & medianr ) const
{
NO_SOLVABLE_RETURN( OnMediaLocation() );
// medianumber and path
unsigned medianr;
- char * file = ::solvable_get_location( _solvable, &medianr );
+ const char * file = ::solvable_lookup_location( _solvable, &medianr );
if ( ! file )
return OnMediaLocation();
+ if ( ! medianr )
+ medianr = 1;
OnMediaLocation ret;
Pathname path;
- if ( repository().info().type().toEnum() == repo::RepoType::YAST2_e )
+ switch ( repository().info().type().toEnum() )
{
-#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";
+ case repo::RepoType::NONE_e:
+ {
+ path = lookupDatadirIn( repository() );
+ if ( ! path.empty() )
+ repository().info().setProbedType( repo::RepoType::YAST2_e );
+ }
+ break;
+
+ case repo::RepoType::YAST2_e:
+ {
+ path = lookupDatadirIn( repository() );
+ if ( path.empty() )
+ path = "suse";
+ }
+ break;
+
+ default:
+ break;
}
ret.setLocation ( path/file, medianr );
- ret.setDownloadSize( ByteCount( lookupNumAttribute( SolvAttr::downloadsize ), ByteCount::K ) );
+ ret.setDownloadSize( ByteCount( lookupNumAttribute( SolvAttr::downloadsize ) ) );
ret.setChecksum ( lookupCheckSumAttribute( SolvAttr::checksum ) );
// Not needed/available for solvables?
- //ret.setOpenSize ( ByteCount( lookupNumAttribute( SolvAttr::opensize ), ByteCount::K ) );
+ //ret.setOpenSize ( ByteCount( lookupNumAttribute( SolvAttr::opensize ) ) );
//ret.setOpenChecksum( lookupCheckSumAttribute( SolvAttr::openchecksum ) );
return ret;
}
break;
}
+ // either explicitly prefixed...
const char * ident = IdString( _solvable->name ).c_str();
- const char * sep = ::strchr( ident, ':' );
+ ResKind knownKind( ResKind::explicitBuiltin( ident ) );
+ if ( knownKind )
+ return knownKind;
- // no ':' in package names (hopefully)
+ // ...or no ':' in package names (hopefully)...
+ const char * sep = ::strchr( ident, ':' );
if ( ! sep )
- return ResKind::package;
-
- // 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 ) ) return ResKind::K
- // ----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
- }
- }
+ return ResKind::package;
- // an unknown kind
+ // ...or something unknown.
return ResKind( std::string( ident, sep-ident ) );
}
//return ArchId( _solvable->arch );
}
+ bool Solvable::multiversionInstall() const
+ {
+ return myPool().isMultiversion( ident() );
+ }
+
IdString Solvable::vendor() const
{
NO_SOLVABLE_RETURN( IdString() );
case Dep::OBSOLETES_e: return obsoletes(); break;
case Dep::RECOMMENDS_e: return recommends(); break;
case Dep::SUGGESTS_e: return suggests(); break;
- case Dep::FRESHENS_e: return freshens(); break;
case Dep::ENHANCES_e: return enhances(); break;
case Dep::SUPPLEMENTS_e: return supplements(); break;
case Dep::PREREQUIRES_e: return prerequires(); break;
NO_SOLVABLE_RETURN( Capabilities() );
return _getCapabilities( _solvable->repo->idarraydata, _solvable->suggests );
}
- Capabilities Solvable::freshens() const
- {
- NO_SOLVABLE_RETURN( Capabilities() );
- return _getCapabilities( _solvable->repo->idarraydata, _solvable->freshens );
- }
Capabilities Solvable::enhances() const
{
NO_SOLVABLE_RETURN( Capabilities() );
: Capabilities();
}
+ CapabilitySet Solvable::providesNamespace( const std::string & namespace_r ) const
+ {
+ NO_SOLVABLE_RETURN( CapabilitySet() );
+ CapabilitySet ret;
+ Capabilities caps( provides() );
+ for_( it, caps.begin(), caps.end() )
+ {
+ CapDetail caprep( it->detail() );
+ if ( str::hasPrefix( caprep.name().c_str(), namespace_r ) && *(caprep.name().c_str()+namespace_r.size()) == '(' )
+ ret.insert( *it );
+ }
+ return ret;
+ }
+
+ CapabilitySet Solvable::valuesOfNamespace( const std::string & namespace_r ) const
+ {
+ NO_SOLVABLE_RETURN( CapabilitySet() );
+ CapabilitySet ret;
+ Capabilities caps( provides() );
+ for_( it, caps.begin(), caps.end() )
+ {
+ CapDetail caprep( it->detail() );
+ if ( str::hasPrefix( caprep.name().c_str(), namespace_r ) && *(caprep.name().c_str()+namespace_r.size()) == '(' )
+ {
+ std::string value( caprep.name().c_str()+namespace_r.size()+1 );
+ value[value.size()-1] = '\0'; // erase the trailing ')'
+ ret.insert( Capability( value, caprep.op(), caprep.ed() ) );
+ }
+ }
+ return ret;
+ }
+
+
+ std::string Solvable::asString() const
+ {
+ NO_SOLVABLE_RETURN( (_id == detail::systemSolvableId ? "systemSolvable" : "noSolvable") );
+ return str::form( "%s-%s.%s",
+ IdString( _solvable->name ).c_str(),
+ IdString( _solvable->evr ).c_str(),
+ IdString( _solvable->arch ).c_str() );
+ }
+
+ std::string Solvable::asUserString() const\
+ {
+ NO_SOLVABLE_RETURN( (_id == detail::systemSolvableId ? "systemSolvable" : "noSolvable") );
+ return str::form( "%s-%s.%s(%s)",
+ IdString( _solvable->name ).c_str(),
+ IdString( _solvable->evr ).c_str(),
+ IdString( _solvable->arch ).c_str(),
+ repository().asUserString().c_str() );
+ }
+
+ bool Solvable::identical( Solvable rhs ) const
+ {
+ NO_SOLVABLE_RETURN( ! rhs.get() );
+ ::_Solvable * rhssolvable( rhs.get() );
+ return rhssolvable && ( _solvable == rhssolvable || ::solvable_identical( _solvable, rhssolvable ) );
+ }
+
///////////////////////////////////////////////////////////////////
namespace
{ /////////////////////////////////////////////////////////////////
return str << "(" << obj.id() << ")"
<< ( obj.isKind( ResKind::srcpackage ) ? "srcpackage:" : "" ) << obj.ident()
<< '-' << obj.edition() << '.' << obj.arch() << "("
- << obj.repository().name() << ")";
+ << obj.repository().alias() << ")";
}
/******************************************************************
OUTS(OBSOLETES);
OUTS(RECOMMENDS);
OUTS(SUGGESTS);
- OUTS(FRESHENS);
OUTS(ENHANCES);
OUTS(SUPPLEMENTS);
#undef OUTS
return str;
}
+ std::ostream & dumpAsXmlOn( std::ostream & str, const Solvable & obj )
+ {
+ xmlout::Node guard( str, "solvable" );
+
+ dumpAsXmlOn( *guard, obj.kind() );
+ *xmlout::Node( *guard, "name" ) << obj.name();
+ dumpAsXmlOn( *guard, obj.edition() );
+ dumpAsXmlOn( *guard, obj.arch() );
+ dumpAsXmlOn( *guard, obj.repository() );
+ return str;
+ }
+
/////////////////////////////////////////////////////////////////
} // namespace sat
///////////////////////////////////////////////////////////////////