27#include <unordered_map>
28#include <sys/utsname.h>
33#undef ZYPP_BASE_LOGGER_LOGGROUP
34#define ZYPP_BASE_LOGGER_LOGGROUP "PurgeKernels"
57 using GroupMap = std::unordered_map<std::string, GroupInfo>;
74 MIL <<
"Edition variant: " <<
edVar <<
"\n";
78 MIL <<
"Failed to detect running kernel: " <<
errno << std::endl;
86 MIL <<
"Set uname " <<
uname << std::endl;
110 MIL <<
"Parsed info from uname: " << std::endl;
112 MIL <<
"Kernel Edition Variants: \n";
114 MIL <<
" " <<
var <<
"\n";
153 if ( !pool.resolver().resolvePool() ) {
154 MIL <<
"Pool failed to resolve, not doing anything" << std::endl;
158 MIL <<
"Request to remove package: " <<
pi << std::endl;
161 const str::regex validRemovals(
"(kernel-syms(-.*)?|kgraft-patch(-.*)?|kernel-(.*)-livepatch(-.*)?|kernel-livepatch(-.*)?|.*-kmp(-.*)?)");
163 if (
pi.status().isLocked() ) {
164 MIL <<
"Package " <<
pi <<
" is locked by the user, not removing." << std::endl;
176 if ( !pool.resolver().resolvePool() ) {
177 MIL <<
"Failed to resolve pool, skipping " <<
pi << std::endl;
178 pool.resolver().problems();
190 if (
p.status().isByUser()
198 MIL <<
"Package " <<
p <<
" was marked by the solver for removal." << std::endl;
205 MIL <<
"Package " <<
p <<
" is in keep spec, skipping" <<
pi << std::endl;
223 for (
const auto &
prov :
p.provides() ) {
231 MIL <<
"Package " <<
p <<
" is most likely a kmod " << std::endl;
235 MIL <<
"Package " <<
p <<
" should not be removed, skipping " <<
pi << std::endl;
242 MIL <<
"Successfully marked package: " <<
pi <<
" for removal."<<std::endl;
245 MIL <<
"Trying to remove debuginfo for: " <<
pi <<
"."<<std::endl;
252 for (
const char *
suffix : {
"-debugsource",
"-debuginfo" } ) {
256 q.setInstalledOnly();
264 MIL <<
"Found debug package for " << solvable <<
" : " <<
debugPackage << std::endl;
270 MIL <<
"Finished removing debuginfo for: " <<
pi <<
"."<<std::endl;
289 if ( matches.
size() >= 2 ) {
309 MIL <<
"Parsing keep spec: " << _keepSpec << std::endl;
311 std::vector<std::string>
words;
313 if (
words.empty() ) {
314 WAR <<
"Invalid keep spec: " << _keepSpec <<
" using default latest,running." << std::endl;
318 _keepRunning =
false;
319 _keepLatestOffsets.clear();
320 _keepOldestOffsets.clear();
322 for (
const std::string &
word :
words ) {
323 if (
word ==
"running" ) {
330 std::string_view edition(
word);
335 WAR <<
"Ignoring possible flavor postfix:'"<<
word.substr (
secondDash) <<
"' in keep spec: " <<
word << std::endl;
344 const off_t
num = off.empty() ? 0 : str::strtonum<off_t>( off );
346 set.insert(
static_cast<size_t>(std::abs(
num)) );
353 WAR <<
"Ignoring invalid modifier in keep spec: " <<
word <<
", oldest supports only positive modifiers." << std::endl;
361 WAR <<
"Ignoring invalid modifier in keep spec: " <<
word <<
", latest supports only negative modifiers." << std::endl;
384 MIL <<
"Marking package " <<
pck <<
" as to keep." << std::endl;
391 const auto &
f = std::bind( versionMatch, _1,
elem.first );
398 MIL <<
"Starting with group " <<
groupInfo.first << std::endl;
402 MIL <<
"Starting with arch " <<
archMap.first << std::endl;
411 && ( (
archMap.first == _kernelArch &&
groupInfo.second.groupFlavour == _runningKernelFlavour )
414 MIL <<
"Matching packages against running kernel "<< _runningKernelFlavour <<
"-" <<_kernelArch <<
"\nVariants:\n";
415 for (
const auto &
var : _runningKernelEditionVariants )
421 if (
it == map.end() ) {
425 MIL <<
"Running kernel " << _runningKernelFlavour <<
"-" <<_kernelArch <<
"\n";
426 for (
const auto &
var : _runningKernelEditionVariants )
427 MIL <<
" Possible Variant:" <<
var <<
"\n";
428 MIL <<
"Not installed! \n";
429 MIL <<
"NOT removing any packages for flavor "<<_runningKernelFlavour<<
"-"<<_kernelArch<<
" ."<<std::endl;
440 MIL <<
"Found possible running candidate edition: " <<
it->first << std::endl;
443 MIL <<
"Found possible more recent running candidate edition: " <<
nit->first << std::endl;
449 if (
it != map.end() ) {
458 if ( _keepOldestOffsets.find(
currOff ) != _keepOldestOffsets.end() || _keepLatestOffsets.find(
currROff ) != _keepLatestOffsets.end() ) {
468 for ( Capability prov : solv.provides() ) {
469 if ( prov.detail().name() == solv.name() && _keepSpecificEditions.count( prov.detail().ed() ) ) {
488 MIL << std::endl <<
"--------------------- Starting to mark obsolete kernels ---------------------"<<std::endl;
490 if (
_pimpl->_keepSpec.empty() ) {
491 WAR <<
"Keep spec is empty, removing nothing." << std::endl;
497 if (
_pimpl->_keepRunning && !
_pimpl->_detectedRunning ) {
498 WAR <<
"Unable to detect running kernel, but keeping the running kernel was requested. Not removing any packages." << std::endl;
503 pool.resolver().setForceResolve(
true );
525 ERR <<
"Got inconsistent type and flavour for ident this is a BUG: " << ident << std::endl
526 <<
"Original Flavour-Type: "<<
groupInfo.groupFlavour<<
"-"<<
groupInfo.groupType << std::endl
527 <<
"Competing Flavour-Type: "<<
flavour <<
"-" << type << std::endl;
575 q.setInstalledOnly();
578 MIL <<
"Searching for obsolete multiversion kernel packages." << std::endl;
585 MIL <<
"Identified as a kernel package " << std::endl;
590 if ( what[1].empty() ) {
591 WAR <<
"Could not detect flavour for: " <<
installedKrnlPck <<
" ...skipping" << std::endl;
599 if (
dash != std::string::npos ) {
611 MIL <<
"Not a kernel package, inspecting more closely " << std::endl;
616 MIL <<
"Handling package explicitly due to architecture (noarch)."<< std::endl;
628 if ( match.size() > 1 && match[1].size() )
629 flav = match[1].substr(1);
631 else if ( match.size() > 2 && match[2].size() )
632 flav = match[2].substr(1);
636 MIL <<
"Handling package explicitly due to name match."<< std::endl;
639 MIL <<
"Package not explicitly handled" << std::endl;
645 MIL <<
"Grouped packages: " << std::endl;
647 MIL <<
"\tGroup ident: "<<ident.first<<std::endl;
648 MIL <<
"\t Group type: "<<ident.second.groupType<<std::endl;
649 MIL <<
"\t Group flav: "<<ident.second.groupFlavour<<std::endl;
650 std::for_each( ident.second.archToEdMap.begin(), ident.second.archToEdMap.end(), []( const auto &arch) {
651 MIL <<
"\t\tArch: "<<arch.first<<std::endl;
652 std::for_each( arch.second.begin(), arch.second.end(), []( const auto &edition) {
653 MIL <<
"\t\t\tEdition: "<<edition.first<<std::endl;
654 std::for_each( edition.second.begin(), edition.second.end(), []( const auto &packageId) {
655 MIL <<
"\t\t\t\t "<<sat::Solvable(packageId)<<std::endl;
679 _pimpl->_kernelArch = arch;
684 return _pimpl->_kernelArch;
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Edition represents [epoch:]version[-release]
static const Edition noedition
Value representing noedition ("") This is in fact a valid Edition.
Access to the sat-pools string space.
Combining sat::Solvable and ResStatus.
std::string unameR() const
void setKeepSpec(const std::string &val)
std::string keepSpec() const
void setUnameR(const std::string &val)
RW_pointer< Impl > _pimpl
void setKernelArch(const zypp::Arch &arch)
void markObsoleteKernels()
static const ResKind package
static ResPool instance()
Singleton ctor.
bool isToBeUninstalled() const
String matching (STRING|SUBSTRING|GLOB|REGEX).
static ZConfig & instance()
Singleton ctor.
Filter solvables according to their status.
static const SolvAttr provides
A Solvable object within the sat Pool.
@ match_extended
Use POSIX Extended Regular Expression syntax when interpreting regex.
Regular expression match result.
std::string::size_type end(unsigned i) const
End index of subexpression i in match_str (or std::string::npos)
std::string::size_type begin(unsigned i) const
Begin index of subexpression i in match_str (or std::string::npos)
bool regex_match(const std::string &s, smatch &matches, const regex ®ex)
\relates regex \ingroup ZYPP_STR_REGEX \relates regex \ingroup ZYPP_STR_REGEX
unsigned split(const C_Str &line_r, TOutputIterator result_r, const C_Str &sepchars_r=" \t", const Trim trim_r=NO_TRIM)
Split line_r into words.
std::string regex_substitute(const std::string &s, const regex ®ex, const std::string &replacement, bool global=true) ZYPP_API
Replaces the matched regex with the string passed in replacement.
Easy-to use interface to the ZYPP dependency resolver.
std::map< Arch, EditionToSolvableMap > ArchToEditionMap
const Arch Arch_empty(IdString::Empty)
std::unordered_map< std::string, GroupInfo > GroupMap
std::list< sat::Solvable > SolvableList
std::map< Edition, SolvableList > EditionToSolvableMap
enum zypp::GroupInfo::GroupType groupType
ArchToEditionMap archToEdMap
GroupInfo(const GroupType type=None, std::string flav="")
static bool versionMatch(const Edition &a, const Edition &b)
std::set< Edition > _keepSpecificEditions
bool removePackageAndCheck(const sat::Solvable slv, const std::set< sat::Solvable > &keepList, const std::set< sat::Solvable > &removeList) const
std::set< Edition > _runningKernelEditionVariants
std::set< size_t > _keepLatestOffsets
void setUnameR(const std::string &uname)
std::set< size_t > _keepOldestOffsets
void fillKeepList(const GroupMap &installedKernels, std::set< sat::Solvable > &keepList, std::set< sat::Solvable > &removeList) const
Flavour _runningKernelFlavour