#
SET(LIBZYPP_MAJOR "17")
SET(LIBZYPP_COMPATMINOR "12")
-SET(LIBZYPP_MINOR "16")
+SET(LIBZYPP_MINOR "17")
SET(LIBZYPP_PATCH "0")
#
-# LAST RELEASED: 17.16.0 (12)
+# LAST RELEASED: 17.17.0 (12)
# (The number in parenthesis is LIBZYPP_COMPATMINOR)
#=======
BuildRequires: pkg-config
%endif
-BuildRequires: libsolv-devel >= 0.7.7
+BuildRequires: libsolv-devel >= 0.7.8
%if 0%{?suse_version} >= 1100
BuildRequires: libsolv-tools
%requires_eq libsolv-tools
-------------------------------------------------------------------
+Thu Nov 28 18:20:04 CET 2019 - ma@suse.de
+
+- Introduce PurgeKernels class (bsc#1155198)
+ Adds libzypp API to mark all obsolete kernels according to the
+ existing purge-kernel script rules.
+- Add solver jobs for retracted packages and ptfs.
+ Support for ptf packages and retract ed patches.
+- Do not enforce 'en' being in RequestedLocales (bsc#1155678)
+ If the user decides to have a system without explicit language
+ support he may do so.
+- Pass correct posttrans script argument (fixes #190)
+- BuildRequires: libsolv-devel >= 0.7.8.
+- version 17.17.0 (12)
+
+-------------------------------------------------------------------
Tue Oct 29 14:54:51 CET 2019 - ma@suse.de
- Expose new libsolv API via C++ counterparts
*/
class TestSetup
{
- public:
- typedef TestSetupOptions Options;
+public:
+ typedef TestSetupOptions Options;
- public:
- TestSetup( const Arch & sysarch_r = Arch_empty, const Options & options_r = Options() )
- { _ctor( Pathname(), sysarch_r, options_r ); }
+public:
+ struct InitLaterType {};
+ static constexpr InitLaterType initLater = InitLaterType();
- TestSetup( const Pathname & rootdir_r, const Arch & sysarch_r = Arch_empty, const Options & options_r = Options() )
- { _ctor( rootdir_r, sysarch_r, options_r ); }
+ TestSetup( InitLaterType )
+ {}
- TestSetup( const Pathname & rootdir_r, const Options & options_r )
- { _ctor( rootdir_r, Arch_empty, options_r ); }
+ TestSetup( const Arch & sysarch_r = Arch_empty, const Options & options_r = Options() )
+ : _pimpl { new Impl( Pathname(), sysarch_r, options_r ) }
+ {}
- ~TestSetup()
- {
- USR << (_tmprootdir.path() == _rootdir ? "DELETE" : "KEEP") << " TESTSETUP below " << _rootdir << endl;
- ZConfig::instance().setRepoManagerRoot( Pathname() );
- }
+ TestSetup( const Pathname & rootdir_r, const Arch & sysarch_r = Arch_empty, const Options & options_r = Options() )
+ : _pimpl { new Impl( rootdir_r, sysarch_r, options_r ) }
+ {}
- public:
- /** Whether directory \a path_r contains a solver testcase. */
- static bool isTestcase( const Pathname & path_r )
- {
- return filesystem::PathInfo( path_r / "solver-test.xml" ).isFile();
- }
+ TestSetup( const Pathname & rootdir_r, const Options & options_r )
+ : _pimpl { new Impl( rootdir_r, Arch_empty, options_r ) }
+ {}
- /** Whether directory \a path_r contains a testsetup. */
- static bool isTestSetup( const Pathname & path_r )
- {
- return filesystem::PathInfo( path_r / "repos.d" ).isDir() && filesystem::PathInfo( path_r / "raw" ).isDir();
- }
+ void reset()
+ { _pimpl.reset(); }
- public:
- const Pathname & root() const { return _rootdir; }
-
- Target & target() { if ( ! getZYpp()->getTarget() ) getZYpp()->initializeTarget( _rootdir ); return *getZYpp()->getTarget(); }
- RepoManager repomanager() { return RepoManager( RepoManagerOptions::makeTestSetup( _rootdir ) ); }
- ResPool pool() { return ResPool::instance(); }
- ResPoolProxy poolProxy() { return pool().proxy(); }
- sat::Pool satpool() { return sat::Pool::instance(); }
- Resolver & resolver() { return *getZYpp()->resolver(); }
-
- public:
- /** Load target repo. */
- void loadTarget()
- { target().load(); }
- /** Fake @System repo from url. */
- void loadTargetRepo( const Url & url_r )
- { loadRepo( url_r, sat::Pool::systemRepoAlias() ); }
- /** Fake @System repo from Path. */
- void loadTargetRepo( const Pathname & path_r )
- { loadRepo( path_r, sat::Pool::systemRepoAlias() ); }
- /** Fake @System repo from helix repo. */
- void loadTargetHelix( const Pathname & path_r )
- { loadHelix( path_r, sat::Pool::systemRepoAlias() ); }
-
- public:
- /** Directly load repoinfo to pool. */
- void loadRepo( RepoInfo nrepo )
- {
- RepoManager rmanager( repomanager() );
- if ( rmanager.hasRepo( nrepo ) )
- nrepo.setAlias( RepoManager::makeStupidAlias( nrepo.url() ) );
- rmanager.addRepository( nrepo );
- rmanager.buildCache( nrepo );
- rmanager.loadFromCache( nrepo );
- }
- /** Directly load repo from url to pool. */
- void loadRepo( const Url & url_r, const std::string & alias_r = std::string() )
- {
- RepoInfo nrepo;
- nrepo.setAlias( alias_r.empty() ? url_r.getHost()+":"+Pathname::basename(url_r.getPathName()) : alias_r );
- nrepo.addBaseUrl( url_r );
- if ( ! _options.testFlag( TSO_REPO_DEFAULT_GPG ) )
- nrepo.setGpgCheck( false );
- loadRepo( nrepo );
- }
- /** Directly load repo from metadata(dir) or solvfile(file) to pool.
+public:
+ /** Whether directory \a path_r contains a solver testcase. */
+ static bool isTestcase( const Pathname & path_r )
+ {
+ return filesystem::PathInfo( path_r / "solver-test.xml" ).isFile();
+ }
+
+ /** Whether directory \a path_r contains a testsetup. */
+ static bool isTestSetup( const Pathname & path_r )
+ {
+ return filesystem::PathInfo( path_r / "repos.d" ).isDir() && filesystem::PathInfo( path_r / "raw" ).isDir();
+ }
+
+public:
+ const Pathname & root() const { return _pimpl->_rootdir; }
+
+ Target & target() { if ( ! getZYpp()->getTarget() ) getZYpp()->initializeTarget( _pimpl->_rootdir ); return *getZYpp()->getTarget(); }
+ RepoManager repomanager() { return RepoManager( RepoManagerOptions::makeTestSetup( _pimpl->_rootdir ) ); }
+ ResPool pool() { return ResPool::instance(); }
+ ResPoolProxy poolProxy() { return pool().proxy(); }
+ sat::Pool satpool() { return sat::Pool::instance(); }
+ Resolver & resolver() { return *getZYpp()->resolver(); }
+
+public:
+ /** Load target repo. */
+ void loadTarget()
+ { target().load(); }
+ /** Fake @System repo from url. */
+ void loadTargetRepo( const Url & url_r )
+ { loadRepo( url_r, sat::Pool::systemRepoAlias() ); }
+ /** Fake @System repo from Path. */
+ void loadTargetRepo( const Pathname & path_r )
+ { loadRepo( path_r, sat::Pool::systemRepoAlias() ); }
+ /** Fake @System repo from helix repo. */
+ void loadTargetHelix( const Pathname & path_r )
+ { loadHelix( path_r, sat::Pool::systemRepoAlias() ); }
+
+public:
+ /** Directly load repoinfo to pool. */
+ void loadRepo( RepoInfo nrepo )
+ {
+ RepoManager rmanager( repomanager() );
+ if ( rmanager.hasRepo( nrepo ) )
+ nrepo.setAlias( RepoManager::makeStupidAlias( nrepo.url() ) );
+ rmanager.addRepository( nrepo );
+ rmanager.buildCache( nrepo );
+ rmanager.loadFromCache( nrepo );
+ }
+ /** Directly load repo from url to pool. */
+ void loadRepo( const Url & url_r, const std::string & alias_r = std::string() )
+ {
+ RepoInfo nrepo;
+ nrepo.setAlias( alias_r.empty() ? url_r.getHost()+":"+Pathname::basename(url_r.getPathName()) : alias_r );
+ nrepo.addBaseUrl( url_r );
+ if ( ! _pimpl->_options.testFlag( TSO_REPO_DEFAULT_GPG ) )
+ nrepo.setGpgCheck( false );
+ loadRepo( nrepo );
+ }
+ /** Directly load repo from metadata(dir) or solvfile(file) to pool.
* An empty alias is guessed.
*/
- void loadRepo( const Pathname & path_r, const std::string & alias_r = std::string() )
+ void loadRepo( const Pathname & path_r, const std::string & alias_r = std::string() )
+ {
+ if ( filesystem::PathInfo( path_r ).isDir() )
{
- if ( filesystem::PathInfo( path_r ).isDir() )
- {
- loadRepo( path_r.asUrl(), alias_r );
- return;
- }
- // .solv file is loaded directly using a faked RepoInfo
- RepoInfo nrepo;
- nrepo.setAlias( alias_r.empty() ? path_r.basename() : alias_r );
- satpool().addRepoSolv( path_r, nrepo );
+ loadRepo( path_r.asUrl(), alias_r );
+ return;
}
- /** Directly load repo from some location (url or absolute(!)path).
+ // .solv file is loaded directly using a faked RepoInfo
+ RepoInfo nrepo;
+ nrepo.setAlias( alias_r.empty() ? path_r.basename() : alias_r );
+ satpool().addRepoSolv( path_r, nrepo );
+ }
+ /** Directly load repo from some location (url or absolute(!)path).
* An empty alias is guessed.
*/
- void loadRepo( const std::string & loc_r, const std::string & alias_r = std::string() )
+ void loadRepo( const std::string & loc_r, const std::string & alias_r = std::string() )
+ {
+ if ( *loc_r.c_str() == '/' )
{
- if ( *loc_r.c_str() == '/' )
- {
- loadRepo( Pathname( loc_r ), alias_r );
- }
- else
- {
- loadRepo( Url( loc_r ), alias_r );
- }
+ loadRepo( Pathname( loc_r ), alias_r );
+ }
+ else
+ {
+ loadRepo( Url( loc_r ), alias_r );
}
- /** Directly load repo from some location (url or absolute(!)path).
+ }
+ /** Directly load repo from some location (url or absolute(!)path).
* An empty alias is guessed.
*/
- void loadRepo( const char * loc_r, const std::string & alias_r = std::string() )
- { loadRepo( std::string( loc_r ? loc_r : "" ), alias_r ); }
-
- private:
- // repo data from solver-test.xml
- struct RepoD {
- DefaultIntegral<unsigned,0> priority;
- std::string alias;
- Url url;
- };
-
- public:
- /** Directly load a helix repo from some testcase.
+ void loadRepo( const char * loc_r, const std::string & alias_r = std::string() )
+ { loadRepo( std::string( loc_r ? loc_r : "" ), alias_r ); }
+
+private:
+ // repo data from solver-test.xml
+ struct RepoD {
+ DefaultIntegral<unsigned,0> priority;
+ std::string alias;
+ Url url;
+ };
+
+public:
+ /** Directly load a helix repo from some testcase.
* An empty alias is guessed.
*/
- void loadHelix( const Pathname & path_r, const std::string & alias_r = std::string() )
+ void loadHelix( const Pathname & path_r, const std::string & alias_r = std::string() )
+ {
+ // .solv file is loaded directly using a faked RepoInfo
+ RepoInfo nrepo;
+ nrepo.setAlias( alias_r.empty() ? path_r.basename() : alias_r );
+ satpool().addRepoHelix( path_r, nrepo );
+ }
+
+ // Load repos included in a solver testcase.
+ void loadTestcaseRepos( const Pathname & path_r )
+ {
+ filesystem::PathInfo pi( path_r / "solver-test.xml" );
+ if ( ! pi.isFile() )
{
- // .solv file is loaded directly using a faked RepoInfo
- RepoInfo nrepo;
- nrepo.setAlias( alias_r.empty() ? path_r.basename() : alias_r );
- satpool().addRepoHelix( path_r, nrepo );
+ ERR << "No testcase in " << filesystem::PathInfo( path_r ) << endl;
+ return;
}
-
- // Load repos included in a solver testcase.
- void loadTestcaseRepos( const Pathname & path_r )
+ // dumb parse
+ InputStream infile( pi.path() );
+ Arch sysarch( Arch_empty );
+ Url guessedUrl;
+ typedef std::map<std::string,RepoD> RepoI;
+ RepoI repoi;
+ for( iostr::EachLine in( infile ); in; in.next() )
{
- filesystem::PathInfo pi( path_r / "solver-test.xml" );
- if ( ! pi.isFile() )
+ if ( str::hasPrefix( *in, "\t<channel" ) )
{
- ERR << "No testcase in " << filesystem::PathInfo( path_r ) << endl;
- return;
+ RepoD & repod( repoi[getXmlNodeVal( *in, "file" )] );
+
+ repod.alias = getXmlNodeVal( *in, "name" );
+ repod.priority = str::strtonum<unsigned>( getXmlNodeVal( *in, "priority" ) );
+ repod.url = guessedUrl;
+ guessedUrl = Url();
}
- // dumb parse
- InputStream infile( pi.path() );
- Arch sysarch( Arch_empty );
- Url guessedUrl;
- typedef std::map<std::string,RepoD> RepoI;
- RepoI repoi;
- for( iostr::EachLine in( infile ); in; in.next() )
+ else if ( str::hasPrefix( *in, "\t- url " ) )
{
- if ( str::hasPrefix( *in, "\t<channel" ) )
- {
- RepoD & repod( repoi[getXmlNodeVal( *in, "file" )] );
-
- repod.alias = getXmlNodeVal( *in, "name" );
- repod.priority = str::strtonum<unsigned>( getXmlNodeVal( *in, "priority" ) );
- repod.url = guessedUrl;
- guessedUrl = Url();
- }
- else if ( str::hasPrefix( *in, "\t- url " ) )
- {
- std::string::size_type pos = in->find( ": " );
- if ( pos != std::string::npos )
- {
- guessedUrl = Url( in->substr( pos+2 ) );
- }
- }
- else if ( str::hasPrefix( *in, "\t<locale" ) )
- {
- satpool().addRequestedLocale( Locale( getXmlNodeVal( *in, "name" ) ) );
- }
- else if ( sysarch.empty() && str::hasPrefix( *in, "<setup" ) )
+ std::string::size_type pos = in->find( ": " );
+ if ( pos != std::string::npos )
{
- sysarch = Arch( getXmlNodeVal( *in, "arch" ) );
- if ( ! sysarch.empty() )
- ZConfig::instance().setSystemArchitecture( sysarch );
+ guessedUrl = Url( in->substr( pos+2 ) );
}
}
+ else if ( str::hasPrefix( *in, "\t<locale" ) )
+ {
+ satpool().addRequestedLocale( Locale( getXmlNodeVal( *in, "name" ) ) );
+ }
+ else if ( sysarch.empty() && str::hasPrefix( *in, "<setup" ) )
+ {
+ sysarch = Arch( getXmlNodeVal( *in, "arch" ) );
+ if ( ! sysarch.empty() )
+ ZConfig::instance().setSystemArchitecture( sysarch );
+ }
+ }
- //
- filesystem::Glob files( path_r/"*{.xml,.xml.gz}", filesystem::Glob::kBrace );
- for_( it, files.begin(), files.end() )
+ //
+ filesystem::Glob files( path_r/"*{.xml,.xml.gz}", filesystem::Glob::kBrace );
+ for_( it, files.begin(), files.end() )
+ {
+ std::string basename( Pathname::basename( *it ) );
+ if ( str::hasPrefix( basename, "solver-test.xml" ) )
+ continue; // master index currently unevaluated
+ if ( str::hasPrefix( basename, "solver-system.xml" ) )
+ loadTargetHelix( *it );
+ else
{
- std::string basename( Pathname::basename( *it ) );
- if ( str::hasPrefix( basename, "solver-test.xml" ) )
- continue; // master index currently unevaluated
- if ( str::hasPrefix( basename, "solver-system.xml" ) )
- loadTargetHelix( *it );
- else
- {
- const RepoD & repod( repoi[basename] );
+ const RepoD & repod( repoi[basename] );
- RepoInfo nrepo;
- nrepo.setAlias( repod.alias.empty() ? basename : repod.alias );
- nrepo.setPriority( repod.priority );
- nrepo.setBaseUrl( repod.url );
- satpool().addRepoHelix( *it, nrepo );
- }
+ RepoInfo nrepo;
+ nrepo.setAlias( repod.alias.empty() ? basename : repod.alias );
+ nrepo.setPriority( repod.priority );
+ nrepo.setBaseUrl( repod.url );
+ satpool().addRepoHelix( *it, nrepo );
}
-
- poolProxy(); // prepare
}
- public:
- /** Load all enabled repos in repos.d to pool. */
- void loadRepos()
+ poolProxy(); // prepare
+ }
+
+public:
+ /** Load all enabled repos in repos.d to pool. */
+ void loadRepos()
+ {
+ RepoManager repoManager( repomanager() );
+ RepoInfoList repos = repoManager.knownRepositories();
+ for ( RepoInfoList::iterator it = repos.begin(); it != repos.end(); ++it )
{
- RepoManager repoManager( repomanager() );
- RepoInfoList repos = repoManager.knownRepositories();
- for ( RepoInfoList::iterator it = repos.begin(); it != repos.end(); ++it )
- {
- RepoInfo & nrepo( *it );
- USR << nrepo << endl;
+ RepoInfo & nrepo( *it );
+ USR << nrepo << endl;
- if ( ! nrepo.enabled() )
- continue;
+ if ( ! nrepo.enabled() )
+ continue;
- if ( ! repoManager.isCached( nrepo ) || nrepo.type() == repo::RepoType::RPMPLAINDIR )
+ if ( ! repoManager.isCached( nrepo ) || nrepo.type() == repo::RepoType::RPMPLAINDIR )
+ {
+ if ( repoManager.isCached( nrepo ) )
{
- if ( repoManager.isCached( nrepo ) )
- {
- USR << "cleanCache" << endl;
- repoManager.cleanCache( nrepo );
- }
- //USR << "refreshMetadata" << endl;
- //repoManager.refreshMetadata( nrepo );
- USR << "buildCache" << endl;
- repoManager.buildCache( nrepo );
+ USR << "cleanCache" << endl;
+ repoManager.cleanCache( nrepo );
}
- USR << "Create from cache" << endl;
- repoManager.loadFromCache( nrepo );
+ //USR << "refreshMetadata" << endl;
+ //repoManager.refreshMetadata( nrepo );
+ USR << "buildCache" << endl;
+ repoManager.buildCache( nrepo );
}
+ USR << "Create from cache" << endl;
+ repoManager.loadFromCache( nrepo );
}
+ }
- public:
- /** Detect and load the system located at \a sysRoot.
+public:
+ /** Detect and load the system located at \a sysRoot.
*
* \a sysRoot needs to be a directory containing either a SolverTestcase,
* a TestSetup system or a real system. The provided repostitories are
* loaded into the pool (without refresh).
*/
- static void LoadSystemAt( const Pathname & sysRoot, const Arch & _testSetupArch_r = Arch_x86_64 )
+ static void LoadSystemAt( const Pathname & sysRoot, const Arch & _testSetupArch_r = Arch_x86_64 )
+ {
+ if ( ! PathInfo( sysRoot ).isDir() )
+ ZYPP_THROW( Exception("sysRoot argument needs to be a directory") );
+
+ if ( TestSetup::isTestcase( sysRoot ) )
+ {
+ USR << str::form( "*** Load Testcase from '%s'", sysRoot.c_str() ) << endl;
+ TestSetup test;
+ test.loadTestcaseRepos( sysRoot );
+ }
+ else if ( TestSetup::isTestSetup( sysRoot ) )
{
- if ( ! PathInfo( sysRoot ).isDir() )
- ZYPP_THROW( Exception("sysRoot argument needs to be a directory") );
+ USR << str::form( "*** Load TestSetup from '%s'", sysRoot.c_str() ) << endl;
+
+ TestSetup test( sysRoot, _testSetupArch_r );
+ test.loadRepos();
- if ( TestSetup::isTestcase( sysRoot ) )
+ Pathname solvCachePath( RepoManagerOptions::makeTestSetup( test.root() ).repoSolvCachePath );
+ Pathname fakeTargetSolv( solvCachePath / sat::Pool::systemRepoAlias() / "solv" );
+ if ( PathInfo( fakeTargetSolv ).isFile() )
{
- USR << str::form( "*** Load Testcase from '%s'", sysRoot.c_str() ) << endl;
- TestSetup test;
- test.loadTestcaseRepos( sysRoot );
+ USR << str::form( "*** Fake TestSetup Target from '%s'", fakeTargetSolv.c_str() ) << endl;
+ test.target();
+ test.loadTargetRepo( fakeTargetSolv );
}
- else if ( TestSetup::isTestSetup( sysRoot ) )
+ }
+ else
+ {
+ sat::Pool satpool( sat::Pool::instance() );
+ // a system
+ USR << str::form( "*** Load system at '%s'", sysRoot.c_str() ) << endl;
+ if ( 1 )
{
- USR << str::form( "*** Load TestSetup from '%s'", sysRoot.c_str() ) << endl;
-
- TestSetup test( sysRoot, _testSetupArch_r );
- test.loadRepos();
-
- Pathname solvCachePath( RepoManagerOptions::makeTestSetup( test.root() ).repoSolvCachePath );
- Pathname fakeTargetSolv( solvCachePath / sat::Pool::systemRepoAlias() / "solv" );
- if ( PathInfo( fakeTargetSolv ).isFile() )
- {
- USR << str::form( "*** Fake TestSetup Target from '%s'", fakeTargetSolv.c_str() ) << endl;
- test.target();
- test.loadTargetRepo( fakeTargetSolv );
- }
+ USR << "*** load target '" << Repository::systemRepoAlias() << "'\t" << endl;
+ getZYpp()->initializeTarget( sysRoot );
+ getZYpp()->target()->load();
+ USR << satpool.systemRepo() << endl;
}
- else
+
+ if ( 1 )
{
- sat::Pool satpool( sat::Pool::instance() );
- // a system
- USR << str::form( "*** Load system at '%s'", sysRoot.c_str() ) << endl;
- if ( 1 )
+ RepoManager repoManager( sysRoot );
+ RepoInfoList repos = repoManager.knownRepositories();
+ for_( it, repos.begin(), repos.end() )
{
- USR << "*** load target '" << Repository::systemRepoAlias() << "'\t" << endl;
- getZYpp()->initializeTarget( sysRoot );
- getZYpp()->target()->load();
- USR << satpool.systemRepo() << endl;
- }
+ RepoInfo & nrepo( *it );
- if ( 1 )
- {
- RepoManager repoManager( sysRoot );
- RepoInfoList repos = repoManager.knownRepositories();
- for_( it, repos.begin(), repos.end() )
+ if ( ! nrepo.enabled() )
+ continue;
+
+ if ( ! repoManager.isCached( nrepo ) )
+ {
+ USR << str::form( "*** omit uncached repo '%s' (do 'zypper refresh')", nrepo.name().c_str() ) << endl;
+ continue;
+ }
+
+ USR << str::form( "*** load repo '%s'\t", nrepo.name().c_str() ) << flush;
+ try
+ {
+ repoManager.loadFromCache( nrepo );
+ USR << satpool.reposFind( nrepo.alias() ) << endl;
+ }
+ catch ( const Exception & exp )
{
- RepoInfo & nrepo( *it );
-
- if ( ! nrepo.enabled() )
- continue;
-
- if ( ! repoManager.isCached( nrepo ) )
- {
- USR << str::form( "*** omit uncached repo '%s' (do 'zypper refresh')", nrepo.name().c_str() ) << endl;
- continue;
- }
-
- USR << str::form( "*** load repo '%s'\t", nrepo.name().c_str() ) << flush;
- try
- {
- repoManager.loadFromCache( nrepo );
- USR << satpool.reposFind( nrepo.alias() ) << endl;
- }
- catch ( const Exception & exp )
- {
- USR << exp.asString() + "\n" + exp.historyAsString() << endl;
- USR << str::form( "*** omit broken repo '%s' (do 'zypper refresh')", nrepo.name().c_str() ) << endl;
- continue;
- }
+ USR << exp.asString() + "\n" + exp.historyAsString() << endl;
+ USR << str::form( "*** omit broken repo '%s' (do 'zypper refresh')", nrepo.name().c_str() ) << endl;
+ continue;
}
}
}
}
+ }
- private:
- void _ctor( const Pathname & rootdir_r, const Arch & sysarch_r, const Options & options_r )
+private:
+ struct Impl
+ {
+ Impl( const Pathname & rootdir_r, const Arch & sysarch_r, const Options & options_r )
{
_options = options_r;
ZConfig::instance().setSystemArchitecture( sysarch_r );
USR << "CREATED TESTSETUP below " << _rootdir << endl;
}
- private:
+
+ ~Impl()
+ {
+ USR << (_tmprootdir.path() == _rootdir ? "DELETE" : "KEEP") << " TESTSETUP below " << _rootdir << endl;
+ ZConfig::instance().setRepoManagerRoot( Pathname() );
+ getZYpp()->finishTarget();
+ sat::Pool::instance().reposEraseAll();
+ }
+
filesystem::TmpDir _tmprootdir;
Pathname _rootdir;
Options _options;
+ };
+
+ std::unique_ptr<Impl> _pimpl; // maybe worth creating RW_pointer traits for it
};
#include "TestSetup.h"
#include <zypp/parser/ProductFileReader.h>
-//static TestSetup test( Arch_x86_64 );
+//TestSetup test( TestSetup::initLater );
+//struct TestInit {
+// TestInit() {
+// test = TestSetup( Arch_x86_64 );
+// }
+// ~TestInit() { test.reset(); }
+//};
+//BOOST_GLOBAL_FIXTURE( TestInit );
// Must be the first test!
BOOST_AUTO_TEST_CASE(basic)
using std::cout;
using std::endl;
-TestSetup test( Arch_x86_64 );
+static TestSetup test( TestSetup::initLater );
+struct TestInit {
+ TestInit() {
+ test = TestSetup( Arch_x86_64 );
+ }
+ ~TestInit() { test.reset(); }
+};
+BOOST_GLOBAL_FIXTURE( TestInit );
+
const Pathname DATADIR( TESTS_SRC_DIR "/repo/RepoLicense" );
///////////////////////////////////////////////////////////////////
#define COUT if ( TC_VERBOSE ) std::cout
#define TAG COUT << "*** " << __PRETTY_FUNCTION__ << endl
-TestSetup test( Arch_x86_64, TSO_REPO_DEFAULT_GPG );
+static TestSetup test( TestSetup::initLater );
+struct TestInit {
+ TestInit() {
+ test = TestSetup( Arch_x86_64, TSO_REPO_DEFAULT_GPG );
+ }
+ ~TestInit() { test.reset(); }
+};
+BOOST_GLOBAL_FIXTURE( TestInit );
const Pathname DATADIR( TESTS_SRC_DIR "/repo/RepoSigcheck" );
///////////////////////////////////////////////////////////////////
#include <zypp/base/StrMatcher.h>
#include <zypp/ResObjects.h>
-static TestSetup test( Arch_x86_64 );
+static TestSetup test( TestSetup::initLater );
+struct TestInit {
+ TestInit() {
+ test = TestSetup( Arch_x86_64 );
+ }
+ ~TestInit() { test.reset(); }
+};
+BOOST_GLOBAL_FIXTURE( TestInit );
// Must be the first test!
BOOST_AUTO_TEST_CASE(bnc_435838)
#include <zypp/Repository.h>
#include <zypp/sat/Pool.h>
-static TestSetup test( Arch_x86_64 );
+static TestSetup test( TestSetup::initLater );
+struct TestInit {
+ TestInit() {
+ test = TestSetup( Arch_x86_64 );
+ }
+ ~TestInit() { test.reset(); }
+};
+BOOST_GLOBAL_FIXTURE( TestInit );
namespace zypp { namespace detail {
/** \relates RepositoryIterator Stream output */
using namespace boost::unit_test;
-BOOST_AUTO_TEST_CASE(test_init)
-{
- TestSetup test( Arch_x86_64 );
- test.loadRepo( TESTS_SRC_DIR "/data/openSUSE-11.1", "opensuse" );
- test.loadRepo( TESTS_SRC_DIR "/data/11.0-update", "update" );
-}
+struct TestInit {
+ TestInit()
+ : _test( Arch_x86_64 ){
+ _test.loadRepo( TESTS_SRC_DIR "/data/openSUSE-11.1", "opensuse" );
+ _test.loadRepo( TESTS_SRC_DIR "/data/11.0-update", "update" );
+ }
+ TestSetup _test;
+};
+BOOST_GLOBAL_FIXTURE( TestInit );
BOOST_AUTO_TEST_CASE(attributes)
{
ProgressData
PtrTypes
PublicKey
+ PurgeKernels
RWPtr
RepoInfo
RepoManager
using namespace std;
using namespace zypp;
-static TestSetup test( Arch_x86_64 );
+static TestSetup test( TestSetup::initLater );
+struct TestInit {
+ TestInit() {
+ test = TestSetup( Arch_x86_64 );
+ }
+ ~TestInit() { test.reset(); }
+};
+BOOST_GLOBAL_FIXTURE( TestInit );
BOOST_AUTO_TEST_CASE(capabilities_test)
{
/////////////////////////////////////////////////////////////////////////////
-static TestSetup test;
+static TestSetup test( TestSetup::initLater );
+struct TestInit {
+ TestInit() {
+ test = TestSetup( Arch_x86_64 );
+ test.loadTestcaseRepos( TESTS_SRC_DIR"/data/TCdup" );
+ dumpRange( USR, test.pool().knownRepositoriesBegin(),
+ test.pool().knownRepositoriesEnd() ) << endl;
+ }
+ ~TestInit() { test.reset(); }
+};
template <class TIterator>
std::ostream & vdumpPoolStats( std::ostream & str, TIterator begin_r, TIterator end_r )
return str << stats;
}
-bool upgrade()
+bool upgrade( )
{
bool rres = false;
{
}
-BOOST_AUTO_TEST_CASE(testcase_init)
+BOOST_GLOBAL_FIXTURE( TestInit );
+
+BOOST_AUTO_TEST_CASE( orphaned )
{
- //zypp::base::LogControl::instance().logToStdErr();
- test.loadTestcaseRepos( TESTS_SRC_DIR"/data/TCdup" );
- dumpRange( USR, test.pool().knownRepositoriesBegin(),
- test.pool().knownRepositoriesEnd() ) << endl;
USR << "pool: " << test.pool() << endl;
- BOOST_REQUIRE( upgrade() );
-}
-/////////////////////////////////////////////////////////////////////////////
+ BOOST_REQUIRE( upgrade( ) );
-BOOST_AUTO_TEST_CASE(orphaned)
-{
ResPoolProxy proxy( test.poolProxy() );
BOOST_CHECK_EQUAL( proxy.lookup( ResKind::package, "glibc" )->status(), ui::S_KeepInstalled );
BOOST_CHECK_EQUAL( proxy.lookup( ResKind::package, "release-package" )->status(), ui::S_AutoUpdate );
BOOST_CHECK_EQUAL( proxy.lookup( ResKind::package, "dropped_required" )->status(), ui::S_KeepInstalled );
BOOST_CHECK_EQUAL( proxy.lookup( ResKind::package, "dropped" )->status(), ui::S_AutoDel );
}
+
using std::endl;
using namespace zypp;
-static TestSetup test;
+static TestSetup test( TestSetup::initLater );
+struct TestInit {
+ TestInit() {
+ test = TestSetup( Arch_x86_64 );
+ }
+ ~TestInit() { test.reset(); }
+};
+BOOST_GLOBAL_FIXTURE( TestInit );
void testcase_init()
{
// Resolvable is still the original one created for a package...
///////////////////////////////////////////////////////////////////
-BOOST_AUTO_TEST_CASE(t_1) { testcase_init(); }
-BOOST_AUTO_TEST_CASE(t_2) { repocheck(); }
-BOOST_AUTO_TEST_CASE(t_4) { testcase_init2(); }
-BOOST_AUTO_TEST_CASE(t_5) { repocheck(); }
+BOOST_AUTO_TEST_CASE(t_1) {
+
+ //will print additional context information on error
+ BOOST_TEST_CONTEXT("First phase") {
+ testcase_init();
+ repocheck();
+ }
+
+ BOOST_TEST_CONTEXT("Second phase") {
+ testcase_init2();
+ repocheck();
+ }
+}
#define BOOST_TEST_MODULE InstanceId
/////////////////////////////////////////////////////////////////////////////
-static TestSetup test( Arch_x86_64 );
-
-BOOST_AUTO_TEST_CASE(pool_query_init)
-{
- // Abuse;) vbox as System repo:
- test.loadTargetRepo( TESTS_SRC_DIR "/data/obs_virtualbox_11_1" );
- test.loadRepo( TESTS_SRC_DIR "/data/openSUSE-11.1", "opensuse" );
- test.loadRepo( TESTS_SRC_DIR "/data/OBS_zypp_svn-11.1", "zyppsvn" );
-}
-
+static TestSetup test( TestSetup::initLater );
+struct TestInit {
+ TestInit() {
+ test = TestSetup( Arch_x86_64 );
+
+ // Abuse;) vbox as System repo:
+ test.loadTargetRepo( TESTS_SRC_DIR "/data/obs_virtualbox_11_1" );
+ test.loadRepo( TESTS_SRC_DIR "/data/openSUSE-11.1", "opensuse" );
+ test.loadRepo( TESTS_SRC_DIR "/data/OBS_zypp_svn-11.1", "zyppsvn" );
+ }
+ ~TestInit() { test.reset(); }
+};
+BOOST_GLOBAL_FIXTURE( TestInit );
/////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(default_constructed)
return false;
}
-BOOST_AUTO_TEST_CASE(pool_query_init)
-{
- TestSetup test( Arch_x86_64 );
- //test.loadTarget(); // initialize and load target
- test.loadRepo( TESTS_SRC_DIR "/data/openSUSE-11.1", "opensuse" );
- test.loadRepo( TESTS_SRC_DIR "/data/OBS_zypp_svn-11.1", "@System" );
-}
-
+static TestSetup test( TestSetup::initLater );
+struct TestInit {
+ TestInit() {
+ test = TestSetup( Arch_x86_64 );
+ //test.loadTarget(); // initialize and load target
+ test.loadRepo( TESTS_SRC_DIR "/data/openSUSE-11.1", "opensuse" );
+ test.loadRepo( TESTS_SRC_DIR "/data/OBS_zypp_svn-11.1", "@System" );
+ }
+ ~TestInit() { test.reset(); }
+};
+BOOST_GLOBAL_FIXTURE( TestInit );
/////////////////////////////////////////////////////////////////////////////
// 0xx basic queries
using std::endl;
using namespace zypp;
-static TestSetup test;
-
-/////////////////////////////////////////////////////////////////////////////
template <class TCont>
std::ostream & nlist( std::ostream & str, const TCont & set_r )
{
return str << endl;
}
-BOOST_AUTO_TEST_CASE(init)
-{
- test.loadTargetHelix( TESTS_SRC_DIR "/zypp/data/PoolQueryCC/rxnames.xml" );
- nlist( cout << "repo ", ResPool::instance() );
-}
+/////////////////////////////////////////////////////////////////////////////
+
+static TestSetup test( TestSetup::initLater );
+struct TestInit {
+ TestInit() {
+ test = TestSetup( Arch_x86_64 );
+
+ test.loadTargetHelix( TESTS_SRC_DIR "/zypp/data/PoolQueryCC/rxnames.xml" );
+ nlist( cout << "repo ", ResPool::instance() );
+ }
+ ~TestInit() { test.reset(); }
+};
+BOOST_GLOBAL_FIXTURE( TestInit );
/////////////////////////////////////////////////////////////////////////////
// Basic issue: Multiple match strings are compiled into a singe regex. The
#define BOOST_TEST_MODULE PoolQuery
/////////////////////////////////////////////////////////////////////////////
-static TestSetup test( Arch_x86_64 );
+static TestSetup test( TestSetup::initLater );
+struct TestInit {
+ TestInit() {
+ test = TestSetup( Arch_x86_64 );
-BOOST_AUTO_TEST_CASE(pool_query_init)
-{
- // Abuse;) vbox as System repo:
- test.loadTargetRepo( TESTS_SRC_DIR "/data/obs_virtualbox_11_1" );
- test.loadRepo( TESTS_SRC_DIR "/data/openSUSE-11.1", "opensuse" );
- test.loadRepo( TESTS_SRC_DIR "/data/OBS_zypp_svn-11.1", "zyppsvn" );
+ // Abuse;) vbox as System repo:
+ test.loadTargetRepo( TESTS_SRC_DIR "/data/obs_virtualbox_11_1" );
+ test.loadRepo( TESTS_SRC_DIR "/data/openSUSE-11.1", "opensuse" );
+ test.loadRepo( TESTS_SRC_DIR "/data/OBS_zypp_svn-11.1", "zyppsvn" );
- dumpRange( USR, test.pool().knownRepositoriesBegin(),
- test.pool().knownRepositoriesEnd() );
- USR << "pool: " << test.pool() << endl;
-}
+ dumpRange( USR, test.pool().knownRepositoriesBegin(),
+ test.pool().knownRepositoriesEnd() );
+ USR << "pool: " << test.pool() << endl;
+ }
+ ~TestInit() { test.reset(); }
+};
+BOOST_GLOBAL_FIXTURE( TestInit );
/////////////////////////////////////////////////////////////////////////////
static std::ofstream devNull;
--- /dev/null
+#include "TestSetup.h"
+#include "zypp/PurgeKernels.h"
+
+#include <boost/test/data/test_case.hpp>
+
+using namespace zypp;
+using namespace boost::unit_test;
+
+namespace boost { namespace test_tools { namespace tt_detail {
+template<>
+struct print_log_value< std::map<std::string, bool> > {
+void operator()( std::ostream& ostr,
+ std::map<std::string, bool> const& set)
+{
+ ostr << "{" << std::endl;
+ for( const auto &elem : set ) ostr << "'" << elem.first << "'," << std::endl;
+ ostr << "}" << std::endl;
+}
+};
+}}}
+
+namespace {
+ std::string makeNVRA( const PoolItem &pck ) {
+ return pck.name() + "-" + pck.edition().asString() + "." + pck.arch().asString();
+ }
+
+ using TestSample = std::tuple<Pathname, std::string, zypp::Arch, std::string, std::map<std::string, bool> >;
+
+ std::vector<TestSample> maketestdata() {
+ return {
+ TestSample {
+ TESTS_SRC_DIR"/zypp/data/PurgeKernels/simple",
+ "1-3-default",
+ Arch("x86_64"),
+ "oldest,running,latest",
+ {
+ { "kernel-default-1-2.x86_64", false },
+ { "kernel-default-devel-1-2.x86_64", false },
+ { "kernel-default-devel-debuginfo-1-2.x86_64", false },
+ { "kernel-devel-1-2.noarch", false },
+ { "kernel-livepatch-default-1-2.x86_64", false },
+ { "kernel-syms-1-2.x86_64", false },
+ { "kernel-default-1-4.x86_64", false },
+ { "kernel-default-devel-1-4.x86_64", false },
+ { "kernel-default-devel-debuginfo-1-4.x86_64", false },
+ { "kernel-devel-1-4.noarch", false },
+ { "kernel-syms-1-4.x86_64", false },
+ }
+ },
+ //test that keeps only the running kernel
+ TestSample {
+ TESTS_SRC_DIR"/zypp/data/PurgeKernels/simple",
+ "1-3-default",
+ Arch("x86_64"),
+ "running",
+ {
+ { "kernel-default-1-1.x86_64", false },
+ { "kernel-default-devel-1-1.x86_64", false },
+ { "kernel-default-devel-debuginfo-1-1.x86_64", false },
+ { "kernel-livepatch-default-1-1.x86_64", false },
+ { "kernel-devel-1-1.noarch", false },
+ { "kernel-syms-1-1.x86_64", false },
+ { "kernel-source-1-1.noarch", false },
+ { "kernel-default-1-2.x86_64", false },
+ { "kernel-default-devel-1-2.x86_64", false },
+ { "kernel-default-devel-debuginfo-1-2.x86_64", false },
+ { "kernel-devel-1-2.noarch", false },
+ { "kernel-livepatch-default-1-2.x86_64", false },
+ { "kernel-syms-1-2.x86_64", false },
+ { "kernel-default-1-4.x86_64", false },
+ { "kernel-default-devel-1-4.x86_64", false },
+ { "kernel-default-devel-debuginfo-1-4.x86_64", false },
+ { "kernel-devel-1-4.noarch", false },
+ { "kernel-syms-1-4.x86_64", false },
+ { "kernel-default-1-5.x86_64", false },
+ { "kernel-default-devel-1-5.x86_64", false },
+ { "kernel-default-devel-debuginfo-1-5.x86_64", false },
+ { "kernel-devel-1-5.noarch", false },
+ { "kernel-syms-1-5.x86_64", false },
+ { "dummy-kmp-default-1-0.x86_64", false },
+ }
+ },
+ TestSample {
+ TESTS_SRC_DIR"/zypp/data/PurgeKernels/simple",
+ "1-3-default",
+ Arch("x86_64"),
+ "oldest+1,running,latest-1",
+ {
+ { "kernel-default-1-1.x86_64", false },
+ { "kernel-livepatch-default-1-1.x86_64", false },
+ { "kernel-default-devel-1-1.x86_64", false },
+ { "kernel-default-devel-debuginfo-1-1.x86_64", false },
+ { "kernel-devel-1-1.noarch", false },
+ { "kernel-syms-1-1.x86_64", false },
+ { "kernel-source-1-1.noarch", false },
+ { "kernel-default-1-5.x86_64", false },
+ { "kernel-default-devel-1-5.x86_64", false },
+ { "kernel-default-devel-debuginfo-1-5.x86_64", false },
+ { "kernel-devel-1-5.noarch", false },
+ { "kernel-syms-1-5.x86_64", false },
+ { "dummy-kmp-default-1-0.x86_64", false },
+ }
+ },
+ TestSample {
+ //kernel-1-1 has a non kernel package depending on it, it should not be removed
+ TESTS_SRC_DIR"/zypp/data/PurgeKernels/withdeps",
+ "1-5-default",
+ Arch("x86_64"),
+ "running",
+ {
+ { "kernel-default-1-2.x86_64", false },
+ { "kernel-default-devel-1-2.x86_64", false },
+ { "kernel-default-devel-debuginfo-1-2.x86_64", false },
+ { "kernel-devel-1-2.noarch", false },
+ { "kernel-livepatch-default-1-2.x86_64", false },
+ { "kernel-syms-1-2.x86_64", false },
+ }
+ },
+ TestSample {
+ //kernel-1-5 provides a symbol for a kmp that has a non kernel package depending on it, it should not be removed
+ TESTS_SRC_DIR"/zypp/data/PurgeKernels/withdeps",
+ "1-1-default",
+ Arch("x86_64"),
+ "running",
+ {
+ { "kernel-default-1-2.x86_64", false },
+ { "kernel-default-devel-1-2.x86_64", false },
+ { "kernel-default-devel-debuginfo-1-2.x86_64", false },
+ { "kernel-devel-1-2.noarch", false },
+ { "kernel-livepatch-default-1-2.x86_64", false },
+ { "kernel-syms-1-2.x86_64", false },
+ }
+ },
+ TestSample {
+ //kernel-1-2 is explicitely in the keep spec, it should not be removed
+ //kernel-1-5 provides a symbol for a kmp that has a non kernel package depending on it, it should not be removed
+ TESTS_SRC_DIR"/zypp/data/PurgeKernels/withdeps",
+ "1-1-default",
+ Arch("x86_64"),
+ "running,1-2",
+ {
+ }
+ },
+ TestSample {
+ //kernel-default-1-1.x86_64 is the running kernel it should not be removed,
+ //in all sets with different arch only the latest should be kept
+ TESTS_SRC_DIR"/zypp/data/PurgeKernels/arch",
+ "1-1-default",
+ Arch("x86_64"),
+ "latest,running",
+ {
+ { "kernel-default-1-1.aarch64", false },
+ { "kernel-default-1-1.i686", false },
+
+ /*
+ { "kernel-default-devel-1-1.x86_64", false },
+ { "kernel-default-devel-debuginfo-1-1.x86_64", false },
+ { "kernel-syms-1-1.x86_64", false },
+ */
+
+ { "kernel-default-1-2.aarch64", false },
+ { "kernel-default-1-2.i686", false },
+ { "kernel-default-1-2.x86_64", false },
+
+ { "kernel-default-devel-1-1.aarch64", false },
+ { "kernel-default-devel-1-1.i686", false },
+ { "kernel-default-devel-1-2.aarch64", false },
+ { "kernel-default-devel-1-2.i686", false },
+ { "kernel-default-devel-1-2.x86_64", false },
+
+ { "kernel-default-devel-debuginfo-1-1.aarch64", false },
+ { "kernel-default-devel-debuginfo-1-1.i686", false },
+ { "kernel-default-devel-debuginfo-1-2.aarch64", false },
+ { "kernel-default-devel-debuginfo-1-2.i686", false },
+ { "kernel-default-devel-debuginfo-1-2.x86_64", false },
+
+ { "kernel-devel-1-2.noarch", false },
+
+ { "kernel-livepatch-default-1-2.aarch64", false },
+ { "kernel-livepatch-default-1-2.i686", false },
+ { "kernel-livepatch-default-1-2.x86_64", false },
+
+ /*
+ Since kernel-syms package requires do not care about architecture, every kernel-syms
+ package for flavour-version will be kept as long as a kernel-flavour-devel package of any arch is installed
+ { "kernel-syms-1-1.aarch64", false },
+ { "kernel-syms-1-1.i686", false },
+ */
+ { "kernel-syms-1-2.aarch64", false },
+ { "kernel-syms-1-2.i686", false },
+ { "kernel-syms-1-2.x86_64", false },
+ }
+ },
+ };
+ }
+}
+
+namespace bdata = boost::unit_test::data;
+
+BOOST_DATA_TEST_CASE(purge_kernels, bdata::make( maketestdata() ), repoPath, uname_r, arch, keepSpec, expectedRems )
+{
+ TestSetup test( Arch_x86_64 );
+ test.loadTestcaseRepos( repoPath );
+
+ auto expectedRemovals = expectedRems;
+
+ PurgeKernels krnls;
+ krnls.setUnameR( uname_r );
+ krnls.setKernelArch( arch );
+ krnls.setKeepSpec( keepSpec );
+ krnls.markObsoleteKernels();
+
+ auto pool = ResPool::instance();
+ BOOST_REQUIRE( pool.resolver().resolvePool() );
+
+ unsigned removeCount = 0;
+ const filter::ByStatus toBeUninstalledFilter( &ResStatus::isToBeUninstalled );
+ for ( auto it = pool.byStatusBegin( toBeUninstalledFilter ); it != pool.byStatusEnd( toBeUninstalledFilter ); it++ ) {
+ removeCount++;
+
+ auto pck = expectedRemovals.find( makeNVRA(*it) );
+ BOOST_REQUIRE_MESSAGE( pck != expectedRemovals.end(), std::string("Unexpected package removed: ") + makeNVRA(*it) );
+
+ pck->second = true;
+ }
+
+ for ( const auto &rem : expectedRemovals ) {
+ if (!rem.second)
+ std::cout << std::string( "Expected package removal did not happen for: ") + rem.first << std::endl;
+ //BOOST_REQUIRE_MESSAGE( rem.second, std::string( "Expected package removal did not happen for: ") + rem.first );
+ }
+
+ BOOST_REQUIRE_EQUAL( expectedRemovals.size(), removeCount );
+}
#include "zypp/pool/PoolStats.h"
#include "zypp/ui/Selectable.h"
-static TestSetup test;
+static TestSetup test( TestSetup::initLater );
struct BAD_TESTCASE {};
PoolItem Apfr; // A: aspell-fr (unwanted locale)
PoolItem Aprec; // A: recommended-pkg (by aspell)
-BOOST_AUTO_TEST_CASE(testcase_init)
-{
- test.loadTestcaseRepos( TESTS_SRC_DIR"/data/TCNamespaceRecommends" );
- Ip = getIPi( "aspell" );
- Ap = getAPi( "aspell" );
- Ipen = getIPi( "aspell-en" );
- Apen = getAPi( "aspell-en" );
- Apde = getAPi( "aspell-de" );
- Apfr = getAPi( "aspell-fr" );
- Aprec = getAPi( "recommended-pkg" );
-}
+struct TestInit {
+ TestInit() {
+ test = TestSetup( );
+
+ test.loadTestcaseRepos( TESTS_SRC_DIR"/data/TCNamespaceRecommends" );
+ Ip = getIPi( "aspell" );
+ Ap = getAPi( "aspell" );
+ Ipen = getIPi( "aspell-en" );
+ Apen = getAPi( "aspell-en" );
+ Apde = getAPi( "aspell-de" );
+ Apfr = getAPi( "aspell-fr" );
+ Aprec = getAPi( "recommended-pkg" );
+ }
+ ~TestInit() { test.reset(); }
+};
+BOOST_GLOBAL_FIXTURE( TestInit );
/////////////////////////////////////////////////////////////////////////////
#include "TestSetup.h"
-static TestSetup test;
#include "zypp/target/rpm/RpmDb.h"
using target::rpm::RpmDb;
#define HAVE_RPMTSSETVFYFLAGS
#endif
+static TestSetup test( TestSetup::initLater );
+struct TestInit {
+ TestInit() {
+ test = TestSetup( );
+ }
+ ~TestInit() { test.reset(); }
+};
+BOOST_GLOBAL_FIXTURE( TestInit );
+
///////////////////////////////////////////////////////////////////
//
// - RpmDb::checkPackage (legacy) and RpmDb::checkPackageSignature are
/////////////////////////////////////////////////////////////////////////////
-static TestSetup test;
+static TestSetup test( TestSetup::initLater );
+struct TestInit {
+ TestInit() {
+ test = TestSetup( );
-BOOST_AUTO_TEST_CASE(testcase_init)
-{
-// zypp::base::LogControl::instance().logToStdErr();
- test.loadTestcaseRepos( TESTS_SRC_DIR"/data/TCSelectable" );
+ // zypp::base::LogControl::instance().logToStdErr();
+ test.loadTestcaseRepos( TESTS_SRC_DIR"/data/TCSelectable" );
+
+ // dumpRange( USR, test.pool().knownRepositoriesBegin(),
+ // test.pool().knownRepositoriesEnd() ) << endl;
+ // USR << "pool: " << test.pool() << endl;
+
+ }
+ ~TestInit() { test.reset(); }
+};
+BOOST_GLOBAL_FIXTURE( TestInit );
-// dumpRange( USR, test.pool().knownRepositoriesBegin(),
-// test.pool().knownRepositoriesEnd() ) << endl;
-// USR << "pool: " << test.pool() << endl;
-}
/////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(candiadate)
--- /dev/null
+<channel><subchannel>
+<package>
+ <name>glibc</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='glibc' op='==' version='1' release='1' />
+ </provides>
+</package>
+
+<package>
+ <name>kernel-firmware</name>
+ <provides>
+ <dep name='kernel-firmware' op='==' version='20190312' release='lp151.2.3.1' />
+ </provides>
+</package>
+
+<package>
+ <name>kernel-macros</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>noarch</arch>
+ <version>1</version><release>0</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-subpackage-macros' />
+ <dep name='kernel-macros' op='==' version='1' release='0' />
+ </provides>
+</package>
+
+<!-- START KERNEL SET -->
+<package>
+ <name>kernel-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-1-1' />
+ <dep name='kernel' op='==' version='1' release='1' />
+ <dep name='kernel-uname-r' op='==' version='1-1' release='default' />
+ </provides>
+ <recommends>
+ <dep name='kernel-firmware' />
+ </recommends>
+</package>
+
+<package>
+ <name>kernel-livepatch-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-livepatch-default-1-1' />
+ </provides>
+ <requires>
+ <dep name='kernel' op='==' version='1' release='1' />
+ </requires>
+</package>
+
+<package>
+ <name>kernel-default-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-devel' op='==' version='1' release='1' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='1' />
+ </requires>
+ <supplements>
+ <dep name='packageand(kernel-default:kernel-devel)' />
+ </supplements>
+</package>
+
+<package>
+ <name>kernel-default-devel-debuginfo</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-default-devel-debuginfo' op='==' version='1' release='1' />
+ </provides>
+</package>
+
+<package>
+ <name>kernel-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>noarch</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-devel' op='==' version='1' release='1' />
+ </provides>
+ <requires>
+ <dep name='kernel-macros' />
+ </requires>
+</package>
+
+<package>
+ <name>kernel-syms</name>
+ <vendor>openSUSE</vendor>
+ <buildtime>1570603549</buildtime>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-syms' op='==' version='1' release='1' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='1' />
+ <dep name='kernel-default-devel' op='==' version='1' release='1' />
+ </requires>
+</package>
+<!-- END KERNEL SET -->
+
+<!-- START KERNEL SET -->
+<package>
+ <name>kernel-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-1-2' />
+ <dep name='kernel' op='==' version='1' release='2' />
+ <dep name='kernel-uname-r' op='==' version='1-2' release='default' />
+ </provides>
+ <recommends>
+ <dep name='kernel-firmware' />
+ </recommends>
+</package>
+
+<package>
+ <name>kernel-livepatch-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-livepatch-default-1-2' />
+ </provides>
+ <requires>
+ <dep name='kernel' op='==' version='1' release='2' />
+ </requires>
+</package>
+
+<package>
+ <name>kernel-default-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-devel' op='==' version='1' release='2' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='2' />
+ </requires>
+ <supplements>
+ <dep name='packageand(kernel-default:kernel-devel)' />
+ </supplements>
+</package>
+
+<package>
+ <name>kernel-default-devel-debuginfo</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-default-devel-debuginfo' op='==' version='1' release='2' />
+ </provides>
+</package>
+
+<package>
+ <name>kernel-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>noarch</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-devel' op='==' version='1' release='2' />
+ </provides>
+ <requires>
+ <dep name='kernel-macros' />
+ </requires>
+</package>
+
+<package>
+ <name>kernel-syms</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-syms' op='==' version='1' release='2' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='2' />
+ <dep name='kernel-default-devel' op='==' version='1' release='2' />
+ </requires>
+</package>
+<!-- END KERNEL SET -->
+
+<!-- START KERNEL SET -->
+<package>
+ <name>kernel-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>5</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-1-5' />
+ <dep name='kernel' op='==' version='1' release='5' />
+ <dep name='kernel-uname-r' op='==' version='1-5' release='default' />
+ <dep name='ksym(foobar)' op='==' version='abdcfee' />
+ </provides>
+ <recommends>
+ <dep name='kernel-firmware' />
+ </recommends>
+</package>
+
+<package>
+ <name>kernel-default-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>5</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-devel' op='==' version='1' release='5' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='5' />
+ </requires>
+ <supplements>
+ <dep name='packageand(kernel-default:kernel-devel)' />
+ </supplements>
+</package>
+
+<package>
+ <name>kernel-default-devel-debuginfo</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>5</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-default-devel-debuginfo' op='==' version='1' release='5' />
+ </provides>
+</package>
+
+<package>
+ <name>kernel-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>noarch</arch>
+ <version>1</version><release>5</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-devel' op='==' version='1' release='5' />
+ </provides>
+ <requires>
+ <dep name='kernel-macros' />
+ </requires>
+</package>
+
+<package>
+ <name>kernel-syms</name>
+ <vendor>openSUSE</vendor>
+ <buildtime>1570603549</buildtime>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>5</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-syms' op='==' version='1' release='5' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='5' />
+ <dep name='kernel-default-devel' op='==' version='1' release='5' />
+ </requires>
+</package>
+
+<package>
+ <name>dummy-kmp-default</name>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>0</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kmod(dummy)' />
+ <dep name='dummy-kmp-default' op='==' version='1' release='0' />
+ </provides>
+ <requires>
+ <dep name='kernel-default-devel'/>
+ <dep name='ksym(foobar)' op='==' version='abdcfee' />
+ </requires>
+</package>
+
+<!-- END KERNEL SET -->
+
+<!-- NEXT ARCH ____________________________________________________________________________ -->
+
+<!-- START KERNEL SET -->
+<package>
+ <name>kernel-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>i686</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-1-1' />
+ <dep name='kernel' op='==' version='1' release='1' />
+ <dep name='kernel-uname-r' op='==' version='1-1' release='default' />
+ </provides>
+ <recommends>
+ <dep name='kernel-firmware' />
+ </recommends>
+</package>
+
+<package>
+ <name>kernel-livepatch-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>i686</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-livepatch-default-1-1' />
+ </provides>
+ <requires>
+ <dep name='kernel' op='==' version='1' release='1' />
+ </requires>
+</package>
+
+<package>
+ <name>kernel-default-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>i686</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-devel' op='==' version='1' release='1' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='1' />
+ </requires>
+ <supplements>
+ <dep name='packageand(kernel-default:kernel-devel)' />
+ </supplements>
+</package>
+
+<package>
+ <name>kernel-default-devel-debuginfo</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>i686</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-default-devel-debuginfo' op='==' version='1' release='1' />
+ </provides>
+</package>
+
+<package>
+ <name>kernel-syms</name>
+ <vendor>openSUSE</vendor>
+ <buildtime>1570603549</buildtime>
+ <history>
+ <update>
+ <arch>i686</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-syms' op='==' version='1' release='1' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='1' />
+ <dep name='kernel-default-devel' op='==' version='1' release='1' />
+ </requires>
+</package>
+<!-- END KERNEL SET -->
+
+<!-- START KERNEL SET -->
+<package>
+ <name>kernel-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>i686</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-1-2' />
+ <dep name='kernel' op='==' version='1' release='2' />
+ <dep name='kernel-uname-r' op='==' version='1-2' release='default' />
+ </provides>
+ <recommends>
+ <dep name='kernel-firmware' />
+ </recommends>
+</package>
+
+<package>
+ <name>kernel-livepatch-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>i686</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-livepatch-default-1-2' />
+ </provides>
+ <requires>
+ <dep name='kernel' op='==' version='1' release='2' />
+ </requires>
+</package>
+
+<package>
+ <name>kernel-default-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>i686</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-devel' op='==' version='1' release='2' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='2' />
+ </requires>
+ <supplements>
+ <dep name='packageand(kernel-default:kernel-devel)' />
+ </supplements>
+</package>
+
+<package>
+ <name>kernel-default-devel-debuginfo</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>i686</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-default-devel-debuginfo' op='==' version='1' release='2' />
+ </provides>
+</package>
+
+<package>
+ <name>kernel-syms</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>i686</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-syms' op='==' version='1' release='2' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='2' />
+ <dep name='kernel-default-devel' op='==' version='1' release='2' />
+ </requires>
+</package>
+<!-- END KERNEL SET -->
+
+<!-- START KERNEL SET -->
+<package>
+ <name>kernel-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>i686</arch>
+ <version>1</version><release>5</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-1-5' />
+ <dep name='kernel' op='==' version='1' release='5' />
+ <dep name='kernel-uname-r' op='==' version='1-5' release='default' />
+ <dep name='ksym(foobar)' op='==' version='abdcfee' />
+ </provides>
+ <recommends>
+ <dep name='kernel-firmware' />
+ </recommends>
+</package>
+
+<package>
+ <name>kernel-default-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>i686</arch>
+ <version>1</version><release>5</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-devel' op='==' version='1' release='5' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='5' />
+ </requires>
+ <supplements>
+ <dep name='packageand(kernel-default:kernel-devel)' />
+ </supplements>
+</package>
+
+<package>
+ <name>kernel-default-devel-debuginfo</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>i686</arch>
+ <version>1</version><release>5</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-default-devel-debuginfo' op='==' version='1' release='5' />
+ </provides>
+</package>
+
+<package>
+ <name>kernel-syms</name>
+ <vendor>openSUSE</vendor>
+ <buildtime>1570603549</buildtime>
+ <history>
+ <update>
+ <arch>i686</arch>
+ <version>1</version><release>5</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-syms' op='==' version='1' release='5' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='5' />
+ <dep name='kernel-default-devel' op='==' version='1' release='5' />
+ </requires>
+</package>
+
+<package>
+ <name>dummy-kmp-default</name>
+ <history>
+ <update>
+ <arch>i686</arch>
+ <version>1</version><release>0</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kmod(dummy)' />
+ <dep name='dummy-kmp-default' op='==' version='1' release='0' />
+ </provides>
+ <requires>
+ <dep name='kernel-default-devel'/>
+ <dep name='ksym(foobar)' op='==' version='abdcfee' />
+ </requires>
+</package>
+
+<!-- END KERNEL SET -->
+
+<!-- NEXT ARCH ____________________________________________________________________________ -->
+
+<!-- START KERNEL SET -->
+<package>
+ <name>kernel-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>aarch64</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-1-1' />
+ <dep name='kernel' op='==' version='1' release='1' />
+ <dep name='kernel-uname-r' op='==' version='1-1' release='default' />
+ </provides>
+ <recommends>
+ <dep name='kernel-firmware' />
+ </recommends>
+</package>
+
+<package>
+ <name>kernel-livepatch-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>aarch64</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-livepatch-default-1-1' />
+ </provides>
+ <requires>
+ <dep name='kernel' op='==' version='1' release='1' />
+ </requires>
+</package>
+
+<package>
+ <name>kernel-default-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>aarch64</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-devel' op='==' version='1' release='1' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='1' />
+ </requires>
+ <supplements>
+ <dep name='packageand(kernel-default:kernel-devel)' />
+ </supplements>
+</package>
+
+<package>
+ <name>kernel-default-devel-debuginfo</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>aarch64</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-default-devel-debuginfo' op='==' version='1' release='1' />
+ </provides>
+</package>
+
+<package>
+ <name>kernel-syms</name>
+ <vendor>openSUSE</vendor>
+ <buildtime>1570603549</buildtime>
+ <history>
+ <update>
+ <arch>aarch64</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-syms' op='==' version='1' release='1' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='1' />
+ <dep name='kernel-default-devel' op='==' version='1' release='1' />
+ </requires>
+</package>
+<!-- END KERNEL SET -->
+
+<!-- START KERNEL SET -->
+<package>
+ <name>kernel-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>aarch64</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-1-2' />
+ <dep name='kernel' op='==' version='1' release='2' />
+ <dep name='kernel-uname-r' op='==' version='1-2' release='default' />
+ </provides>
+ <recommends>
+ <dep name='kernel-firmware' />
+ </recommends>
+</package>
+
+<package>
+ <name>kernel-livepatch-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>aarch64</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-livepatch-default-1-2' />
+ </provides>
+ <requires>
+ <dep name='kernel' op='==' version='1' release='2' />
+ </requires>
+</package>
+
+<package>
+ <name>kernel-default-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>aarch64</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-devel' op='==' version='1' release='2' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='2' />
+ </requires>
+ <supplements>
+ <dep name='packageand(kernel-default:kernel-devel)' />
+ </supplements>
+</package>
+
+<package>
+ <name>kernel-default-devel-debuginfo</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>aarch64</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-default-devel-debuginfo' op='==' version='1' release='2' />
+ </provides>
+</package>
+
+<package>
+ <name>kernel-syms</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>aarch64</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-syms' op='==' version='1' release='2' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='2' />
+ <dep name='kernel-default-devel' op='==' version='1' release='2' />
+ </requires>
+</package>
+<!-- END KERNEL SET -->
+
+<!-- START KERNEL SET -->
+<package>
+ <name>kernel-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>aarch64</arch>
+ <version>1</version><release>5</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-1-5' />
+ <dep name='kernel' op='==' version='1' release='5' />
+ <dep name='kernel-uname-r' op='==' version='1-5' release='default' />
+ <dep name='ksym(foobar)' op='==' version='abdcfee' />
+ </provides>
+ <recommends>
+ <dep name='kernel-firmware' />
+ </recommends>
+</package>
+
+<package>
+ <name>kernel-default-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>aarch64</arch>
+ <version>1</version><release>5</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-devel' op='==' version='1' release='5' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='5' />
+ </requires>
+ <supplements>
+ <dep name='packageand(kernel-default:kernel-devel)' />
+ </supplements>
+</package>
+
+<package>
+ <name>kernel-default-devel-debuginfo</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>aarch64</arch>
+ <version>1</version><release>5</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-default-devel-debuginfo' op='==' version='1' release='5' />
+ </provides>
+</package>
+
+<package>
+ <name>kernel-syms</name>
+ <vendor>openSUSE</vendor>
+ <buildtime>1570603549</buildtime>
+ <history>
+ <update>
+ <arch>aarch64</arch>
+ <version>1</version><release>5</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-syms' op='==' version='1' release='5' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='5' />
+ <dep name='kernel-default-devel' op='==' version='1' release='5' />
+ </requires>
+</package>
+
+<package>
+ <name>dummy-kmp-default</name>
+ <history>
+ <update>
+ <arch>aarch64</arch>
+ <version>1</version><release>0</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kmod(dummy)' />
+ <dep name='dummy-kmp-default' op='==' version='1' release='0' />
+ </provides>
+ <requires>
+ <dep name='kernel-default-devel'/>
+ <dep name='ksym(foobar)' op='==' version='abdcfee' />
+ </requires>
+</package>
+
+<!-- END KERNEL SET -->
+
+
+</channel></subchannel>
--- /dev/null
+<?xml version="1.0"?>
+<test>
+<setup arch="x86_64">
+ <system file="solver-system.xml"/>
+ <locale name="en_US" />
+ <locale name="de" />
+</setup>
+</test>
--- /dev/null
+<channel><subchannel>
+<package>
+ <name>glibc</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='glibc' op='==' version='1' release='1' />
+ </provides>
+</package>
+
+<package>
+ <name>kernel-firmware</name>
+ <provides>
+ <dep name='kernel-firmware' op='==' version='20190312' release='lp151.2.3.1' />
+ </provides>
+</package>
+
+<package>
+ <name>kernel-macros</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>noarch</arch>
+ <version>1</version><release>0</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-subpackage-macros' />
+ <dep name='kernel-macros' op='==' version='1' release='0' />
+ </provides>
+</package>
+
+<!-- START KERNEL SET -->
+<package>
+ <name>kernel-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-1-1' />
+ <dep name='kernel' op='==' version='1' release='1' />
+ <dep name='kernel-uname-r' op='==' version='1-1' release='default' />
+ </provides>
+ <recommends>
+ <dep name='kernel-firmware' />
+ </recommends>
+</package>
+
+<package>
+ <name>kernel-livepatch-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-livepatch-default-1-1' />
+ </provides>
+ <requires>
+ <dep name='kernel' op='==' version='1' release='1' />
+ </requires>
+</package>
+
+<package>
+ <name>kernel-default-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-devel' op='==' version='1' release='1' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='1' />
+ </requires>
+ <supplements>
+ <dep name='packageand(kernel-default:kernel-devel)' />
+ </supplements>
+</package>
+
+<package>
+ <name>kernel-default-devel-debuginfo</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-default-devel-debuginfo' op='==' version='1' release='1' />
+ </provides>
+</package>
+
+<package>
+ <name>kernel-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>noarch</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-devel' op='==' version='1' release='1' />
+ </provides>
+ <requires>
+ <dep name='kernel-macros' />
+ </requires>
+</package>
+
+<package>
+ <name>kernel-source</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>noarch</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-source' op='==' version='1' release='1' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='1' />
+ </requires>
+</package>
+
+<package>
+ <name>kernel-syms</name>
+ <vendor>openSUSE</vendor>
+ <buildtime>1570603549</buildtime>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-syms' op='==' version='1' release='1' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='1' />
+ <dep name='kernel-default-devel' op='==' version='1' release='1' />
+ </requires>
+</package>
+<!-- END KERNEL SET -->
+
+<!-- START KERNEL SET -->
+<package>
+ <name>kernel-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-1-2' />
+ <dep name='kernel' op='==' version='1' release='2' />
+ <dep name='kernel-uname-r' op='==' version='1-2' release='default' />
+ </provides>
+ <recommends>
+ <dep name='kernel-firmware' />
+ </recommends>
+</package>
+
+<package>
+ <name>kernel-livepatch-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-livepatch-default-1-2' />
+ </provides>
+ <requires>
+ <dep name='kernel' op='==' version='1' release='2' />
+ </requires>
+</package>
+
+<package>
+ <name>kernel-default-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-devel' op='==' version='1' release='2' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='2' />
+ </requires>
+ <supplements>
+ <dep name='packageand(kernel-default:kernel-devel)' />
+ </supplements>
+</package>
+
+<package>
+ <name>kernel-default-devel-debuginfo</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-default-devel-debuginfo' op='==' version='1' release='2' />
+ </provides>
+</package>
+
+<package>
+ <name>kernel-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>noarch</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-devel' op='==' version='1' release='2' />
+ </provides>
+ <requires>
+ <dep name='kernel-macros' />
+ </requires>
+</package>
+
+<package>
+ <name>kernel-syms</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-syms' op='==' version='1' release='2' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='2' />
+ <dep name='kernel-default-devel' op='==' version='1' release='2' />
+ </requires>
+</package>
+<!-- END KERNEL SET -->
+
+<!-- START KERNEL SET -->
+<package>
+ <name>kernel-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>3</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-1-3' />
+ <dep name='kernel' op='==' version='1' release='3' />
+ <dep name='kernel-uname-r' op='==' version='1-3' release='default' />
+ </provides>
+ <recommends>
+ <dep name='kernel-firmware' />
+ </recommends>
+</package>
+
+<package>
+ <name>kernel-default-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>3</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-devel' op='==' version='1' release='3' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='3' />
+ </requires>
+ <supplements>
+ <dep name='packageand(kernel-default:kernel-devel)' />
+ </supplements>
+</package>
+
+<package>
+ <name>kernel-default-devel-debuginfo</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>3</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-default-devel-debuginfo' op='==' version='1' release='3' />
+ </provides>
+</package>
+
+<package>
+ <name>kernel-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>noarch</arch>
+ <version>1</version><release>3</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-devel' op='==' version='1' release='3' />
+ </provides>
+ <requires>
+ <dep name='kernel-macros' />
+ </requires>
+</package>
+
+<package>
+ <name>kernel-syms</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>3</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-syms' op='==' version='1' release='3' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='3' />
+ <dep name='kernel-default-devel' op='==' version='1' release='3' />
+ </requires>
+</package>
+<!-- END KERNEL SET -->
+
+<!-- START KERNEL SET -->
+<package>
+ <name>kernel-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>4</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-1-4' />
+ <dep name='kernel' op='==' version='1' release='4' />
+ <dep name='kernel-uname-r' op='==' version='1-4' release='default' />
+ </provides>
+ <recommends>
+ <dep name='kernel-firmware' />
+ </recommends>
+</package>
+
+<package>
+ <name>kernel-default-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>4</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-devel' op='==' version='1' release='4' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='4' />
+ </requires>
+ <supplements>
+ <dep name='packageand(kernel-default:kernel-devel)' />
+ </supplements>
+</package>
+
+<package>
+ <name>kernel-default-devel-debuginfo</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>4</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-default-devel-debuginfo' op='==' version='1' release='4' />
+ </provides>
+</package>
+
+<package>
+ <name>kernel-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>noarch</arch>
+ <version>1</version><release>4</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-devel' op='==' version='1' release='4' />
+ </provides>
+ <requires>
+ <dep name='kernel-macros' />
+ </requires>
+</package>
+
+<package>
+ <name>kernel-syms</name>
+ <vendor>openSUSE</vendor>
+ <buildtime>1570603549</buildtime>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>4</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-syms' op='==' version='1' release='4' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='4' />
+ <dep name='kernel-default-devel' op='==' version='1' release='4' />
+ </requires>
+</package>
+<!-- END KERNEL SET -->
+
+<!-- START KERNEL SET -->
+<package>
+ <name>kernel-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>5</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-1-5' />
+ <dep name='kernel' op='==' version='1' release='5' />
+ <dep name='kernel-uname-r' op='==' version='1-5' release='default' />
+ <dep name='ksym(foobar)' op='==' version='abdcfee' />
+ </provides>
+ <recommends>
+ <dep name='kernel-firmware' />
+ </recommends>
+</package>
+
+<package>
+ <name>kernel-default-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>5</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-devel' op='==' version='1' release='5' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='5' />
+ </requires>
+ <supplements>
+ <dep name='packageand(kernel-default:kernel-devel)' />
+ </supplements>
+</package>
+
+<package>
+ <name>kernel-default-devel-debuginfo</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>5</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-default-devel-debuginfo' op='==' version='1' release='5' />
+ </provides>
+</package>
+
+<package>
+ <name>kernel-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>noarch</arch>
+ <version>1</version><release>5</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-devel' op='==' version='1' release='5' />
+ </provides>
+ <requires>
+ <dep name='kernel-macros' />
+ </requires>
+</package>
+
+<package>
+ <name>kernel-syms</name>
+ <vendor>openSUSE</vendor>
+ <buildtime>1570603549</buildtime>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>5</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-syms' op='==' version='1' release='5' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='5' />
+ <dep name='kernel-default-devel' op='==' version='1' release='5' />
+ </requires>
+</package>
+
+<package>
+ <name>dummy-kmp-default</name>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>0</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kmod(dummy)' />
+ <dep name='dummy-kmp-default' op='==' version='1' release='0' />
+ </provides>
+ <requires>
+ <dep name='kernel-default-devel'/>
+ <dep name='ksym(foobar)' op='==' version='abdcfee' />
+ </requires>
+</package>
+
+<!-- END KERNEL SET -->
+
+
+</channel></subchannel>
--- /dev/null
+<?xml version="1.0"?>
+<test>
+<setup arch="x86_64">
+ <system file="solver-system.xml"/>
+ <locale name="en_US" />
+ <locale name="de" />
+</setup>
+</test>
--- /dev/null
+<channel><subchannel>
+<package>
+ <name>glibc</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='glibc' op='==' version='1' release='1' />
+ </provides>
+</package>
+
+<package>
+ <name>kernel-firmware</name>
+ <provides>
+ <dep name='kernel-firmware' op='==' version='20190312' release='lp151.2.3.1' />
+ </provides>
+</package>
+
+<package>
+ <name>kernel-macros</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>noarch</arch>
+ <version>1</version><release>0</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-subpackage-macros' />
+ <dep name='kernel-macros' op='==' version='1' release='0' />
+ </provides>
+</package>
+
+<!-- START KERNEL SET -->
+<package>
+ <name>kernel-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-1-1' />
+ <dep name='kernel' op='==' version='1' release='1' />
+ <dep name='kernel-uname-r' op='==' version='1-1' release='default' />
+ </provides>
+ <recommends>
+ <dep name='kernel-firmware' />
+ </recommends>
+</package>
+
+<package>
+ <name>kernel-livepatch-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-livepatch-default-1-1' />
+ </provides>
+ <requires>
+ <dep name='kernel' op='==' version='1' release='1' />
+ </requires>
+</package>
+
+<!-- random package depending on a specific kernel version, this should block the kernel from being purged -->
+<package>
+ <name>foo</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='foo' op='==' version='1' release='1' />
+ </provides>
+ <requires>
+ <dep name='kernel' op='==' version='1' release='1' />
+ </requires>
+</package>
+
+<package>
+ <name>kernel-default-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-devel' op='==' version='1' release='1' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='1' />
+ </requires>
+ <supplements>
+ <dep name='packageand(kernel-default:kernel-devel)' />
+ </supplements>
+</package>
+
+<package>
+ <name>kernel-default-devel-debuginfo</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-default-devel-debuginfo' op='==' version='1' release='1' />
+ </provides>
+</package>
+
+<package>
+ <name>kernel-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>noarch</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-devel' op='==' version='1' release='1' />
+ </provides>
+ <requires>
+ <dep name='kernel-macros' />
+ </requires>
+</package>
+
+<package>
+ <name>kernel-syms</name>
+ <vendor>openSUSE</vendor>
+ <buildtime>1570603549</buildtime>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>1</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-syms' op='==' version='1' release='1' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='1' />
+ <dep name='kernel-default-devel' op='==' version='1' release='1' />
+ </requires>
+</package>
+<!-- END KERNEL SET -->
+
+<!-- START KERNEL SET -->
+<package>
+ <name>kernel-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-1-2' />
+ <dep name='kernel' op='==' version='1' release='2' />
+ <dep name='kernel-uname-r' op='==' version='1-2' release='default' />
+ </provides>
+ <recommends>
+ <dep name='kernel-firmware' />
+ </recommends>
+</package>
+
+<package>
+ <name>kernel-livepatch-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-livepatch-default-1-2' />
+ </provides>
+ <requires>
+ <dep name='kernel' op='==' version='1' release='2' />
+ </requires>
+</package>
+
+<package>
+ <name>kernel-default-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-devel' op='==' version='1' release='2' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='2' />
+ </requires>
+ <supplements>
+ <dep name='packageand(kernel-default:kernel-devel)' />
+ </supplements>
+</package>
+
+<package>
+ <name>kernel-default-devel-debuginfo</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-default-devel-debuginfo' op='==' version='1' release='2' />
+ </provides>
+</package>
+
+<package>
+ <name>kernel-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>noarch</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-devel' op='==' version='1' release='2' />
+ </provides>
+ <requires>
+ <dep name='kernel-macros' />
+ </requires>
+</package>
+
+<package>
+ <name>kernel-syms</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>2</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-syms' op='==' version='1' release='2' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='2' />
+ <dep name='kernel-default-devel' op='==' version='1' release='2' />
+ </requires>
+</package>
+<!-- END KERNEL SET -->
+
+<!-- START KERNEL SET -->
+<package>
+ <name>kernel-default</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>5</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-1-5' />
+ <dep name='kernel' op='==' version='1' release='5' />
+ <dep name='kernel-uname-r' op='==' version='1-5' release='default' />
+ <dep name='ksym(foobar)' op='==' version='abdcfee' />
+ </provides>
+ <recommends>
+ <dep name='kernel-firmware' />
+ </recommends>
+</package>
+
+<package>
+ <name>kernel-default-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>5</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-default-devel' op='==' version='1' release='5' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='5' />
+ </requires>
+ <supplements>
+ <dep name='packageand(kernel-default:kernel-devel)' />
+ </supplements>
+</package>
+
+<package>
+ <name>kernel-default-devel-debuginfo</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>5</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kernel-default-devel-debuginfo' op='==' version='1' release='5' />
+ </provides>
+</package>
+
+<package>
+ <name>kernel-devel</name>
+ <vendor>openSUSE</vendor>
+ <history>
+ <update>
+ <arch>noarch</arch>
+ <version>1</version><release>5</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-devel' op='==' version='1' release='5' />
+ </provides>
+ <requires>
+ <dep name='kernel-macros' />
+ </requires>
+</package>
+
+<package>
+ <name>kernel-syms</name>
+ <vendor>openSUSE</vendor>
+ <buildtime>1570603549</buildtime>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>5</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='multiversion(kernel)' />
+ <dep name='kernel-syms' op='==' version='1' release='5' />
+ </provides>
+ <requires>
+ <dep name='kernel-devel' op='==' version='1' release='5' />
+ <dep name='kernel-default-devel' op='==' version='1' release='5' />
+ </requires>
+</package>
+
+<package>
+ <name>dummy-kmp-default</name>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>0</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='kmod(dummy)' />
+ <dep name='dummy-kmp-default' op='==' version='1' release='0' />
+ </provides>
+ <requires>
+ <dep name='kernel-default-devel'/>
+ <dep name='ksym(foobar)' op='==' version='abdcfee' />
+ </requires>
+</package>
+
+<package>
+ <name>package-needing-krnlmodule</name>
+ <history>
+ <update>
+ <arch>x86_64</arch>
+ <version>1</version><release>0</release>
+ </update>
+ </history>
+ <provides>
+ <dep name='package-needing-krnlmodule' op='==' version='1' release='0' />
+ </provides>
+ <requires>
+ <dep name='dummy-kmp-default' op='==' version='1' release='0' />
+ </requires>
+</package>
+
+<!-- END KERNEL SET -->
+
+
+</channel></subchannel>
--- /dev/null
+<?xml version="1.0"?>
+<test>
+<setup arch="x86_64">
+ <system file="solver-system.xml"/>
+ <locale name="en_US" />
+ <locale name="de" />
+</setup>
+</test>
return exit_r;
}
+#define COL_R "\033[0;31m"
+#define COL_G "\033[0;32m"
+#define COL_B "\033[0;34m"
+#define COL_C "\033[0;36m"
+#define COL_M "\033[0;35m"
+#define COL_Y "\033[0;33m"
+#define COL_BL "\033[0;30m"
+#define COL_WH "\033[1;37m"
+#define COL_OFF "\033[0m"
+
+std::string colorId( sat::Solvable solv_r )
+{
+ // return solv_r.asString();
+ std::string ret;
+ if ( solv_r )
+ {
+ static str::Format fmt { COL_B "%s" COL_OFF "-" COL_G "%s" COL_OFF ".%s" };
+ ret = fmt % solv_r.name() % solv_r.edition() % solv_r.arch();
+ }
+ else
+ {
+ ret = ( solv_r.id() == sat::detail::systemSolvableId ? "systemSolvable" : "noSolvable" );
+ }
+ return ret;
+}
+
void tableOut( const std::string & s1 = std::string(),
const std::string & s2 = std::string(),
const std::string & s3 = std::string(),
{
if ( (*argv)[0] == '-' )
{
- switch ( (*argv)[1] )
+ for ( const char * arg = (*argv)+1; *arg != '\0'; ++arg ) // -pr for -p -r
{
- case 'a': names = true, requires = provides = true; break;
- case 'A': names = true, requires = provides = false; break;
- case 'D':
- if ( argc > 1 )
- {
- --argc,++argv;
- dDump( *argv );
- }
- else
- return errexit("-D <pkgspec> requires an argument.");
- break;
- case 'i': ignorecase = true; break;
- case 'I': ignorecase = false; break;
- case 'x': matechexact = true; break;
- case 'n': names = true; break;
- case 'N': names = false; break;
- case 'r': requires = true; break;
- case 'R': requires = false; break;
- case 'p': provides = true; break;
- case 'P': provides = false; break;
- case 'c': conflicts = true; break;
- case 'C': conflicts = false; break;
- case 'o': obsoletes = true; break;
- case 'O': obsoletes = false; break;
- case 'm': recommends = true; break;
- case 'M': recommends = false; break;
- case 's': supplements = true; break;
- case 'S': supplements = false; break;
- case 'e': enhacements = true; break;
- case 'E': enhacements = false; break;
+ switch ( *arg )
+ {
+ case 'a': names = true, requires = provides = true; break;
+ case 'A': names = true, requires = provides = false; break;
+ case 'D':
+ if ( argc > 1 )
+ {
+ --argc,++argv;
+ dDump( *argv );
+ }
+ else
+ return errexit("-D <pkgspec> requires an argument.");
+ break;
+ case 'i': ignorecase = true; break;
+ case 'I': ignorecase = false; break;
+ case 'x': matechexact = true; break;
+ case 'n': names = true; break;
+ case 'N': names = false; break;
+ case 'r': requires = true; break;
+ case 'R': requires = false; break;
+ case 'p': provides = true; break;
+ case 'P': provides = false; break;
+ case 'c': conflicts = true; break;
+ case 'C': conflicts = false; break;
+ case 'o': obsoletes = true; break;
+ case 'O': obsoletes = false; break;
+ case 'm': recommends = true; break;
+ case 'M': recommends = false; break;
+ case 's': supplements = true; break;
+ case 'S': supplements = false; break;
+ case 'e': enhacements = true; break;
+ case 'E': enhacements = false; break;
+ }
}
continue;
}
if ( it->isKind( ResKind::srcpackage ) && !withSrcPackages )
continue;
- tableOut( str::numstring( it->id() ), it->asString(),
+ tableOut( str::numstring( it->id() ), colorId(*it),
str::form( "(%d)%s", it->repository().info().priority(), it->repository().name().c_str() ),
str::numstring( PoolItem(*it)->buildtime() ) );
tableOut( "", "",
ProgressData.cc
ProvideFilePolicy.cc
PublicKey.cc
+ PurgeKernels.cc
Range.cc
Rel.cc
RepoInfo.cc
ProgressData.h
ProvideFilePolicy.h
PublicKey.h
+ PurgeKernels.h
Range.h
RelCompare.h
Rel.h
{
return xmlout::node( str, name_r, {
{ "time_t", Date::ValueType(obj) },
- { "text", obj.printISO() },
+ { "text", obj.printISO( Date::TB_UTC ) },
} );
}
--- /dev/null
+/*---------------------------------------------------------------------\
+| ____ _ __ __ ___ |
+| |__ / \ / / . \ . \ |
+| / / \ V /| _/ _/ |
+| / /__ | | | | | | |
+| /_____||_| |_| |_| |
+| |
+\---------------------------------------------------------------------*/
+/** \file zypp/PurgeKernels.cc
+ *
+*/
+
+#include "zypp/base/String.h"
+#include "zypp/base/Logger.h"
+#include "zypp/base/Regex.h"
+#include "zypp/ui/Selectable.h"
+#include "zypp/PurgeKernels.h"
+#include "zypp/PoolQuery.h"
+#include "zypp/ResPool.h"
+#include "zypp/Resolver.h"
+#include "zypp/Filter.h"
+#include "zypp/ZConfig.h"
+
+#include <iostream>
+#include <fstream>
+#include <map>
+#include <unordered_map>
+#include <sys/utsname.h>
+
+#undef ZYPP_BASE_LOGGER_LOGGROUP
+#define ZYPP_BASE_LOGGER_LOGGROUP "PurgeKernels"
+
+namespace zypp {
+
+ struct PurgeKernels::Impl {
+
+ Impl() {
+ struct utsname unameData;
+ if ( uname( &unameData) == 0 ) {
+ _kernelArch = Arch( unameData.machine );
+ _uname_r = std::string( unameData.release );
+ }
+ }
+
+ bool removePackageAndCheck( PoolItem &item, const str::regex &validRemovals ) const;
+ void parseKeepSpec();
+ void fillKeepList( const std::unordered_map< std::string, std::map< Arch, std::map<Edition, sat::Solvable> > > &installedKernels, std::set<sat::Solvable::IdType> &list ) const;
+ void cleanDevelAndSrcPackages ( const str::regex &validRemovals, std::set<Edition> &validEditions, const std::string &flavour = std::string() );
+
+ static std::string detectRunningKernel() {
+
+ std::string kernelVersion;
+ std::ifstream procKernel( "/proc/sys/kernel/osrelease" );
+ if ( procKernel ) {
+ std::getline( procKernel, kernelVersion );
+ }
+ return kernelVersion;
+
+ }
+
+
+ std::set<size_t> _keepLatestOffsets = { 0 };
+ std::set<size_t> _keepOldestOffsets;
+ std::set<Edition> _keepSpecificEditions;
+ std::string _uname_r;
+ Arch _kernelArch;
+ std::string _keepSpec = ZConfig::instance().multiversionKernels();
+ bool _keepRunning = true;
+ };
+
+ /*!
+ * tries to remove a the \ref PoolItem \a pi from the pool, solves and checks if no unexpected packages are removed due to the \a validRemovals regex.
+ * If the constraint fails the changes are reverted and \a false is returned.
+ */
+ bool PurgeKernels::Impl::removePackageAndCheck( PoolItem &pi, const str::regex &validRemovals ) const
+ {
+ const filter::ByStatus toBeUninstalledFilter( &ResStatus::isToBeUninstalled );
+ auto pool = ResPool::instance();
+
+ //remember which packages are already marked for removal, we do not need to check them again
+ std::set< sat::Solvable::IdType> currentSetOfRemovals;
+ for ( auto it = pool.byStatusBegin( toBeUninstalledFilter ); it != pool.byStatusEnd( toBeUninstalledFilter ); it++ )
+ currentSetOfRemovals.insert( it->id() );
+
+ pi.status().setToBeUninstalled( ResStatus::USER );
+
+ if ( !pool.resolver().resolvePool() ) {
+ MIL << "Failed to resolve pool, skipping " << pi << std::endl;
+ pool.resolver().problems();
+ pi.statusReset();
+
+ return false;
+ }
+
+ for ( auto it = pool.byStatusBegin( toBeUninstalledFilter ); it != pool.byStatusEnd( toBeUninstalledFilter ); it++ ) {
+
+ //this was set by us or marked by a previous removal, ignore them
+ if ( it->status().isByUser() || (currentSetOfRemovals.find( it->id() ) != currentSetOfRemovals.end()) )
+ continue;
+
+ str::smatch what;
+ if ( !str::regex_match( it->name(), what, validRemovals) ) {
+ MIL << "Package " << PoolItem(*it) << " should not be removed, skipping " << pi << std::endl;
+ pi.statusReset();
+ return false;
+ }
+ }
+
+ MIL << "Removing package: " << pi << std::endl;
+ return true;
+ }
+
+ /*!
+ * Parse the config line keep spec that tells us which kernels should be kept
+ */
+ void PurgeKernels::Impl::parseKeepSpec( )
+ {
+ //keep spec parse regex, make sure to edit the group offsets if changing this regex
+ const str::regex specRegex( "^(latest|oldest)([+-][0-9]+)?$", str::regex::match_extended );
+
+ const unsigned tokenGrp = 1; //index of the group matching the token
+ const unsigned modifierGrp = 2; //index of the group matching the offset modifier
+
+
+ MIL << "Parsing keep spec: " << _keepSpec << std::endl;
+
+ std::vector<std::string> words;
+ str::split( _keepSpec, std::back_inserter(words), ",", str::TRIM );
+ if ( words.empty() ) {
+ WAR << "Invalid keep spec: " << _keepSpec << " using default latest,running." << std::endl;
+ return;
+ }
+
+ _keepRunning = false;
+ _keepLatestOffsets.clear();
+ _keepOldestOffsets.clear();
+
+ for ( const std::string &word : words ) {
+ if ( word == "running" ) {
+ _keepRunning = true;
+ } else {
+ str::smatch what;
+ if ( !str::regex_match( word, what, specRegex ) ) {
+ _keepSpecificEditions.insert( Edition(word) );
+ continue;
+ }
+
+ auto addKeepOff = []( const auto &off, auto &set, const auto &constraint ){
+ const off_t num = off.empty() ? 0 : str::strtonum<off_t>( off );
+ if ( !constraint(num) ) return false;
+ set.insert( static_cast<size_t>(std::abs(num)) );
+ return true;
+ };
+
+ if ( what[tokenGrp] == "oldest" ) {
+ addKeepOff( what[modifierGrp], _keepOldestOffsets, [ &word ]( off_t num ) {
+ if ( num < 0 ) {
+ WAR << "Ignoring invalid modifier in keep spec: " << word << ", oldest supports only positive modifiers." << std::endl;
+ return false;
+ }
+ return true;
+ });
+ } else {
+ addKeepOff( what[modifierGrp], _keepLatestOffsets, [ &word ]( off_t num ) {
+ if ( num > 0 ) {
+ WAR << "Ignoring invalid modifier in keep spec: " << word << ", latest supports only negative modifiers." << std::endl;
+ return false;
+ }
+ return true;
+ });
+ }
+ }
+ }
+ }
+
+ /*!
+ * Go over the list of installed kernels and mark those as "do not remove" that match
+ * a entry in the keep spec
+ */
+ void PurgeKernels::Impl::fillKeepList( const std::unordered_map<std::string, std::map<Arch, std::map<Edition, sat::Solvable> > > &installedKernels, std::set<sat::Solvable::IdType> &list ) const
+ {
+ for ( const auto &flavourMap : installedKernels ) {
+ for ( const auto &archMap : flavourMap.second ) {
+ size_t currOff = 0; //the current "oldest" offset ( runs from map start to end )
+ size_t currROff = archMap.second.size() - 1; // the current "latest" offset ( runs from map end to start )
+ for ( const auto &kernelMap : archMap.second ) {
+
+ //if we find one of the running offsets in the keepspec, we add the kernel id the the list of packages to keep
+ if ( _keepOldestOffsets.find( currOff ) != _keepOldestOffsets.end()
+ || _keepLatestOffsets.find( currROff ) != _keepLatestOffsets.end()
+ // a kernel might be explicitely locked by version
+ || _keepSpecificEditions.find( kernelMap.second.edition() ) != _keepSpecificEditions.end() ) {
+ MIL << "Marking kernel " << kernelMap.second << " as to keep." << std::endl;
+ list.insert( kernelMap.second.id() ) ;
+ }
+
+ currOff++;
+ currROff--;
+ }
+ }
+ }
+ }
+
+ /*!
+ * This cleans up the source and devel packages tree for a specific flavour.
+ */
+ void PurgeKernels::Impl::cleanDevelAndSrcPackages(const str::regex &validRemovals, std::set<Edition> &validEditions, const std::string &flavour )
+ {
+ bool isWithFlavour = flavour.size();
+
+ if ( isWithFlavour )
+ MIL << "Trying to remove source/devel packages for flavour " << flavour << std::endl;
+ else
+ MIL << "Trying to remove global/default source/devel packages "<< std::endl;
+
+ auto withFlavour = [&isWithFlavour, &flavour]( const std::string &name ) {
+ return isWithFlavour ? name+"-"+flavour : name;
+ };
+
+ //try to remove the kernel-devel-flavour and kernel-source-flavour packages
+ PoolQuery q;
+ q.addKind( zypp::ResKind::package );
+
+ q.addAttribute( sat::SolvAttr::name, withFlavour("kernel-devel") );
+ q.addAttribute( sat::SolvAttr::name, withFlavour("kernel-source") );
+ q.setInstalledOnly();
+ q.setMatchExact();
+
+ for ( auto installedSrcPck : q ) {
+
+ if ( validEditions.find( installedSrcPck.edition() ) == validEditions.end() ) {
+ MIL << "Skipping source package " << installedSrcPck << " no corresponding kernel with the same version was installed." << std::endl;
+ continue;
+ }
+
+ //if no package providing kernel-flavour = VERSION is installed , we are free to remove the package
+ PoolQuery instKrnl;
+ instKrnl.addKind( zypp::ResKind::package );
+ instKrnl.setInstalledOnly();
+ instKrnl.setMatchExact();
+ instKrnl.addDependency( sat::SolvAttr::provides, withFlavour("kernel"), Rel::EQ, installedSrcPck.edition() );
+
+ bool found = std::any_of ( instKrnl.begin(), instKrnl.end(), []( auto it ) { return !PoolItem(it).status().isToBeUninstalled(); } );
+ if ( found ) {
+ MIL << "Skipping source package " << installedSrcPck << " binary packages with the same edition are still installed" << std::endl;
+ continue;
+ }
+
+ PoolItem pi( installedSrcPck );
+ removePackageAndCheck( pi, validRemovals );
+ }
+ }
+
+ PurgeKernels::PurgeKernels()
+ : _pimpl( new Impl() )
+ {
+
+ }
+
+ void PurgeKernels::markObsoleteKernels()
+ {
+ if ( _pimpl->_keepSpec.empty() )
+ return;
+
+ _pimpl->parseKeepSpec();
+
+ auto pool = ResPool::instance();
+ pool.resolver().setForceResolve( true ); // set allow uninstall flag
+
+ const filter::ByStatus toBeUninstalledFilter( &ResStatus::isToBeUninstalled );
+
+ //list of packages that are allowed to be removed automatically.
+ const str::regex validRemovals("(kernel-syms(-.*)?|kgraft-patch(-.*)?|kernel-livepatch(-.*)?|.*-kmp(-.*)?)");
+
+ //list of packages that are allowed to be removed automatically when uninstalling kernel-devel packages
+ const str::regex validDevelRemovals("(kernel-source(-.*)?|(kernel-syms(-.*)?)|(kernel-devel(-.*)?)|(kernel(-.*)?-devel))");
+
+ // kernel flavour regex
+ const str::regex kernelFlavourRegex("^kernel-(.*)$");
+
+ // the map of all installed kernels, grouped by Flavour -> Arch -> Version
+ std::unordered_map< std::string, std::map< Arch, std::map<Edition, sat::Solvable> > > installedKernels;
+
+ // the set of kernel package IDs that have to be kept always
+ std::set<sat::Solvable::IdType> packagesToKeep;
+
+ //collect the list of installed kernel packages
+ PoolQuery q;
+ q.addKind( zypp::ResKind::package );
+ q.addAttribute( sat::SolvAttr::provides, "kernel" );
+ q.setInstalledOnly();
+ q.setMatchExact();
+
+ MIL << "Searching for obsolete kernels." << std::endl;
+
+ for ( auto installedKernel : q ) {
+
+ MIL << "Found installed kernel " << installedKernel << std::endl;
+
+ //we can not simply skip the running kernel to make sure the keep-spec works correctly
+ if ( _pimpl->_keepRunning
+ && installedKernel.provides().matches( Capability( "kernel-uname-r", Rel::EQ, Edition( _pimpl->_uname_r ) ) )
+ && installedKernel.arch() == _pimpl->_kernelArch ) {
+ MIL << "Marking kernel " << installedKernel << " as to keep." << std::endl;
+ packagesToKeep.insert( installedKernel.id() );
+ }
+
+ str::smatch what;
+ str::regex_match( installedKernel.name(), what, kernelFlavourRegex );
+ if ( what[1].empty() ) {
+ WAR << "Could not detect kernel flavour for: " << installedKernel << " ...skipping" << std::endl;
+ continue;
+ }
+
+ const std::string flavour = what[1];
+ if ( !installedKernels.count( flavour ) )
+ installedKernels.insert( std::make_pair( flavour, std::map< Arch, std::map<Edition, sat::Solvable> > {} ) );
+
+ auto &flavourMap = installedKernels[ flavour ];
+ if ( !flavourMap.count( installedKernel.arch() ) )
+ flavourMap.insert( std::make_pair( installedKernel.arch(), std::map<Edition, sat::Solvable>{} ) );
+
+ flavourMap[ installedKernel.arch() ].insert( std::make_pair( installedKernel.edition(), installedKernel ) );
+ }
+
+ _pimpl->fillKeepList( installedKernels, packagesToKeep );
+
+
+ MIL << "Starting to remove obsolete kernels." << std::endl;
+
+
+ std::set<Edition> removedVersions;
+
+ /*
+ * If there is a KMP or livepatch depending on the package remove it as well. If
+ * there is another package depending on the kernel keep the kernel. If there is
+ * a package that depends on a KMP keep the KMP and a kernel required to use the
+ * KMP.
+ */
+ for ( const auto &flavourMap : installedKernels ) {
+
+ // collect all removed versions of this edition
+ std::set<Edition> removedFlavourVersions;
+
+ for ( const auto &archMap : flavourMap.second ) {
+ for ( const auto &kernelMap : archMap.second ) {
+ auto &installedKernel = kernelMap.second;
+
+ // if the kernel is locked by the user, its not removed automatically
+ if ( ui::asSelectable()( installedKernel )->hasLocks() )
+ continue;
+
+ // this package is in the keep spec, do not touch
+ if ( packagesToKeep.count( installedKernel.id() ) )
+ continue;
+
+ // try to remove the kernel package, check afterwards if only expected packages have been removed
+ PoolItem pi( installedKernel );
+ if ( !_pimpl->removePackageAndCheck( pi, validRemovals ) ) {
+ continue;
+ }
+
+ removedFlavourVersions.insert( installedKernel.edition() );
+
+ //lets remove the kernel-flavour-devel package too
+ PoolQuery develPckQ;
+ develPckQ.addKind( zypp::ResKind::package );
+ develPckQ.addDependency( sat::SolvAttr::name, installedKernel.name()+"-devel", Rel::EQ, installedKernel.edition() );
+ develPckQ.addDependency( sat::SolvAttr::name, installedKernel.name()+"-devel-debuginfo", Rel::EQ, installedKernel.edition() );
+ develPckQ.setInstalledOnly();
+ develPckQ.setMatchExact();
+
+ for ( auto krnlDevPck : develPckQ ) {
+
+ if ( krnlDevPck.arch() != installedKernel.arch() )
+ continue;
+
+ PoolItem devPi(krnlDevPck);
+ _pimpl->removePackageAndCheck( devPi, validDevelRemovals );
+ }
+ }
+ }
+ //try to remove the kernel-devel-flavour and kernel-source-flavour packages
+ _pimpl->cleanDevelAndSrcPackages( validDevelRemovals, removedFlavourVersions, flavourMap.first );
+ removedVersions.insert( removedFlavourVersions.begin(), removedFlavourVersions.end() );
+ }
+
+ // clean the global -devel and -source packages
+ _pimpl->cleanDevelAndSrcPackages( validDevelRemovals, removedVersions );
+ }
+
+ void PurgeKernels::setUnameR( const std::string &val )
+ {
+ _pimpl->_uname_r = val;
+ }
+
+ std::string PurgeKernels::unameR() const
+ {
+ return _pimpl->_uname_r;
+ }
+
+ void PurgeKernels::setKernelArch(const Arch &arch)
+ {
+ _pimpl->_kernelArch = arch;
+ }
+
+ Arch PurgeKernels::kernelArch() const
+ {
+ return _pimpl->_kernelArch;
+ }
+
+ void PurgeKernels::setKeepSpec( const std::string &val )
+ {
+ _pimpl->_keepSpec = val;
+ }
+
+ std::string PurgeKernels::keepSpec() const
+ {
+ return _pimpl->_keepSpec;
+ }
+
+}
--- /dev/null
+/*---------------------------------------------------------------------\
+| ____ _ __ __ ___ |
+| |__ / \ / / . \ . \ |
+| / / \ V /| _/ _/ |
+| / /__ | | | | | | |
+| /_____||_| |_| |_| |
+| |
+\---------------------------------------------------------------------*/
+/** \file zypp/PurgeKernels.h
+ *
+*/
+
+#include <zypp/PoolItem.h>
+#include <zypp/base/PtrTypes.h>
+
+namespace zypp {
+
+ namespace str {
+ class regex;
+ }
+
+ /*!
+ * Implements the logic of the "purge-kernels" command.
+ *
+ */
+ class PurgeKernels
+ {
+ public:
+ PurgeKernels();
+
+
+ /*!
+ * Marks all currently obsolete Kernels according to the keep spec.
+ * \note This will not commit the changes
+ */
+ void markObsoleteKernels();
+
+ /*!
+ * Force a specific uname to be set, only used for testing,
+ * in production the running kernel is detected.
+ */
+ void setUnameR( const std::string &val );
+ std::string unameR() const;
+
+
+ /*!
+ * Force a specific kernel arch to be set, only used for testing,
+ * in production the running kernel arch is detected.
+ */
+ void setKernelArch( const zypp::Arch &arch );
+ Arch kernelArch() const;
+
+ /*!
+ * Overrides the keep spec, the default value is read from ZConfig.
+ * The keep spec is a string of tokens seperated by ",".
+ * It only supports 3 different tokens:
+ * - "running" matches only the currently running kernel of the system
+ * - "oldest" matches the kernel version for each flavour/arch combination with the lowest edition
+ * can be modified with a positive number: oldest+n
+ * - "latest" matches the kernel version for each flavour/arch combination with the highest edition
+ * can be modified with a negative number: latest-n
+ */
+ void setKeepSpec( const std::string &val );
+ std::string keepSpec () const;
+
+ struct Impl;
+ private:
+ RW_pointer<Impl> _pimpl;
+ };
+
+}
+
{
cfg_multiversion_path = Pathname(value);
}
+ else if ( entry == "multiversion.kernels" )
+ {
+ cfg_kernel_keep_spec = value;
+ }
else if ( entry == "solver.focus" )
{
fromString( value, solver_focus );
Pathname cfg_vendor_path;
Pathname cfg_multiversion_path;
+ std::string cfg_kernel_keep_spec;
Pathname locks_file;
Pathname update_data_path;
Pathname ZConfig::pluginsPath() const
{ return _pimpl->pluginsPath.get(); }
+ string ZConfig::multiversionKernels() const
+ {
+ return _pimpl->cfg_kernel_keep_spec;
+ }
+
///////////////////////////////////////////////////////////////////
std::ostream & ZConfig::about( std::ostream & str ) const
*/
Pathname pluginsPath() const;
+ /*!
+ * Defaults to a empty string, if no keep spec is defined no kernels are removed
+ */
+ std::string multiversionKernels() const;
+
//@}
public:
class Impl;
inline typename MapKVIteratorTraits<TMap>::Value_const_iterator make_map_value_upper_bound( const TMap & map_r, const typename TMap::key_type & key_r )
{ return make_transform_iterator( map_r.upper_bound( key_r ), GetPairSecond<typename TMap::value_type>() ); }
+
+ /** Convenience to create an \ref Iterable over the container keys */
+ template<class TMap>
+ inline Iterable<typename MapKVIteratorTraits<TMap>::Key_const_iterator> make_map_key_Iterable( const TMap & map_r )
+ { return makeIterable( make_map_key_begin( map_r ), make_map_key_end( map_r ) ); }
+
+ /** Convenience to create an \ref Iterable over the container values */
+ template<class TMap>
+ inline Iterable<typename MapKVIteratorTraits<TMap>::Value_const_iterator> make_map_value_Iterable( const TMap & map_r )
+ { return makeIterable( make_map_value_begin( map_r ), make_map_value_end( map_r ) ); }
+
+
/** \class function_output_iterator
* An output iterator wrapping a unary function object; each time an
* element is written into the dereferenced iterator, it is passed as
}
///////////////////////////////////////////////////////////////////
+ /** \name Trimming whitepace.
+ * \todo optimize l/r trim.
+ */
+ //@{
+ /** To define how to trim. */
+ enum Trim {
+ NO_TRIM = 0x00,
+ L_TRIM = 0x01,
+ R_TRIM = 0x02,
+ TRIM = (L_TRIM|R_TRIM)
+ };
+
+ std::string trim( const std::string & s, const Trim trim_r = TRIM );
+ std::string trim( std::string && s, const Trim trim_r = TRIM );
+
+ inline std::string ltrim( const std::string & s )
+ { return trim( s, L_TRIM ); }
+ inline std::string ltrim( std::string && s )
+ { return trim( std::move(s), L_TRIM ); }
+
+ inline std::string rtrim( const std::string & s )
+ { return trim( s, R_TRIM ); }
+ inline std::string rtrim( std::string && s )
+ { return trim( std::move(s), R_TRIM ); }
+ //@}
+
+ ///////////////////////////////////////////////////////////////////
/** \name Split. */
//@{
/** Split \a line_r into words.
*
*/
template<class TOutputIterator>
- unsigned split( const C_Str & line_r, TOutputIterator result_r, const C_Str & sepchars_r = " \t" )
+ unsigned split( const C_Str & line_r, TOutputIterator result_r, const C_Str & sepchars_r = " \t", const Trim trim_r = NO_TRIM )
{
const char * beg = line_r;
const char * cur = beg;
while( *cur && !::strchr( sepchars_r, *cur ) )
++cur;
// build string
- *result_r = std::string( beg, cur-beg );
+ *result_r = trim( std::string( beg, cur-beg ), trim_r );
// skip sepchars
while ( *cur && ::strchr( sepchars_r, *cur ) )
++cur;
return ret;
}
+ template<class TOutputIterator>
+ unsigned split( const C_Str & line_r, TOutputIterator result_r, const Trim trim_r )
+ { return split( line_r, result_r, " \t", trim_r ); }
+
+
/** Split \a line_r into words with respect to escape delimeters.
* Any sequence of characters in \a sepchars_r is treated as
* delimiter if not inside \c "" or \c '' or escaped by \c \.
{ return ::strcasestr( str_r, val_r ); }
//@}
- ///////////////////////////////////////////////////////////////////
- /** \name Trimming whitepace.
- * \todo optimize l/r trim.
- */
- //@{
- /** To define how to trim. */
- enum Trim {
- NO_TRIM = 0x00,
- L_TRIM = 0x01,
- R_TRIM = 0x02,
- TRIM = (L_TRIM|R_TRIM)
- };
-
- std::string trim( const std::string & s, const Trim trim_r = TRIM );
- std::string trim( std::string && s, const Trim trim_r = TRIM );
-
- inline std::string ltrim( const std::string & s )
- { return trim( s, L_TRIM ); }
- inline std::string ltrim( std::string && s )
- { return trim( std::move(s), L_TRIM ); }
-
- inline std::string rtrim( const std::string & s )
- { return trim( s, R_TRIM ); }
- inline std::string rtrim( std::string && s )
- { return trim( std::move(s), R_TRIM ); }
- //@}
-
std::string stripFirstWord( std::string & line, const bool ltrim_first = true );
std::string stripLastWord( std::string & line, const bool rtrim_first = true );
{ 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) ); }
+ // bsc#1155678: We try to differ between an empty RequestedLocales
+ // and one containing 'en' (explicit or as fallback). An empty RequestedLocales
+ // should not even drag in recommended 'en' packages. So we no longer enforce
+ // 'en' being in the set.
}
return *_trackedLocaleIdsPtr;
}
queue_push( &(_jobQueue), id );
}
+ // Ad rules for retracted pathces and packages
+ {
+ static const IdString retractedToken { "retracted-patch-package()" };
+ static const IdString ptfToken { "ptf()" };
+ queue_push( &(_jobQueue), SOLVER_BLACKLIST|SOLVER_SOLVABLE_PROVIDES );
+ queue_push( &(_jobQueue), retractedToken.id() );
+ queue_push( &(_jobQueue), SOLVER_BLACKLIST|SOLVER_SOLVABLE_PROVIDES );
+ queue_push( &(_jobQueue), ptfToken.id() );
+ }
+
// Ad rules for changed requestedLocales
{
const auto & trackedLocaleIds( myPool().trackedLocaleIds() );
#include "zypp/ZYppCallbacks.h"
#include "zypp/ExternalProgram.h"
#include "zypp/target/rpm/RpmHeader.h"
+#include "zypp/target/rpm/librpmDb.h"
#include "zypp/ZConfig.h"
#include "zypp/ZYppCallbacks.h"
out << "#! " << pkg->tag_posttransprog() << endl
<< pkg->tag_posttrans() << endl;
}
- _scripts.push_back( script.path().basename() );
- MIL << "COLLECT posttrans: " << PathInfo( script.path() ) << endl;
+ _scripts.push_back( std::make_pair( script.path().basename(), pkg->tag_name() ) );
+ MIL << "COLLECT posttrans: '" << PathInfo( script.path() ) << "' for package: '" << pkg->tag_name() << "'" << endl;
//DBG << "PROG: " << pkg->tag_posttransprog() << endl;
//DBG << "SCRPT: " << pkg->tag_posttrans() << endl;
return true;
bool firstScript = true;
while ( ! _scripts.empty() )
{
- const std::string & script = _scripts.front();
+ const auto &scriptPair = _scripts.front();
+ const std::string & script = scriptPair.first;
const std::string & pkgident( script.substr( 0, script.size()-6 ) ); // strip tmp file suffix
scriptProgress.name( str::Format(_("Executing %%posttrans script '%1%'")) % pkgident );
return false;
}
- MIL << "EXECUTE posttrans: " << script << endl;
- ExternalProgram prog( (noRootScriptDir/script).asString() + " 0", ExternalProgram::Stderr_To_Stdout, false, -1, true, _root );
+ int npkgs = 0;
+ rpm::librpmDb::db_const_iterator it;
+ for ( it.findByName( scriptPair.second ); *it; ++it )
+ npkgs++;
+
+ MIL << "EXECUTE posttrans: " << script << " with argument: " << npkgs << endl;
+ ExternalProgram prog( (noRootScriptDir/script).asString() + " " +str::numstring( npkgs ), ExternalProgram::Stderr_To_Stdout, false, -1, true, _root );
str::Str collect;
for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
msg << "%posttrans scripts skipped while aborting:\n";
for ( const auto & script : _scripts )
{
- const std::string & pkgident( script.substr( 0, script.size()-6 ) ); // strip tmp file suffix
- WAR << "UNEXECUTED posttrans: " << script << endl;
+ const std::string & pkgident( script.first.substr( 0, script.first.size()-6 ) ); // strip tmp file suffix
+ WAR << "UNEXECUTED posttrans: " << script.first << endl;
msg << " " << pkgident << "\n";
}
private:
Pathname _root;
- std::list<std::string> _scripts;
+ std::list< std::pair< std::string, std::string > > _scripts;
boost::scoped_ptr<filesystem::TmpDir> _ptrTmpdir;
};