#include "zypp/ZConfig.h"
#include "zypp/sat/detail/PoolImpl.h"
+#include "zypp/sat/SolvableSet.h"
#include "zypp/sat/Pool.h"
#include "zypp/Capability.h"
#include "zypp/Locale.h"
BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_NAMESPACE, ==, REL_NAMESPACE );
BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_ARCH, ==, REL_ARCH );
- /////////////////////////////////////////////////////////////////
+ BOOST_MPL_ASSERT_RELATION( namespaceModalias, ==, NAMESPACE_MODALIAS );
+ BOOST_MPL_ASSERT_RELATION( namespaceLanguage, ==, NAMESPACE_LANGUAGE );
+ BOOST_MPL_ASSERT_RELATION( namespaceFilesystem, ==, NAMESPACE_FILESYSTEM );
+
+ /////////////////////////////////////////////////////////////////
+
+ const bool resusePoolIDs = true;
const std::string & PoolImpl::systemRepoAlias()
{
return _val;
}
-
/////////////////////////////////////////////////////////////////
- static void logSat( struct _Pool *, void *data, int type, const char *logString )
+ static void logSat( CPool *, void *data, int type, const char *logString )
{
if ( type & (SOLV_FATAL|SOLV_ERROR) ) {
- _ERR("libsolv") << logString;
+ L_ERR("libsolv") << logString;
} else if ( type & SOLV_DEBUG_STATS ) {
- _DBG("libsolv") << logString;
+ L_DBG("libsolv") << logString;
} else {
- _MIL("libsolv") << logString;
+ L_MIL("libsolv") << logString;
}
}
- detail::IdType PoolImpl::nsCallback( struct _Pool *, void * data, detail::IdType lhs, detail::IdType rhs )
+ detail::IdType PoolImpl::nsCallback( CPool *, void * data, detail::IdType lhs, detail::IdType rhs )
{
// lhs: the namespace identifier, e.g. NAMESPACE:MODALIAS
// rhs: the value, e.g. pci:v0000104Cd0000840[01]sv*sd*bc*sc*i*
{
case NAMESPACE_LANGUAGE:
{
- static IdString en( "en" );
- const std::tr1::unordered_set<IdString> & locale2Solver( reinterpret_cast<PoolImpl*>(data)->_locale2Solver );
- if ( locale2Solver.empty() )
- {
- return rhs == en.id() ? RET_systemProperty : RET_unsupported;
- }
- return locale2Solver.find( IdString(rhs) ) != locale2Solver.end() ? RET_systemProperty : RET_unsupported;
+ const TrackedLocaleIds & localeIds( reinterpret_cast<PoolImpl*>(data)->trackedLocaleIds() );
+ return localeIds.contains( IdString(rhs) ) ? RET_systemProperty : RET_unsupported;
}
break;
}
break;
- case NAMESPACE_PRODUCTBUDDY:
- {
- PoolItem pi( (Solvable(rhs)) );
- return( pi ? pi.buddy().id() : noId );
- }
-
- break;
}
WAR << "Unhandled " << Capability( lhs ) << " vs. " << Capability( rhs ) << endl;
{
ZYPP_THROW( Exception( _("Can not create sat-pool.") ) );
}
+ // by now we support only a RPM backend
+ ::pool_setdisttype(_pool, DISTTYPE_RPM );
+
// initialialize logging
if ( env::LIBSOLV_DEBUGMASK() )
{
_availableLocalesPtr.reset(); // available locales may change
_multiversionListPtr.reset(); // re-evaluate ZConfig::multiversionSpec.
- // invaldate dependency/namespace related indices:
- depSetDirty();
+ depSetDirty(); // invaldate dependency/namespace related indices
+ }
+
+ void PoolImpl::localeSetDirty( const char * a1, const char * a2, const char * a3 )
+ {
+ if ( a1 )
+ {
+ if ( a3 ) MIL << a1 << " " << a2 << " " << a3 << endl;
+ else if ( a2 ) MIL << a1 << " " << a2 << endl;
+ else MIL << a1 << endl;
+ }
+ _trackedLocaleIdsPtr.reset(); // requested locales changed
+ depSetDirty(); // invaldate dependency/namespace related indices
}
void PoolImpl::depSetDirty( const char * a1, const char * a2, const char * a3 )
void PoolImpl::prepare() const
{
+ // additional /etc/sysconfig/storage check:
+ static WatchFile sysconfigFile( sysconfigStoragePath(), WatchFile::NO_INIT );
+ if ( sysconfigFile.hasChanged() )
+ {
+ _requiredFilesystemsPtr.reset(); // recreated on demand
+ const_cast<PoolImpl*>(this)->depSetDirty( "/etc/sysconfig/storage change" );
+ }
if ( _watcher.remember( _serial ) )
{
// After repo/solvable add/remove:
}
}
- void PoolImpl::prepareForSolving() const
- {
- // additional /etc/sysconfig/storage check:
- static WatchFile sysconfigFile( sysconfigStoragePath(), WatchFile::NO_INIT );
- if ( sysconfigFile.hasChanged() )
- {
- _requiredFilesystemsPtr.reset(); // recreated on demand
- const_cast<PoolImpl*>(this)->depSetDirty( "/etc/sysconfig/storage change" );
- }
- // finally prepare as usual:
- prepare();
- }
-
///////////////////////////////////////////////////////////////////
- ::_Repo * PoolImpl::_createRepo( const std::string & name_r )
+ CRepo * PoolImpl::_createRepo( const std::string & name_r )
{
setDirty(__FUNCTION__, name_r.c_str() );
- ::_Repo * ret = ::repo_create( _pool, name_r.c_str() );
+ CRepo * ret = ::repo_create( _pool, name_r.c_str() );
if ( ret && name_r == systemRepoAlias() )
::pool_set_installed( _pool, ret );
return ret;
}
- void PoolImpl::_deleteRepo( ::_Repo * repo_r )
+ void PoolImpl::_deleteRepo( CRepo * repo_r )
{
setDirty(__FUNCTION__, repo_r->name );
- ::repo_free( repo_r, /*reuseids*/false );
- eraseRepoInfo( repo_r );
if ( isSystemRepo( repo_r ) )
- {
- // systemRepo added
- _onSystemByUserListPtr.reset(); // re-evaluate
- }
+ _autoinstalled.clear();
+ eraseRepoInfo( repo_r );
+ ::repo_free( repo_r, resusePoolIDs );
+ if ( resusePoolIDs && !_pool->urepos ) // If the last repo is removed clear the pool to actually reuse all IDs.
+ ::pool_freeallrepos( _pool, resusePoolIDs );
}
- int PoolImpl::_addSolv( ::_Repo * repo_r, FILE * file_r )
+ int PoolImpl::_addSolv( CRepo * repo_r, FILE * file_r )
{
setDirty(__FUNCTION__, repo_r->name );
int ret = ::repo_add_solv( repo_r, file_r, 0 );
return ret;
}
- int PoolImpl::_addHelix( ::_Repo * repo_r, FILE * file_r )
+ int PoolImpl::_addHelix( CRepo * repo_r, FILE * file_r )
{
setDirty(__FUNCTION__, repo_r->name );
int ret = ::repo_add_helix( repo_r, file_r, 0 );
return 0;
}
- void PoolImpl::_postRepoAdd( ::_Repo * repo_r )
+ void PoolImpl::_postRepoAdd( CRepo * repo_r )
{
if ( ! isSystemRepo( repo_r ) )
{
unsigned blockSize = 0;
for ( detail::IdType i = repo_r->start; i < repo_r->end; ++i )
{
- ::_Solvable * s( _pool->solvables + i );
+ CSolvable * s( _pool->solvables + i );
if ( s->repo == repo_r && sysids.find( s->arch ) == sysids.end() )
{
// Remember an unwanted arch entry:
else if ( blockSize )
{
// Free remembered entries
- ::repo_free_solvable_block( repo_r, blockBegin, blockSize, /*reuseids*/false );
+ ::repo_free_solvable_block( repo_r, blockBegin, blockSize, resusePoolIDs );
blockBegin = blockSize = 0;
}
}
if ( blockSize )
{
// Free remembered entries
- ::repo_free_solvable_block( repo_r, blockBegin, blockSize, /*reuseids*/false );
+ ::repo_free_solvable_block( repo_r, blockBegin, blockSize, resusePoolIDs );
blockBegin = blockSize = 0;
}
}
- else
- {
- // systemRepo added
- _onSystemByUserListPtr.reset(); // re-evaluate
- }
}
- detail::SolvableIdType PoolImpl::_addSolvables( ::_Repo * repo_r, unsigned count_r )
+ detail::SolvableIdType PoolImpl::_addSolvables( CRepo * repo_r, unsigned count_r )
{
setDirty(__FUNCTION__, repo_r->name );
return ::repo_add_solvable_block( repo_r, count_r );
void PoolImpl::setRepoInfo( RepoIdType id_r, const RepoInfo & info_r )
{
- ::_Repo * repo( getRepo( id_r ) );
+ CRepo * repo( getRepo( id_r ) );
if ( repo )
{
bool dirty = false;
///////////////////////////////////////////////////////////////////
- // need on demand and id based Locale
- void _locale_hack( const LocaleSet & locales_r,
- std::tr1::unordered_set<IdString> & locale2Solver )
- {
- std::tr1::unordered_set<IdString>( 2*locales_r.size() ).swap( locale2Solver );
- for_( it, locales_r.begin(),locales_r.end() )
- {
- for ( Locale l( *it ); l != Locale::noCode; l = l.fallback() )
- locale2Solver.insert( IdString( l.code() ) );
- }
- MIL << "New Solver Locales: " << locale2Solver << endl;
- }
-
void PoolImpl::setTextLocale( const Locale & locale_r )
{
std::vector<std::string> fallbacklist;
- for ( Locale l( locale_r ); l != Locale::noCode; l = l.fallback() )
+ for ( Locale l( locale_r ); l; l = l.fallback() )
{
fallbacklist.push_back( l.code() );
}
::pool_set_languages( _pool, &fallbacklist_cstr.front(), fallbacklist_cstr.size() );
}
+ void PoolImpl::initRequestedLocales( const LocaleSet & locales_r )
+ {
+ if ( _requestedLocalesTracker.setInitial( locales_r ) )
+ {
+ localeSetDirty( "initRequestedLocales" );
+ MIL << "Init RequestedLocales: " << _requestedLocalesTracker << " =" << locales_r << endl;
+ }
+ }
+
void PoolImpl::setRequestedLocales( const LocaleSet & locales_r )
{
- depSetDirty( "setRequestedLocales" );
- _requestedLocales = locales_r;
- MIL << "New RequestedLocales: " << locales_r << endl;
- _locale_hack( _requestedLocales, _locale2Solver );
+ if ( _requestedLocalesTracker.set( locales_r ) )
+ {
+ localeSetDirty( "setRequestedLocales" );
+ MIL << "New RequestedLocales: " << _requestedLocalesTracker << " =" << locales_r << endl;
+ }
}
bool PoolImpl::addRequestedLocale( const Locale & locale_r )
{
- if ( _requestedLocales.insert( locale_r ).second )
+ bool done = _requestedLocalesTracker.add( locale_r );
+ if ( done )
{
- depSetDirty( "addRequestedLocale", locale_r.code().c_str() );
- _locale_hack( _requestedLocales, _locale2Solver );
- return true;
+ localeSetDirty( "addRequestedLocale", locale_r.code().c_str() );
+ MIL << "New RequestedLocales: " << _requestedLocalesTracker << " +" << locale_r << endl;
}
- return false;
+ return done;
}
bool PoolImpl::eraseRequestedLocale( const Locale & locale_r )
{
- if ( _requestedLocales.erase( locale_r ) )
+ bool done = _requestedLocalesTracker.remove( locale_r );
+ if ( done )
{
- depSetDirty( "addRequestedLocale", locale_r.code().c_str() );
- _locale_hack( _requestedLocales, _locale2Solver );
- return true;
+ localeSetDirty( "addRequestedLocale", locale_r.code().c_str() );
+ MIL << "New RequestedLocales: " << _requestedLocalesTracker << " -" << locale_r << endl;
}
- return false;
+ return done;
}
- static void _getLocaleDeps( Capability cap_r, std::tr1::unordered_set<sat::detail::IdType> & store_r )
+
+ const PoolImpl::TrackedLocaleIds & PoolImpl::trackedLocaleIds() const
+ {
+ if ( ! _trackedLocaleIdsPtr )
+ {
+ _trackedLocaleIdsPtr.reset( new TrackedLocaleIds );
+
+ const base::SetTracker<LocaleSet> & localesTracker( _requestedLocalesTracker );
+ TrackedLocaleIds & localeIds( *_trackedLocaleIdsPtr );
+
+ // Add current locales+fallback except for added ones
+ for ( Locale lang: localesTracker.current() )
+ {
+ if ( localesTracker.wasAdded( lang ) )
+ continue;
+ for ( ; lang; lang = lang.fallback() )
+ { localeIds.current().insert( IdString(lang) ); }
+ }
+
+ // Add added locales+fallback except they are already in current
+ for ( Locale lang: localesTracker.added() )
+ {
+ for ( ; lang && localeIds.current().insert( IdString(lang) ).second; lang = lang.fallback() )
+ { localeIds.added().insert( IdString(lang) ); }
+ }
+
+ // Add removed locales+fallback except they are still in current
+ for ( Locale lang: localesTracker.removed() )
+ {
+ for ( ; lang && ! localeIds.current().count( IdString(lang) ); lang = lang.fallback() )
+ { localeIds.removed().insert( IdString(lang) ); }
+ }
+
+ // Assert that TrackedLocaleIds::current is not empty.
+ // If, so fill in LanguageCode::enCode as last resort.
+ if ( localeIds.current().empty() )
+ { localeIds.current().insert( IdString(Locale::enCode) ); }
+ }
+ return *_trackedLocaleIdsPtr;
+ }
+
+
+ static void _getLocaleDeps( const Capability & cap_r, LocaleSet & store_r )
{
// Collect locales from any 'namespace:language(lang)' dependency
CapDetail detail( cap_r );
case CapDetail::CAP_NAMESPACE:
if ( detail.lhs().id() == NAMESPACE_LANGUAGE )
{
- store_r.insert( detail.rhs().id() );
+ store_r.insert( Locale( IdString(detail.rhs().id()) ) );
}
break;
{
if ( !_availableLocalesPtr )
{
- // Collect any 'namespace:language(ja)' dependencies
- std::tr1::unordered_set<sat::detail::IdType> tmp;
- Pool pool( Pool::instance() );
- for_( it, pool.solvablesBegin(), pool.solvablesEnd() )
- {
- Capabilities cap( it->supplements() );
- for_( cit, cap.begin(), cap.end() )
- {
- _getLocaleDeps( *cit, tmp );
+ _availableLocalesPtr.reset( new LocaleSet );
+ LocaleSet & localeSet( *_availableLocalesPtr );
+
+ for ( const Solvable & pi : Pool::instance().solvables() )
+ {
+ for ( const Capability & cap : pi.supplements() )
+ {
+ _getLocaleDeps( cap, localeSet );
}
- }
-#warning immediately build LocaleSet as soon as Loale is an Id based type
- _availableLocalesPtr.reset( new LocaleSet(tmp.size()) );
- for_( it, tmp.begin(), tmp.end() )
- {
- _availableLocalesPtr->insert( Locale( IdString(*it) ) );
- }
+ }
}
return *_availableLocalesPtr;
}
+ ///////////////////////////////////////////////////////////////////
+
void PoolImpl::multiversionListInit() const
{
_multiversionListPtr.reset( new MultiversionList );
MultiversionList & multiversionList( *_multiversionListPtr );
+
+ MultiversionList::size_type size = 0;
+ for ( const std::string & spec : ZConfig::instance().multiversionSpec() )
+ {
+ static const std::string prefix( "provides:" );
+ bool provides = str::hasPrefix( spec, prefix );
- const std::set<std::string> & multiversionSpec( ZConfig::instance().multiversionSpec() );
- for_( it, multiversionSpec.begin(), multiversionSpec.end() )
- {
- static const std::string prefix( "provides:" );
- if ( str::hasPrefix( *it, prefix ) )
- {
- WhatProvides provides( Capability( it->c_str() + prefix.size() ) );
- if ( provides.empty() )
- {
- MIL << "Multiversion install not provided (" << *it << ")" << endl;
- }
- else
- {
- for_( pit, provides.begin(), provides.end() )
- {
- if ( multiversionList.insert( pit->ident() ).second )
- MIL << "Multiversion install " << pit->ident() << " (" << *it << ")" << endl;
- }
- }
- }
- else
- {
- MIL << "Multiversion install " << *it << endl;
- multiversionList.insert( IdString( *it ) );
- }
+ for ( Solvable solv : WhatProvides( Capability( provides ? spec.c_str() + prefix.size() : spec.c_str() ) ) )
+ {
+ if ( provides || solv.ident() == spec )
+ multiversionList.insert( solv );
+ }
+
+ MultiversionList::size_type nsize = multiversionList.size();
+ MIL << "Multiversion install " << spec << ": " << (nsize-size) << " matches" << endl;
+ size = nsize;
}
}
- void PoolImpl::onSystemByUserListInit() const
- {
- _onSystemByUserListPtr.reset( new OnSystemByUserList );
- OnSystemByUserList & onSystemByUserList( *_onSystemByUserListPtr );
+ void PoolImpl::multiversionSpecChanged()
+ { _multiversionListPtr.reset(); }
- Pathname root( ZConfig::instance().systemRoot() );
- if ( root.empty() )
- {
- MIL << "Target not initialized." << endl;
- return;
- }
- PathInfo pi( root / ZConfig::instance().historyLogFile() );
- MIL << "onSystemByUserList from history: " << pi << endl;
- if ( ! pi.isFile() )
- return;
-
- // go and parse it: 'who' must constain an '@', then it was installed by user request.
- // 2009-09-29 07:25:19|install|lirc-remotes|0.8.5-3.2|x86_64|root@opensuse|InstallationImage|a204211eb0...
- std::ifstream infile( pi.path().c_str() );
- for( iostr::EachLine in( infile ); in; in.next() )
- {
- const char * ch( (*in).c_str() );
- // start with year
- if ( *ch < '1' || '9' < *ch )
- continue;
- const char * sep1 = ::strchr( ch, '|' ); // | after date
- if ( !sep1 )
- continue;
- ++sep1;
- // if logs an install or delete
- bool installs = true;
- if ( ::strncmp( sep1, "install|", 8 ) )
- {
- if ( ::strncmp( sep1, "remove |", 8 ) )
- continue; // no install and no remove
- else
- installs = false; // remove
- }
- sep1 += 8; // | after what
- // get the package name
- const char * sep2 = ::strchr( sep1, '|' ); // | after name
- if ( !sep2 || sep1 == sep2 )
- continue;
- (*in)[sep2-ch] = '\0';
- IdString pkg( sep1 );
- // we're done, if a delete
- if ( !installs )
- {
- onSystemByUserList.erase( pkg );
- continue;
- }
- // now guess whether user installed or not (3rd next field contains 'user@host')
- if ( (sep1 = ::strchr( sep2+1, '|' )) // | after version
- && (sep1 = ::strchr( sep1+1, '|' )) // | after arch
- && (sep2 = ::strchr( sep1+1, '|' )) ) // | after who
- {
- (*in)[sep2-ch] = '\0';
- if ( ::strchr( sep1+1, '@' ) )
- {
- // by user
- onSystemByUserList.insert( pkg );
- continue;
- }
- }
- }
- MIL << "onSystemByUserList found: " << onSystemByUserList.size() << endl;
+ const PoolImpl::MultiversionList & PoolImpl::multiversionList() const
+ {
+ if ( ! _multiversionListPtr )
+ multiversionListInit();
+ return *_multiversionListPtr;
}
+ bool PoolImpl::isMultiversion( const Solvable & solv_r ) const
+ { return multiversionList().contains( solv_r ); }
+
+ ///////////////////////////////////////////////////////////////////
+
const std::set<std::string> & PoolImpl::requiredFilesystems() const
{
if ( ! _requiredFilesystemsPtr )