#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"
+
+#include "zypp/ui/Selectable.h"
using std::endl;
///////////////////////////////////////////////////////////////////
namespace zypp
-{ /////////////////////////////////////////////////////////////////
+{
///////////////////////////////////////////////////////////////////
namespace sat
- { /////////////////////////////////////////////////////////////////
+ {
+ ///////////////////////////////////////////////////////////////////
+ namespace
+ {
+ void _doSplit( IdString & _ident, ResKind & _kind, IdString & _name )
+ {
+ 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;
+ }
+ } // namespace
+ ///////////////////////////////////////////////////////////////////
+
+ Solvable::SplitIdent::SplitIdent( IdString ident_r )
+ : _ident( ident_r )
+ { _doSplit( _ident, _kind, _name ); }
+
+ 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 )
+ : _ident( name_r )
+ , _kind( kind_r )
+ { _doSplit( _ident, _kind, _name ); }
+
+ Solvable::SplitIdent::SplitIdent( ResKind kind_r, const C_Str & name_r )
+ : _ident( name_r )
+ , _kind( kind_r )
+ { _doSplit( _ident, _kind, _name ); }
- const Solvable Solvable::nosolvable;
+ /////////////////////////////////////////////////////////////////
+ // class Solvable
+ /////////////////////////////////////////////////////////////////
+
+ const Solvable Solvable::noSolvable;
/////////////////////////////////////////////////////////////////
- ::_Solvable * Solvable::get() const
+ detail::CSolvable * Solvable::get() const
{ return myPool().getSolvable( _id ); }
#define NO_SOLVABLE_RETURN( VAL ) \
- ::_Solvable * _solvable( get() ); \
+ detail::CSolvable * _solvable( get() ); \
if ( ! _solvable ) return VAL
Solvable Solvable::nextInPool() const
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 ) );
+ detail::CSolvable * nextS( myPool().getSolvable( next ) );
if ( nextS && nextS->repo == _solvable->repo )
{
return Solvable( next );
}
}
- return nosolvable;
+ return noSolvable;
}
- Repository Solvable::repository() const
+ std::string Solvable::lookupStrAttribute( const SolvAttr & attr ) const
{
- NO_SOLVABLE_RETURN( Repository::noRepository );
- return Repository( _solvable->repo );
+ NO_SOLVABLE_RETURN( std::string() );
+ const char * s = ::solvable_lookup_str( _solvable, attr.id() );
+ return s ? s : std::string();
}
- bool Solvable::isSystem() const
- { return repository().isSystemRepo(); }
-
- IdString Solvable::ident() const
+ std::string Solvable::lookupStrAttribute( const SolvAttr & attr, const Locale & lang_r ) const
{
- NO_SOLVABLE_RETURN( IdString() );
- return IdString( _solvable->name );
- }
+ NO_SOLVABLE_RETURN( std::string() );
+ const char * s = 0;
+ if ( !lang_r )
+ {
+ s = ::solvable_lookup_str_poollang( _solvable, attr.id() );
+ }
+ else
+ {
+ for ( Locale l( lang_r ); l; l = l.fallback() )
+ {
+ if ( (s = ::solvable_lookup_str_lang( _solvable, attr.id(), l.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();
+ }
- std::string Solvable::lookupStrAttribute( const SolvAttr &attr ) const
+ unsigned long long Solvable::lookupNumAttribute( const SolvAttr & attr ) const
{
- const char *s = repo_lookup_str(this->get(), attr.idStr().id());
- return s ? s : std::string();
+ NO_SOLVABLE_RETURN( 0 );
+ return ::solvable_lookup_num( _solvable, attr.id(), 0 );
}
- unsigned Solvable::lookupNumAttribute( const SolvAttr &attr ) const
+ unsigned long long Solvable::lookupNumAttribute( const SolvAttr & attr, unsigned long long notfound_r ) const
{
- return repo_lookup_num(this->get(), attr.idStr().id());
+ NO_SOLVABLE_RETURN( notfound_r );
+ return ::solvable_lookup_num( _solvable, attr.id(), notfound_r );
}
- 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 REPOKEY_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 REPOKEY_TYPE_STR:
- if (key->name == SolvAttr::mediafile.idStr().id())
- lc->mediafile = kv->str;
- break;
- case REPOKEY_TYPE_VOID:
- if (key->name == SolvAttr::mediafile.idStr().id())
- lc->trivial = 1;
- break;
- case REPOKEY_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_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 );
}
- /* continue walking */
- return 0;
+ return CheckSum( std::string(), s ); // try to autodetect
}
- std::string Solvable::lookupLocation(unsigned &medianr) const
+ ///////////////////////////////////////////////////////////////////
+ namespace
{
- 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++)
+ inline Pathname lookupDatadirIn( Repository repor_r )
{
- 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);
+ static const 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.
+ LookupRepoAttr datadir( susetagsDatadir, repor_r );
+ if ( ! datadir.empty() )
+ ret = datadir.begin().asString();
+ else
+ {
+ LookupAttr datadir( susetagsDatadir, repor_r );
+ if ( ! datadir.empty() )
+ ret = datadir.begin().asString();
+ }
+ return ret;
}
- medianr = lc.medianr;
- std::string ret;
+ } // namespace
+ ///////////////////////////////////////////////////////////////////
- if (lc.mediadir)
- {
- ret += std::string( lc.mediadir ) + "/";
- }
- else
- {
- /* If we haven't seen an explicit dirname, then prepend the arch as
- directory. */
- ret += "suse/";
- ret += IdString(_solvable->arch).asString() + "/";
- }
+ OnMediaLocation Solvable::lookupLocation() const
+ {
+ NO_SOLVABLE_RETURN( OnMediaLocation() );
+ // medianumber and path
+ unsigned medianr;
+ const char * file = ::solvable_lookup_location( _solvable, &medianr );
+ if ( ! file )
+ return OnMediaLocation();
+ if ( ! medianr )
+ medianr = 1;
+
+ OnMediaLocation ret;
- if (!lc.trivial)
+ Pathname path;
+ switch ( repository().info().type().toEnum() )
{
- if (lc.mediafile)
- ret += lc.mediafile;
- return ret;
- }
+ 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;
- /* 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";
+ default:
+ break;
+ }
+ ret.setLocation ( path/file, medianr );
+ ret.setDownloadSize( ByteCount( lookupNumAttribute( SolvAttr::downloadsize ) ) );
+ ret.setChecksum ( lookupCheckSumAttribute( SolvAttr::checksum ) );
+ // Not needed/available for solvables?
+ //ret.setOpenSize ( ByteCount( lookupNumAttribute( SolvAttr::opensize ) ) );
+ //ret.setOpenChecksum( lookupCheckSumAttribute( SolvAttr::openchecksum ) );
return ret;
}
- ResKind Solvable::kind() const
+
+ IdString Solvable::ident() const
+ {
+ NO_SOLVABLE_RETURN( IdString() );
+ return IdString( _solvable->name );
+ }
+
+ ResKind Solvable::kind() const
{
NO_SOLVABLE_RETURN( ResKind() );
// detect srcpackages by 'arch'
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 ) );
}
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)
return IdString( _solvable->vendor );
}
- Capabilities Solvable::operator[]( Dep which_r ) const
+ Repository Solvable::repository() const
{
- switch( which_r.inSwitch() )
- {
- case Dep::PROVIDES_e: return provides(); break;
- case Dep::REQUIRES_e: return requires(); break;
- case Dep::CONFLICTS_e: return conflicts(); break;
- 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;
- }
- return Capabilities();
+ NO_SOLVABLE_RETURN( Repository::noRepository );
+ return Repository( _solvable->repo );
+ }
+
+ RepoInfo Solvable::repoInfo() const
+ { return repository().info(); }
+
+
+ bool Solvable::isSystem() const
+ {
+ NO_SOLVABLE_RETURN( _id == detail::systemSolvableId );
+ return myPool().isSystemRepo( _solvable->repo );
+ }
+
+ bool Solvable::onSystemByUser() const
+ {
+ return isSystem() && myPool().isOnSystemByUser( ident() );
+ }
+
+ bool Solvable::onSystemByAuto() const
+ {
+ return isSystem() && myPool().isOnSystemByAuto( ident() );
+ }
+
+ bool Solvable::identIsAutoInstalled( const IdString & ident_r )
+ {
+ return myPool().isOnSystemByAuto( ident_r );
+ }
+
+ bool Solvable::multiversionInstall() const
+ {
+ NO_SOLVABLE_RETURN( false );
+ return myPool().isMultiversion( *this );
+ }
+
+ Date Solvable::buildtime() const
+ {
+ NO_SOLVABLE_RETURN( Date() );
+ return Date( lookupNumAttribute( SolvAttr::buildtime ) );
+ }
+
+ Date Solvable::installtime() const
+ {
+ NO_SOLVABLE_RETURN( Date() );
+ return Date( lookupNumAttribute( SolvAttr::installtime ) );
+ }
+
+ 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() );
}
- inline Capabilities _getCapabilities( detail::IdType * idarraydata_r, ::Offset offs_r )
+ std::string Solvable::asUserString() const\
{
- return offs_r ? Capabilities( idarraydata_r + offs_r ) : Capabilities();
+ 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( const Solvable & rhs ) const
+ {
+ NO_SOLVABLE_RETURN( ! rhs.get() );
+ detail::CSolvable * rhssolvable( rhs.get() );
+ return rhssolvable && ( _solvable == rhssolvable || ::solvable_identical( _solvable, rhssolvable ) );
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ namespace
+ {
+ inline Capabilities _getCapabilities( detail::IdType * idarraydata_r, ::Offset offs_r )
+ {
+ return offs_r ? Capabilities( idarraydata_r + offs_r ) : Capabilities();
+ }
+ } // namespace
+ ///////////////////////////////////////////////////////////////////
+
Capabilities Solvable::provides() const
{
NO_SOLVABLE_RETURN( Capabilities() );
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;
+ }
+
///////////////////////////////////////////////////////////////////
namespace
- { /////////////////////////////////////////////////////////////////
- /** Expand \ref Capability and call \c fnc_r for each namescpace:language
+ {
+ /** Expand \ref Capability and call \c fnc_r for each namespace:language
* dependency. Return #invocations of fnc_r, negative if fnc_r returned
* false to indicate abort.
*/
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;
+ {
+ 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 )
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
+ /** Expand \ref Capability and call \c fnc_r for each namespace: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 )
+ inline int invokeOnEachSupportedLocale( Capabilities cap_r, function<bool (Locale)> fnc_r )
{
int cnt = 0;
for_( cit, cap_r.begin(), cap_r.end() )
const LocaleSet & _locales;
};
-
- } /////////////////////////////////////////////////////////////////
+ } // namespace
+ ///////////////////////////////////////////////////////////////////
bool Solvable::supportsLocales() const
{
bool Solvable::supportsRequestedLocales() const
{ return supportsLocale( myPool().getRequestedLocales() ); }
- void Solvable::getSupportedLocales( LocaleSet & locales_r ) const
+ LocaleSet Solvable::getSupportedLocales() const
+ {
+ LocaleSet ret;
+ invokeOnEachSupportedLocale( supplements(), functor::collector( std::inserter( ret, ret.begin() ) ) );
+ return ret;
+ }
+
+ CpeId Solvable::cpeId() const
+ {
+ NO_SOLVABLE_RETURN( CpeId() );
+ return CpeId( lookupStrAttribute( SolvAttr::cpeid ), CpeId::noThrow );
+ }
+
+ unsigned Solvable::mediaNr() const
+ {
+ NO_SOLVABLE_RETURN( 0U );
+ return lookupNumAttribute( SolvAttr::medianr );
+ }
+
+ ByteCount Solvable::installSize() const
+ {
+ NO_SOLVABLE_RETURN( ByteCount() );
+ return ByteCount( lookupNumAttribute( SolvAttr::installsize ) );
+ }
+
+ ByteCount Solvable::downloadSize() const
+ {
+ NO_SOLVABLE_RETURN( ByteCount() );
+ return ByteCount( lookupNumAttribute( SolvAttr::downloadsize ) );
+ }
+
+ std::string Solvable::distribution() const
+ {
+ NO_SOLVABLE_RETURN( std::string() );
+ return lookupStrAttribute( SolvAttr::distribution );
+ }
+
+ std::string Solvable::summary( const Locale & lang_r ) const
+ {
+ NO_SOLVABLE_RETURN( std::string() );
+ return lookupStrAttribute( SolvAttr::summary, lang_r );
+ }
+
+ std::string Solvable::description( const Locale & lang_r ) const
+ {
+ NO_SOLVABLE_RETURN( std::string() );
+ return lookupStrAttribute( SolvAttr::description, lang_r );
+ }
+
+ std::string Solvable::insnotify( const Locale & lang_r ) const
+ {
+ NO_SOLVABLE_RETURN( std::string() );
+ return lookupStrAttribute( SolvAttr::insnotify, lang_r );
+ }
+
+ std::string Solvable::delnotify( const Locale & lang_r ) const
+ {
+ NO_SOLVABLE_RETURN( std::string() );
+ return lookupStrAttribute( SolvAttr::delnotify, lang_r );
+ }
+
+ std::string Solvable::licenseToConfirm( const Locale & lang_r ) const
+ {
+ NO_SOLVABLE_RETURN( std::string() );
+ std::string ret = lookupStrAttribute( SolvAttr::eula, lang_r );
+ if ( ret.empty() && isKind<Product>() )
+ {
+ const RepoInfo & ri( repoInfo() );
+ std::string riname( name() ); // "license-"+name with fallback "license"
+ if ( ! ri.hasLicense( riname ) )
+ riname.clear();
+
+ if ( ri.needToAcceptLicense( riname ) || ! ui::Selectable::get( *this )->hasInstalledObj() )
+ ret = ri.getLicense( riname, lang_r ); // bnc#908976: suppress informal license upon update
+ }
+ return ret;
+ }
+
+ bool Solvable::needToAcceptLicense() const
{
- invokeOnEachSupportedLocale( supplements(),
- functor::Collector( std::inserter( locales_r, locales_r.begin() ) ) );
+ NO_SOLVABLE_RETURN( false );
+ if ( isKind<Product>() )
+ {
+ const RepoInfo & ri( repoInfo() );
+ std::string riname( name() ); // "license-"+name with fallback "license"
+ if ( ! ri.hasLicense( riname ) )
+ riname.clear();
+
+ return ri.needToAcceptLicense( riname );
+ }
+ return true;
}
- /******************************************************************
- **
- ** FUNCTION NAME : operator<<
- ** FUNCTION TYPE : std::ostream &
- */
+
std::ostream & operator<<( std::ostream & str, const Solvable & obj )
{
if ( ! obj )
- return str << "sat::solvable()";
+ return str << (obj.isSystem() ? "systemSolvable" : "noSolvable" );
return str << "(" << obj.id() << ")"
<< ( obj.isKind( ResKind::srcpackage ) ? "srcpackage:" : "" ) << obj.ident()
<< '-' << obj.edition() << '.' << obj.arch() << "("
- << obj.repository().name() << ")";
+ << obj.repository().alias() << ")";
}
- /******************************************************************
- **
- ** FUNCTION NAME : dumpOn
- ** FUNCTION TYPE : std::ostream &
- */
std::ostream & dumpOn( std::ostream & str, const Solvable & obj )
{
str << obj;
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
///////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////
} // namespace zypp
///////////////////////////////////////////////////////////////////